# MECHWEAP.CPP / .HPP — reconstruction notes `MechWeapon` (: PoweredSubsystem) is the weapon base: PPC/GaussRifle bind it via Emitter, the SRMs via ProjectileWeapon/MissileLauncher. The resource streams rechargeRate / weaponRange / damage / heatCostToFire (+ pip fields). ## Reconstructed - Statics (ClassDerivations, DefaultData on Subsystem::MessageHandlers/ AttributeIndex), ctor streaming the tuning fields, damageData prime. - **View-fire gating (2026-07-21, the look-commit wave):** real `rearFiring` / `viewFireEnable` members (1995 binary @0x334/@0x3E0) + `IsRearFiring()` / `GetViewFireEnable()` / `SetViewFireEnable()`. The ctor resolves REAR-FIRING authentically (binary ctor tail @004b99a8): the mount SEGMENT site name (`owner->GetSegment(GetSegmentIndex())`) is tested for the 'b' (back) marker — only the back gun ports (`sitelbgunport`/`siterbgunport`) carry it. Spawn state = armed for the forward view. `Mech::CommitLookState` re-arms on every view change (see MECH.NOTES.md increment 7). Verified: the TEST.EGG mech's two rear lasers (ERMLaser_2/3) arm only in LOOK-BACK. ## Fire path (2026-07-21, Phase 5.3.8) - **The authentic attribute table IS published** (binary @0x511890, IDs pinned): PercentDone 0x12 → rechargeLevel, **TriggerState 0x13 → fireImpulse** (the streamed per-mech fire-button mappings bind this ID — the real trigger wiring), DistanceToTarget 0x14, TargetWithinRange 0x15, WeaponRange 0x16 → effectiveRange, EstimatedReadyTime 0x1A, RearFiring 0x1B, WeaponState 0x1C → weaponAlarm. Pads bridge our chain gap 2..0x11 (parents publish nothing yet; they shrink to the authentic 0x0F..0x11 when the mechsub/heat/powersub attribute waves land — SENSOR.HPP pins PoweredSubsystem::NextAttributeID at 0x0F). **Pads are LOAD-BEARING**: AttributeIndexSet::Build leaves uncovered gap slots as UNINITIALIZED GARBAGE (`new IndexEntry[entryCount]`, only inherited + listed entries written), so every ID up to the max must be covered or Find() on a gap ID returns a wild pointer. Pip* (0x17-0x19) are pads → rechargeLevel until the pip members are reconstructed. - **Fire state machine members**: fireImpulse/previousFireImpulse (the trigger sample pair), rechargeLevel, rangeToTarget, effectiveRange, estimatedReadyTime, recoil, weaponAlarm (the state carrier: 0 Firing / 2 Loaded / 3 Loading / 4 trigger-during-load). Spawn = charged + Loaded. - **CheckFireEdge** (@004b9608): rising-edge on fireImpulse comparing BIT PATTERNS as signed ints — TriggerState carries raw ControlsButton ints (+(button+1) press / −(button+1) release); the release bit-pattern is a negative NaN as float, and an IEEE float compare would latch the detector shut after the first release (BT411 task #8). Int compare reproduces the binary's x87 semantics exactly. - **ComputeOutputVoltage** (@004b9c9c): `rechargeLevel = (rechargeRate − recoil) / rechargeRate` — the recharge dial. - **Emitter::EmitterSimulation** (PARTIAL, @004baa88) installed on every non-replicant energy weapon: Firing → discharge countdown → ResetFiringState(Loading); Loaded + trigger edge → viewFireEnable gate → FireWeapon; Loading → recoil decays over the authored RechargeRate seconds → Loaded. Deferred within it: the leading PoweredSubsystemSimulation electrical step, the destroyed/heat-failure/dead-mech hard gates, the TrackSeekVoltage generator charge integration (the partial uses the authored seconds directly), and the HasActiveTarget gate (targeting wave). - **Emitter::FireWeapon** (PARTIAL, @004bace8): discharge bookkeeping (beam countdown re-arm, charge spent, recoil loaded). Deferred: the 0.5·V²·EC energy/damage/heat closed forms (need the electrical model), the heat dump (heat wave), the beam build + Damage submission (targeting + renderer). - Emitter's index re-chained to MechWeapon's (ChargeLevel at the authentic 0x1D past the table end); Emitter::DefaultData now binds MechWeapon::MessageHandlers. - DEV hook `BT_FORCE_FIRE=1`: pulses the trigger whenever a weapon is Loaded → every armed weapon auto-fires at its authored cadence. **VERIFIED headlessly**: forward view — PPC_1/2 + ERMLaser_1 cycle FIRED→LOADED→FIRED at the authored 0.6 s discharge / 1 s recharge, rear lasers silent; `BT_FORCE_LOOK=3` (look-behind) — ONLY ERMLaser_2/3 fire. The full view-fire × fire-FSM interlock holds in both directions. Zero Fail. (SRM6s are MissileLaunchers — the ballistic ProjectileWeaponSimulation is a later increment.) ## Still staged - The ballistic fire path (ProjectileWeaponSimulation @004bbd04, missile launch/seeker), `SendDamage` (damage/networking), `CreateStreamedSubsystem` (tool-side model build). - ~~`MechWeapon::MessageHandlers` declared but not defined~~ — **FIXED 2026-07-21**: it is now a real defined set (`(0, NULL, Subsystem::MessageHandlers)` — no own handlers yet, inherits the chain), and `MechWeapon::DefaultData` binds it. This mattered because the surviving CODE PPC.CPP binds the inherited name (`PPC::MessageHandlers`) into PPC::DefaultData, and a declared-but-undefined static links as a zero-filled common block — the same silent-NULL trap as the Emitter::AttributeIndex crash. Real weapon handlers (fire/damage messages) come with the combat wave (grow the table in place).