Accessory passive-effect table Confirmed
Accessories - the game calls them "Goods" - grant passive effects: HP/MP boosts, status-nullify
guards, elemental guards, AP / encounter / loot / escape modifiers. The shape is the surprise: there is
no per-accessory effect record. The executable defines a 64-slot passive-effect index space -
one index = one effect - and equipping an item simply sets bit index in a per-character
ability bitfield. Every mechanic that honours a passive just tests its bit at the point of use, which
is also why quest items alias their purchasable twins (Mei's Pendant literally is a Life Ring,
effect-wise).
At a glance
- Magic
- none - static data in
SCUS_942.54(the game's main executable) - Where
- Name / description / scope table at
0x8007625C(file0x66A5C), 64 × 12 bytes; the index bytes ride the item-effect descriptors (+3) and equip rows (+5) - Index space
0x00..=0x3F; index = bit position in the character's ability bitfield at record+0xF4- Sentinels
0x40(equipment rows) /0x41(consumable rows) = no passive- Parser / engine
legaia_asset::accessory_passive;engine-core::accessory_passives- Confidence
- Confirmed - all appliers traced (how we know); assignments byte-verified against the curated accessory table
- Used by
- Battle formulas, Pause menu (Goods panel), Shops page
How an accessory grants its effect
The per-frame stat aggregator walks each active party member's eight equipment-slot bytes
(record +0x196) and resolves each item to an index:
kind = item_table[id].byte(+0)
if kind == 1: index = equip_bonus[sub].byte(+5)
if kind == 2: index = descriptor[sub].byte(+3)
if index < 0x40:
char[+0xF4 + (index>>5)*4] |= 1 << (index & 0x1F)
char +0xF4..+0x103is the per-character 4×u32 ability bitfield - the home of the MP-cost bits (indices0x04/0x05).- All three members' bitfields are then OR'd into a global 4×u32 mask - how party-wide passives are consumed.
- An index of
0x40or above grants nothing. In retail every equipment row carries the0x40sentinel (no equipment grants a passive) and every consumable carries0x41; only accessory and quest-item rows carry live indices.
The same gate is read by the pause menu's Goods detail panel and the description resolver to fetch the display text. The battle damage path reads the first two bitfield words directly as the defender's elemental-resist / spirit words (details under how we know).
History: the "constant 0x41 marker" reading
The descriptor +3 byte was previously documented as a "constant 0x41
('A') marker" and the equip record's +5 byte as "constant 0x40".
Both are this index space's no-passive sentinels: 0x41 on every consumable
row, 0x40 on every retail equipment row.
Passive name/description table
A static 64-record table at 0x8007625C (stride 0xC) gives each index its menu
name, effect description, and scope:
| Offset | Type | Field |
|---|---|---|
+0 | u32 | scope: 1 = party-wide (one wearer benefits the whole party), 0 = wearer-only |
+4 | u32 | pointer to the effect name string (e.g. "HP Boost 1") |
+8 | u32 | pointer to the effect description string (0x7C '|' is the line break) |
Party-wide scope is set on exactly indices 0x30..=0x37 and 0x3B..=0x3F - the
battle-end, encounter and escape modifiers.
The 64-index space
The bands, with example items (full per-index list in the source doc):
| Indices | Band | Examples |
|---|---|---|
0x00..=0x0C | percent stat boosts (HP/MP 10%/25%, ATK/DEF/SPD/INT/AGL 20%) | Life Ring, Magic Armband, Power Ring |
0x0D..=0x15 | combat behaviours (Attack ×2, Guard/Steal/Counter Attack, turn-order chains) | War God Icon, Evil God Icon, Speed Chain |
0x16..=0x1C | status-nullify guards | Cure Amulet, Wonder Amulet |
0x1D..=0x24 | elemental guards (Earth/Water/Fire/Wind/Thunder/Light/Dark + All) | Earth Jewel, Rainbow Jewel |
0x25..=0x2F | per-turn regen, AP modifiers, arts/magic/EXP boosts | Life Grail, Mettle Ring, Crimson Book |
0x30..=0x37 | party-wide battle-end / initiative / escape modifiers | Golden Book, Chicken King |
0x38..=0x3A | walk regen (HP/MP/AP) | Life Source |
0x3B..=0x3F | encounter modifiers + two display-text-only card slots | Good Luck Bell; Point/Platinum Card special-cased by id |
Quest items share indices with their purchasable twins (Mei's Pendant = Life Ring, each Egg / Talisman = the
matching Jewel) - which is what first exposed the index space. Indices 0x3E/0x3F have
populated description records, but the Point / Platinum Card rows carry the 0x41 sentinel; the
cards are special-cased by item id in the Goods panel.
Status-guard clear masks
Seven indices are status guards - the amulets that stop poison, curse, stone and the rest from sticking. The guard applier ANDs a fixed mask into the battle actor's status word per set bit, and the mask table is what pins the battle status-flag bit map:
| Index | Name | AND mask | Bits cleared | Ailment |
|---|---|---|---|---|
0x16 | Poison Guard 1 | 0xFFFE | 0x0001 | Venom |
0x17 | Poison Guard 2 | 0xFFFC | 0x0003 | Venom + Toxic |
0x18 | Rot Guard | 0xFF87 | 0x0078 | Rot (three limb bits + one unused) |
0x19 | Curse Guard | 0xEFFF | 0x1000 | Curse |
0x1A | Stone Guard | 0xFFFB | 0x0004 | Stone |
0x1B | Numb Guard | 0xFBFF | 0x0400 | Numb |
0x1C | Master Guard | 0xE380 | 0x1C7F | every ailment |
Master Guard's mask is the definition of "ailment": 0x1C7F is the union of the six above plus
0x0800, the one condition with no guard of its own. It does not clear the
AI-delegation group Rage sets - a passive, not an ailment, so a full cure leaves it standing. Bit assignments
and the HUD elements are on save-record; engine mirror
engine-vm::status_effects::display_flags.
Magnitudes and the Talisman arm
The percent boosts (0x00..=0x0C) are applied inline by the aggregator - no
magnitude table exists. Per index: +10% = base/10, +25% = base>>2, +20% =
base/5, added to the copied base and capped (HP 9999, AGL 280, others 999). Every other index is a
point-of-use flag: each consumer tests the bit where the mechanic lives - MP cost at cast time, the
steal table for Steal Attack, the guards in the damage path, encounter rate in
the field step roll, loot in the battle-end reward resolver.
A separate arm of the same aggregator watches equip slots for specific item ids (not passive indices) and grants or revokes battle spells: the five Talismans grant summon spells, and the top-tier Ra-Seru weapons grant their own. A Talisman is therefore "guard passive by index + summon by id".
Escape bits, catch-rate bit, and the spell-grant ids
- Escape. Pinned in the run roll
FUN_801E791C:0x34Escape Boost (Chicken Heart) scales the party's escape roll ×1.5;0x37Great Escape (Chicken King) forces the roll compare to a tie - assured escape, still blocked by the scripted no-escape flag, hence "non-boss". Both fold only from living wearers (battle-action). - Magic Boost (
0x2E, Ivory Book). The killing-blow Seru-absorb roll reads ability word+0xF8bit0x4000and adds a flat 30 percentage points to the monster's catch byte before the d100. - Maximum AP (
0x2A). The guard applier's second word (+0xF8bit0x400) writes0x64to the actor's+0x170gauge - how that offset is pinned as the 0..100 AP gauge. - Spell grants. Talismans
0x72..=0x76grant summon spells0x9A/0x9B/0x9C/0x9D/0x99(Palma / Mule / Horn / Jedo / Juggernaut); Ra-Seru weapons0x09/0x11/0x19grant0x9E/0x9F/0xA0. The spell-slot list is maintained atchar +0x13D.
How we know
| Function | Address | What it proves | Dump |
|---|---|---|---|
| Per-frame stat aggregator | FUN_80042558 | index resolution, bitfield write, inline percent-boost arithmetic, Talisman spell-grant arm | funcs/80042558.txt |
| Global-mask tester | FUN_800431D0 | party-wide consumption of the OR'd mask at DAT_80074358 | funcs/800431d0.txt |
| Status-guard applier | FUN_8004CE2C (body 0x8004CEF4..0x8004CFF8) | the seven AND masks; the Maximum-AP +0x170 write | funcs/8004ce2c.txt |
| Battle damage finisher | FUN_801DDB30 | words +0xF4/+0xF8 as elemental-resist ladder (bit 0x1D + element), All-Guard 3/4-scale, AP Boost spirit-fill bits | funcs/overlay_battle_action_801ddb30.txt |
| Goods detail panel | FUN_801D0F1C (menu overlay) | display-text gate on descriptor +3 < 0x40; Point Card special case | funcs/overlay_menu_801d0f1c.txt |
| Description resolver | FUN_80034250 | same gate, static side | funcs/80034250.txt |
| Escape roll | FUN_801E791C | bits 0x34/0x37 consumer semantics | funcs/overlay_*_801e791c.txt |
| Validation | accessory_passives_vs_disc, accessory_passive_real | every curated accessory effect matches its decoded index; sentinel invariants hold | disc-gated tests |
Parser: legaia_asset::accessory_passive::AccessoryPassiveTable::from_scus
(CLI asset accessory-passive <SCUS> [--json]). Engine:
engine-core::accessory_passives maps item id → index + scope;
World::refresh_party_ability_bits ports the aggregator pass,
World::party_has_ability the mask test, and
compute_battle_stats_with_passives the percent boosts with the retail clamp block.
Source of record: docs/formats/accessory-passive-table.md.