Weapon Hierarchy
The key words MUST, MUST NOT, SHOULD, and MAY are used as in RFC 2119.
Weapons split three ways: data rows (every individual weapon), archetype behavior (one class per weapon type), and the shared combat spine (#157's CombatResolver). The 360 loaded weapons stay data; the archetype layer is what #56/#57 build.
The split
| Layer | Owns | Examples |
|---|---|---|
| WeaponData (resource, per weapon) | Stats (ATK/ATA/range), grind, element + level, special/PA id (#95 — the PSOBB weapon_special field pattern), model path, rarity, class restrictions | every saber, every rifle |
| Archetype class (one per type) | Combo chain (animation triple + per-motion windows from #155), hitbox preset geometry (#157 inc 3), fire mode (single/burst/spread — #57), hold/swap animations | SaberWeapon, MechgunWeapon |
| CombatResolver (shared, #157) | Damage formula, accuracy rolls (melee + projectile variants), crit bonuses (from stats + equipment) | one module |
Archetype contract
- An archetype class provides: its combo table (per step — animation, window fractions, hitbox preset, damage multiplier), its fire mode (melee archetypes: none), and its PA binding hook. Nothing else.
- Archetypes MUST NOT carry damage math — multipliers are inputs to CombatResolver, never local formulas. (The Alpha pattern of inline afford/damage checks per shop/weapon is what the ratchet now guards against.)
- A new weapon of an existing type MUST be a WeaponData row. A new archetype class MUST correspond to a genuinely new moveset (PSZ's roster: saber, sword, daggers, claws, partisan, fists / handgun, rifle, mechgun, laser, slicer / rod, wand, shield — implement as content demands, not speculatively).
- Attack-speed stats scale windows in real time (PSOBB
animation_speedsanalog) — archetypes declare window fractions; the speed scaling is shared.
Invariants
- Every hit, melee or projectile, resolves through CombatResolver — one damage door, mirroring the enemy contract's
take_damagerule. - Hitboxes only monitor inside their declared frame window (#157 inc 4); an always-on hitbox is a bug.
- Equip/class legality is data (
WeaponDatarestrictions + ClassData), checked in one shared predicate — not per-screen logic.
Testing
Per archetype: seeded unit tests for the combo window table and damage-multiplier routing; the post-build layer is the autopilot equipping that archetype in a kill_all room (extend the shops/equip smoke — it already equips a weapon).