3 Cookbook Items And Balls
bryanthaboi edited this page 2026-10-20 17:01:40 -04:00

Cookbook: items and balls

An item record identifies what is in the bag. A shop entry makes it purchasable; an effect or ball record supplies behavior.

Setup: a working mod from Getting Started. Examples target Red/local single-player unless a recipe explicitly says otherwise. Use Modding Basics for syntax and Glossary for unfamiliar terms. Save and restart after content edits. A validation pass and an in-game checkpoint are different checks.

Where code goes: insert Lua fragments inside your existing return function(mod) ... end in main.lua. A complete-file label or named other file overrides that default. Do not paste a second entry function inside the first. Read the recipe's requirements before copying its code. For output, use Read log output; for IDs, use Find internal IDs.

Mechanism: Concepts: Registries; worked path: Tutorial 04.

R08 - Add a Mart item

Basic Lua. Before you paste: Use a Red save with money and access to Viridian Mart. This recipe both defines an item and puts it in a shop. R09 adds its use behavior.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.items:register("MODBERRY", {
  id = "MODBERRY", name = "MODBERRY", price = 250, tossable = true,
})
mod.content.text_pointers:patch("ViridianMart", {
  TEXT_VIRIDIANMART_CLERK = { mart = { __append = { "MODBERRY" } } },
})

Checkpoint: the Viridian clerk sells MODBERRY. Each shop clerk has a mart list of items to sell. __append keeps the existing shelf and adds your item. This is a deep registry, so a plain list also appends; do not use it expecting to erase the existing inventory.

Gen 2 / Gen 3: items:register works on both (an api 3 mod uses this same record and Gen 3 allocates a free item slot). text_pointers has no Gen 2 or Gen 3 target, so the shop half is dropped and reported there.

R09 - Define an item use effect

A complete R08 + R09 mod is stored in examples/cookbook/berry/: download its manifest and main.lua, or follow the two recipe insertions below/above in your own mod.

Basic Lua. Before you paste: First install R08 in the same mod so MODBERRY exists and can be purchased. This adds a field-use healing effect; use it on a living, injured party member.

Complete walkthrough / required concept.

Insert after R08 inside the same main.lua entry function.

mod.content.item_effects:register("MODBERRY_EFFECT", {
  use = function(ctx)
    local mon = ctx.target
    local max = mon and (mon.maxHp or mon.stats.hp)
    if not mon or mon.hp <= 0 or mon.hp >= max then
      return "failed", { "It had no effect." }
    end
    mon.hp = math.min(max, mon.hp + 10)
    return "consumed", { "Restored 10 HP!" }
  end,
  field = true, battle = false, needsTarget = true,
})
mod.content.items:patch("MODBERRY", { effect = "MODBERRY_EFFECT" })

Checkpoint: outside battle, use a purchased MODBERRY on a living party Pokemon missing HP. It restores up to 10 HP and uses one berry. At full HP or on a fainted Pokemon it reports no effect and keeps the berry.

ctx.target is the chosen Pokemon. mon.hp is current HP and mon.stats.hp is its maximum on Red. math.min prevents healing above the maximum. The first return value tells the bag whether to consume the item; the second is a list of messages. battle = false deliberately keeps this first effect out of the battle menu. See src/inventory/ItemEffects.lua for other results such as "kept", "ball", and "learn".

Gen 3: this record runs through the native item flow (src/core/game3/item_use.lua), honouring field, battle and needsTarget. ctx.target is the native party record, whose maximum is mon.maxHp; the mon.maxHp or mon.stats.hp read above covers both. Gen 3 accepts only "consumed", "kept" and "failed".

Gen 2: Gold's item_effects (gen2ItemEffects) are keyed by item id and called as use(ctx) with ctx.mon, returning { used, text } (src/core/gen2/ItemEffects.lua), so this record does not run there as is.

R10 - Add a new Poke Ball

Basic Lua. Before you paste: This defines the ball but does not put it in the bag or a shop. Use Tutorial04's complete shop example, adding MODBALL to its stocked items.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

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,
})

Checkpoint: thrown in battle, MODBALL catches better than an Ultra Ball (randMax 150). The fields are the real Gen 1 math (src/battle/Catching.lua); autoCatch = true is the Master Ball behavior, and attempt = fn replaces the roll outright.

Gen 2 / Gen 3: Gold routes balls to its own table (gen2Balls). Gen 3 takes a different record, { multiplier, autoCatch }, where multiplier is the ball bonus times 10 (Ultra Ball is 20), keyed by an item id that exists:

mod.content.balls:register("MODBALL", { multiplier = 25 })

An api 3 mod writes this native record too: mod:supports("content", "balls") is true on Gen 3, and the record passes through as shown. Claim gen3 in games (or branch on mod.generation) so the Gen 1 ball shape is not sent here.