-
Notifications
You must be signed in to change notification settings - Fork 2
Tutorial 04 New Item
Goal. Add an item, put it on a mart shelf, and add a new Poke Ball variant with its own catch math.
Prerequisites. Tutorial 03; Concepts: Events and Hooks.
Files created.
mods/tutorial_04_item/
├── manifest.json
└── main.lua
-
Register the item.
return function(mod) mod.content.items:register("MODBERRY", { id = "MODBERRY", name = "MODBERRY", price = 250, tossable = true, }) end
id,name,priceare the required fields. Outcome:modkit validatepasses and the item is a known id — it can sit in the bag, be tossed, be sold. -
Stock a mart. Marts are data: each shop clerk's TEXT entry in the
text_pointersdeep registry carries amartlist. Add your item to Viridian's shelf:mod.content.text_pointers:patch("ViridianMart", { TEXT_VIRIDIANMART_CLERK = { mart = { __append = { "MODBERRY" } }, }, })
Outcome: the Viridian clerk sells MODBERRY at its
price. The__appendwrapper extends the list; a bare list would replace the whole shelf. -
Register a ball. The
ballsregistry drives the catch pipeline (src/battle/Catching.lua) — vanilla's five balls are records in it, registered by the engine:mod.content.items:register("MODBALL", { id = "MODBALL", name = "MODBALL", price = 500, ball = "MODBALL", }) mod.content.balls:register("MODBALL", { randMax = 120, hpFactor = 10, wobbleFactor = 120, tossAnim = "ULTRATOSS_ANIM", flicker = true, })
The record fields are the real Gen 1 catch math (
src/battle/Catching.lua):randMaxis the ceiling of the catch roll (lower = better; Poke 255, Great 200, Ultra 150),hpFactorthe X of the HP term,wobbleFactorthe divisor of the shake math,autoCatchskips the roll entirely (Master Ball),tossAnimpicks the arc (TOSS_ANIM,GREATTOSS_ANIM,ULTRATOSS_ANIM),flickerthe Master/Ultra palette strobe, andattemptreplaces the whole roll with your function. Outcome: throwing MODBALL at a wild mon uses your numbers — better than an Ultra Ball. -
Watch it happen. Subscribe to the throw event to see the pipeline from the outside:
mod.events:on("battle.ball_thrown", function(ev) mod.log:info("%s: caught=%s shakes=%d", ev.ball, tostring(ev.caught), ev.shakes or 0) end)
Outcome: a log line per throw naming ball, outcome, and shakes.
Buy a MODBERRY and a MODBALL in Viridian; throw the MODBALL at a wild Pidgey and see the logged shake count. Disable the mod: the shelf, the items, and the catch math are vanilla again.
-
Forgetting
ball = "MODBALL"on the item. The item record'sballfield is what routes a bag throw into yourballsrecord. -
Guessing field names from other games. There is no
catchModifier; the record is Gen 1's actual math (randMax,hpFactor,wobbleFactor). Check Reference: Registries before inventing a field — unknown top-level keys are preserved but do nothing. -
Custom use-effects. The
item_effectsregistry holds use handlers ({ use = fn, field = true, battle = true, needsTarget = true }) and theitems.effectfield names one. Vanilla item behavior lives insrc/inventory/ItemEffects.lua, whose result verbs are"consumed","kept","failed","ball","learn"— match that contract in a custom handler.
Next: Tutorial 05 — New Move.
Engine 1.0.0 · mod API 2 · repository · Discord
This project ships no ROM data. All game content is decoded on the player's machine from their own verified Pokemon Red ROM; mods ship recipes and original assets, never extracted content.
Start here
Concepts
Tutorials
- The ladder
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Reference
Guides
Playing