At a glance

In the game
every item use from the field menu or the battle Item command; which items are greyed out where
Magic / marker
none - a fixed table in SCUS_942.54
Lives in
SCUS VA DAT_800752C0 (file 0x65AC0), 130 × 4-byte records, ending where the spell table begins; heal amounts at 0x8007655C
Retail readers
menu-usability gate, field list builder, apply handler (how we know)
Parser
legaia_game_tables::item_effect::ItemEffectTable (from_scus, heal_amounts, restore_amount, stat_effect)
Confidence
Confirmed - Ghidra-traced readers; the parsed bytes cross-check against each item's on-disc description string

What it is and is not

The amounts are not here

This table holds class + tier + flags. "Healing Leaf restores 200 HP" is split in two: this table says (class = heal-HP, tier = 0), and the tier → 200 mapping is the separate, also-static heal-amount table. Stat-up and buff magnitudes (classes 5/6/7) are inline immediates in the apply handler.

It is the sibling of the item-name table and the spell table: the three are contiguous static data. The lookup is double-indirected - an item id resolves to a subtype byte in its name-table record, and the subtype picks a descriptor here - so many items share one descriptor, and "key items are unusable" is not a special case at all: a key item simply resolves to a descriptor with neither usability bit set.

  1. item id → subtypeitem_name_table[id].byte(+1) (item table)
  2. subtype → descriptorDAT_800752C0[subtype * 4] - class, tier, flags, passive index
  3. descriptor → amountHP / MP classes read the tier tables; stat classes use handler immediates

Record layout (4 bytes, 130 records)

FieldMeaning
classeffect class - the action-validator arm (table below)
tierper-class sub-case; heal-HP 0/1/2 = 200 / 800 / full, stat-up = which stat, arts book = the art id granted
flagspopulated / info-panel / all-party / battle-usable / field-usable bits (below)
passive-effect index0x00..=0x3F for accessory / quest-item rows (the accessory-passive table); 0x41 = no-passive sentinel on consumable rows

Flag byte (+2)

BitMeaning
0x80populated - set on every descriptor that has an effect
0x40target side is the enemy party (clear = the ally party); paired with 0x20 it selects one of four target modes - set on exactly five subtypes, the Point Card and two pairs for the summon flutes. Three consumables select them - the Point Card, the Lippian Flute (subtype 0x27, 0xC4) and the Spikefish Flute (subtype 0x28, 0xE4); the 0xC6 / 0xE6 rows (subtypes 0x23, 0x24) are selected by no consumable (see shop)
0x20all targets on the selected side (clear = one)
0x04usable from the battle item menu
0x02usable from the field item menu

The 0x40/0x20 pair is read in exactly one place: the battle Item command in FUN_801D0748 (PROT 0898) loads the flag byte at 0x801D18D8 and forks on andi 0x40 / andi 0x20 at 0x801D18E0/0x801D18E8 into phase 0x5B (one enemy), 0x5D (all enemies), 0x64 (one ally) or 0x66 (all allies). The magic arm runs the identical ladder on the spell table’s +2 byte at 0x801D1C50, and the two tables’ low nibbles agree - an item’s 0xC4 is the spell table’s “one enemy” 0x44 with the 0x80 bit added. Sweeping every image for a +2 load followed by andi 0x40 finds those two sites and nothing else; the item-info panel FUN_801D0F1C contains no andi 0x40 at all, and its slti 0x40 tests the record’s +3 passive index against the no-passive sentinel, a different field.

Healers carry 0x04 | 0x02; permanent stat-ups and field-utility items carry 0x02 only; status-cures and revive carry 0x04 only. Key items resolve to a descriptor with neither usability bit (e.g. flag 0x89), which is how the menu greys them out. The class byte is meaningful only together with the usability flags - many key items funnel to class 0 with no usability bit, so "class 0" alone is not "an HP potion".

Class byte (+0)

Class labels are validated against the on-disc item description strings:

ClassEffectExample item
0 / 1heal HP, one ally / whole partyHealing Leaf / Healing Bloom
2restore MPMagic Leaf
3 / 8cure all status / cure single statusMedicine / Antidote
4revivePhoenix
5extend action gauge (one battle)Fury Boost
6permanent stat-up (tier = which stat)Miracle Water, the Water line
7temporary stat buff (one battle, ×6/5)Power Elixir
11/12/13arts book (Fire/Wind/Thunder; tier = the art id granted)Fire Book I
14Point Card strike - reached by item 0xFE through an id test in the battle action state machine, not through a descriptorPoint Card
126/127summon fluteLippian Flute, Spikefish Flute
128 / 129field escape (dungeon) / field warp (city)Door of Light / Door of Wind
130reduce encounter rateIncense

Arts books: the tier is an art id

Classes 11/12/13 write the tier byte verbatim into a per-character learned-art list (kept sorted by id), so the tier is the art the book grants, not a book level. The character comes from the class alone - class - 11 is the roster slot (0 / 1 / 2) - and the target the menu highlights is never read, so a Fire Book always lands on the same roster slot. The field VM's grant arm 4C C7 calls the same applier with the slot plus 0xB. On disc the nine books carry tiers Fire 3/2/1, Wind 5/4/1, Thunder 3/2/1 for I/II/III, all with flag 0x83 (field use only).

Class 14: the Point Card strike, reached by item id

The class-14 arm of the apply handler takes min(points_bank, 9999) off the Point Card bank and applies it as battle damage - a strike scaling with how much the player has shopped. Decoding all 256 item records finds no item carrying class 14, but the arm is live: the battle action state machine tests for item 0xFE at 0x801E4080 and forces the selector to 0x0E at 0x801E40C0, so the Point Card itself runs it.

Heal-amount table

The literal restore amounts the apply handler reads: two contiguous u16[4] sub-tables indexed by the descriptor tier (base + tier*2); only tiers 0..=2 are read flat.

VASub-tableTier 0Tier 1Tier 2Read by
0x8007655C (file 0x66D5C)HP restore cap2008009999classes 0 / 1
0x80076564MP restore cap5020020class 2
  • Each restore is deficit-clamped (applied = min(max - current, table[tier])), so tier 2's 9999 is an effective full restore.
  • Tier 3+ HP heals do not read this table - they are character-relative, scaled off the per-character Seru-heal tables.
  • Revive (class 4) is not a flat amount: tier 0 restores max_hp×0.4 + rand()%(max_hp/8), higher tiers a full revive.

Stat-up / buff items (classes 5/6/7)

These classes read no data table - their magnitudes are inline immediates in the apply handler's case 5/6/7, so the (class, tier) → effect mapping is pinned to the disassembly while each item's (class, tier) is parsed from the descriptor. In brief: the Water line adds a flat permanent increment to one stat (tier selects which), the Elixirs multiply a battle-actor stat by 6/5 for the rest of the battle, and Fury Boost widens the action gauge. Parser: stat_effect(id) → ActionGauge / Permanent / BuffOneBattle.

Full magnitude tables (Waters, Elixirs, Fury Boost)

Class 6 - permanent stat-up (field-use, flag 0x82)

Adds a flat increment to the character record, tier selecting the stat:

TierStatRecord offsetDeltaCapItem
0Max HP+0x11C+169999Life Water (0x82)
1ATK+0x124+4999Power Water (0x83)
2DEF (both facets)+0x126 / +0x128+4999Guardian Water (0x84)
3SPD+0x12A+4999Swift Water (0x85)
4INT+0x12C+4999Wisdom Water (0x86)
5Max MP+0x11E+8999Magic Water (0x87)
6all (AGL/HP/ATK/SPD/INT/MP/DEF)-+4 eachAGL 280, HP 9999, else 999Honey (0x65), Miracle Water (0x6D)

The handler writes the base window (+0x11C..+0x12C) and nothing else. The live window follows because the menu's use routine (FUN_801D8308) calls the stat aggregator straight after it. The aggregator copies each base value over its live one, adds the equipment's percent boosts off the base (ability bit 0 a tenth of base Max HP, bit 1 a quarter, bits 2 and 3 the same two for Max MP), clamps to 9999 / 999, and lowers a current value that now exceeds its maximum. So a raised maximum is the base plus whatever boost is worn, and the gain is not refilled: current HP / MP stay where they were.

Port: World::apply_stat_up_item raises the base window and World::rebuild_record_live_hp_mp rebuilds the two maxima from it - the same rebuild World::refresh_party_ability_bits runs for every party member, so an equipment change moves the maxima with the accessory. The combat stats take the base raise and the same increment on the live value, which the battle seed re-derives from the base.

Class 7 - one-battle buff (battle-use, flag 0x84)

Multiplies the battle-actor stat halfwords by 6/5 (the handler's uVar + uVar/5), clamped to 0xFFFF, for the rest of the battle:

TierStat(s)Item
1SPD (+0x164/+0x166)Speed Elixir (0x8D)
2DEF, both facets (+0x15C/+0x15E, +0x160/+0x162)Shield Elixir (0x8C)
3ATK (+0x158/+0x15A)Power Elixir (0x8B)
4all - SPD + DEF + ATK + INT (+0x168/+0x16A)Wonder Elixir (0x8E)

Class 5 - Fury Boost (0x81) sets the actor +0x1F9 gauge flag; the action-SM gauge-build phase then sizes the gauge as gauge_stat * 7 / 5 + 8 (clamped to 0x120). See the buff-selector table on the battle-formulas page.

How we know

The readers behind each field
FunctionAddressWhat it provesDump
Menu-usability gateFUN_8003043CThe subtype → descriptor index chain; the & 0x20 all-party test selecting the all-targets validator call; an item is offered only when at least one eligible target would benefit (walks the live party calling FUN_8003fb10(class, tier, target) per member).funcs/8003043c.txt
Field list builderFUN_80030628Reads the 0x02 / 0x04 usability bits - the grey-out logic.funcs/80030628.txt
Apply handlerFUN_800402F4; HP arm 0x800404B8, MP arm 0x80040DC0, revive arm 0x80040F58The tier-table reads, deficit clamp, revive formula, and the class 5/6/7 immediates. One handler serves field menu and battle (branching on game_mode == 0x15).funcs/800402f4.txt
Jump-table callerstable at 0x80014FA0 (132 entries); callers 0x801D84B4, 0x801D9280, 0x801E40DCWhat indexes the handler depends on the caller: descriptor class (field item use), the item record's own kind byte, or the battle actor's +0x1E8.overlay dumps
Target-panel previewFUN_801D6A54Gates on kind == 2 and class == 6 before mapping tier to a preview mode - the sibling kind-byte selector.funcs/overlay_menu_801d6a54.txt
Arts-book arm0x80041FC0 (class - 0xB), 0x80042064 (sb tier at +0x74E)Tier = art id; character = class-derived roster slot; picked target unused.funcs/800402f4.txt

In the port

legaia_game_tables::item_effect::ItemEffectTable::from_scus resolves both tables from a SCUS_942.54 image; engine-menus::items::ItemCatalog installs the usability and all-party flags and seeds the stat-up, buff and Fury Boost items from it, and engine-menus::inventory_use mirrors the retail menu-usability gate (a heal greys out when nobody would benefit). Source of record: docs/formats/item-effect-table.md.

See also