Files
TeslaRel410/restoration/source410/BT/MECHSUB.NOTES.md
T
CydandClaude Fable 5 9e0f045273 Mech phase 2->4: roster core complete (16 classes) + segment-walk blueprint
Records the Mech-ctor segment-walk factory (mech.cpp:1146-1330) with the full
MISLABELED ClassID->real-class map (VDATA enum names differ from the real
classes). 16 roster classes done; 7 remain for a complete walk (Reservoir,
HeatSink-bank, Searchlight, MechTech, ThermalSight, SubsystemMessageManager,
Actuator). Blueprint in MECHSUB.NOTES.md guides phase 4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:29:39 -05:00

9.8 KiB

MECHSUB — reconstruction notes (phase 2 kickoff, 2026-07-19)

Status: base-class ANALYSIS done; the reconstruction must be done FRESH against the 4.10 structure, NOT backdated from BT411 (its base class + damage model diverge). Key findings below de-risk the actual code.

MechSubsystem is the base of the ~30-class subsystem roster (sensor, gyro, torso, hud, generator, myomers, weapons…) the Mech ctor's segment-table walk instantiates. The staged MECHSUB.HPP is interface-only (one Mech *owner member, no bodies). Reconstructing the base is phase-2 step 1.

Dependencies (all survive in the 4.10 archive)

  • Subsystem (CODE/RP/MUNGA/SUBSYSTM.HPP) — the base.
  • DamageZone (CODE/RP/MUNGA/DAMAGE.HPP/.CPP) — the engine damage zone.
  • Mech__DamageZone : public DamageZone (CODE/BT/BT/MECHDMG.HPP) + the BT damage model (MechCriticalSubsystem, redirect tables, critical hits).
  • AlarmIndicator (just reconstructed, MUNGA/ALARM.HPP) — statusAlarm.

Finding 1 — the base Subsystem DECLARES the zone but does NOT create it (RESOLVED)

SUBSYSTM.HPP:181 declares DamageZone *damageZone; in the base Subsystem and its TakeDamage (SUBSYSTM.HPP:177-178) delegates damageZone->TakeDamage(damage). The base ctors ARE reconstructed — staged source410/MUNGA/SUBSYSTM.CPP (built, in munga.lib; 38 Subsystem:: syms in the map). Both base ctors set damageZone = NULL (resource ctor line 63) — the base does not allocate the zone. So the DERIVED MechSubsystem creates the Mech__DamageZone (BT411's zone-creation is structurally right here) — but the ARMOUR it seeds must follow Finding 2 (per-type streamed), not BT411's per-facing hand-seed.

Finding 2 — CRITICAL: the damage model diverged

The 4.10 base DamageZone (DAMAGE.HPP/CPP) is a per-damage-TYPE model:

  • members: defaultArmorPoints (Scalar) + damageScale[Damage::DamageTypeCount] where DamageTypeCount = 5 = {Collision, Ballistic, Explosive, Laser, Energy}.
  • TakeDamage: damageLevel += damage.damageAmount * damageScale[damage.damageType] (DAMAGE.CPP:413); the zone STREAMS its own armour (*stream >> defaultArmorPoints; *stream >> damageScale[ii], DAMAGE.CPP:335,340).

BT411's reconstruction is a per-FACING model: armorByFacing[5] (front/back/ left/right/top) + structureReference, manually seeded by MechSubsystem's resource ctor with an armour→absorption-coefficient inversion. Those field names (armour[5], structureReference) exist only in BT411's ReconDamageZone proxy — NOT in the surviving 4.10 DamageZone/Mech__DamageZone. The staged MechSubsystem__SubsystemResource (armorByFacing[5]+structureReference) was copied from BT411 and is likewise suspect for 4.10.

Consequence: BT411's MechSubsystem ctor (heat.cpp/mechsub.cpp) CANNOT be backdated verbatim — it would install a damage model the 4.10 engine's DamageZone doesn't implement, corrupting every subsystem's damage behaviour. The 4.10 MechSubsystem must let the base Subsystem + DamageZone stream ctor handle armour (per-type), not hand-seed per-facing values.

Corrected reconstruction approach (fully scoped — ready to write)

  1. Pin the base Subsystem ctor DONE (Finding 1) — staged SUBSYSTM.CPP sets damageZone = NULL; MechSubsystem creates the Mech__DamageZone.
  2. Reconstruct MechSubsystem: chain the base Subsystem, new Mech__DamageZone(this, index), add the mech-specific members (statusAlarm = AlarmIndicator, vital flag, alarmModel, criticalReference, collisionCriticalHitWeight, printSimulationState, configureActivePress) and the TakeDamage override, using the 4.10 per-type damage model — let the zone stream its own armour (defaultArmorPoints + damageScale[5]); do NOT hand-seed BT411's per-facing armorByFacing[5]/structureReference.
  3. Re-derive MechSubsystem__SubsystemResource against the 4.10 DamageZone stream format (the staged struct's per-facing fields are BT411-copied and suspect).
  4. Then the roster (GAUSS/PPC/SENSOR source + .TCP partials + decomp).

Analysis complete; step 2 is the next code to write. This worksheet is the deliverable that keeps the subsystem foundation on the 4.10 damage model rather than BT411's divergent one.

Progress + roster hierarchy findings (2026-07-19)

DONE: MechSubsystem base (MECHSUB.HPP/.CPP) and HeatableSubsystem (HEAT.HPP/.CPP) reconstructed + compile-verified. Verified vertical slice so far: Subsystem → MechSubsystem → HeatableSubsystem.

The subsystem hierarchy is DEEPER than the staged headers show. From BT411:

MechSubsystem            (done)
  └ HeatableSubsystem    (done; ctor chains MechSubsystem + ResetToInitialState
                          -> currentTemperature=300, heatLoad=0)
     └ HeatSink          (MISSING from the staged tree -- not in source410 nor
                          CODE; VDATA HeatSinkClassID=0xBC5. Must be added.)
        └ PoweredSubsystem (staged POWERSUB.HPP wrongly derives it from
                          HeatableSubsystem -- real base is HeatSink; FIX the
                          staged header. Also its ctor has embedded AlarmIndicators
                          (electricalStateAlarm 5-level, modeAlarm 3-level) and a
                          voltageSource SlotOf.)
           └ Sensor       (surviving header CODE/BT/BT/SENSOR.HPP; leaf)
           └ Generator, ... (other leaves)

PoweredSubsystem has inter-subsystem wiring — its ctor resolves a voltage source (generator) by indexing the OWNER MECH's subsystem roster (owner->GetSubsystem(res->voltageSourceIndex)), not the skeleton. So powered subsystems must be created AFTER the generator in the segment-walk order, and the Mech must expose GetSubsystemCount()/GetSubsystem(). This ordering constraint is a segment-walk (phase-4 ctor) concern; note it there.

Complete subsystem family tree (mapped 2026-07-19) + build status

MechSubsystem                         DONE (MECHSUB.HPP/.CPP)
├─ HeatableSubsystem                  DONE (HEAT)
│   └─ HeatSink                       DONE (HEAT)
│       ├─ PoweredSubsystem           DONE (POWERSUB)
│       │   ├─ Sensor                 DONE (SENSOR; interface survives in CODE)
│       │   └─ Myomers                todo (myomers.hpp)
│       ├─ Generator                  DONE (POWERSUB; source, GNRATOR.TCP partial)
│       └─ Condenser                  todo (heat.hpp)
└─ HeatWatcher  (: MechSubsystem)     todo  -- sibling branch to HeatableSubsystem
    └─ PowerWatcher (: HeatWatcher)   todo
        ├─ Torso                      todo (torso.hpp)   -- Mech sinkSourceSubsystem
        ├─ HUD                        todo (hud.hpp)     -- Mech hudSubsystem
        └─ Gyroscope                  todo (gyro.hpp)    -- Mech gyroSubsystem

Plus the WEAPON family (separate subtree): MechWeapon → {PPC, Gauss, ProjectileWeapon → Missile/…}. PPC/GAUSS source survives in CODE/BT/BT; AMMOBIN/EMITTER/MISSILE/ PROJTILE/PROJWEAP have .TCP partials; the rest decomp-only.

Pattern established (6 classes verified): each = statics (ClassDerivations(parent, "Name") + DefaultData reusing Subsystem::MessageHandlers/ AttributeIndex/StateCount), ctor chaining the parent + member init from the resource, dtor, TestClass/TestInstance/ResetToInitialState real, per-frame Simulation method + CreateStreamedSubsystem staged with Fail. Embedded alarms = AlarmIndicator(N); filters = AverageOf; owner->GetInstance() != ReplicantInstance gates the master performance install.

ROSTER CORE COMPLETE (2026-07-20) — 16 classes verified

All committed + compile-verified: MechSubsystem, HeatableSubsystem, HeatSink, HeatWatcher, PowerWatcher, PoweredSubsystem, Generator, Condenser, Sensor, Myomers, Gyroscope, HUD, Torso, MechWeapon, Emitter (+ surviving PPC/GaussRifle), ProjectileWeapon, MissileLauncher, AmmoBin. Tree links clean.

Phase-4 blueprint: the Mech-ctor segment-walk factory (mech.cpp:1146-1330)

The Mech ctor allocates subsystemArray[subsystemCount] (+GetSubsystem/Count), then loops segments (from id 2) switching on seg->classID to new <Class>(this, id, seg), caching the key ones. The VDATA ClassID enum names are MISLABELED vs the real class (BT411's mapping):

ClassID enum name REAL class built?
0xBBD CockpitClassID Condenser
0xBBE SensorClassID HeatSink bank ~ (HeatSink ; bank variant TODO)
0xBC0 CondenserClassID Reservoir TODO
0xBC1 GeneratorClassID Generator
0xBC2 PoweredSubsystemClassID PoweredSubsystem
0xBC3 MyomersClassID Sensor
0xBC4 GyroClassID Gyroscope (cache gyroSubsystem)
0xBC5 SinkSourceClassID Torso (cache sinkSourceSubsystem)
0xBC6 ActuatorClassID Myomers
0xBC8 WeaponEmitterClassID Emitter (weaponCount++)
0xBCB JumpJetClassID AmmoBin
0xBCD MechWeaponClassID ProjectileWeapon
0xBCE MissileWeaponClassID GaussRifle
0xBD0 BallisticWeaponClassID MissileLauncher
0xBD3 SubsystemMessageManagerID SubsystemMessageManager TODO
0xBD4 GaussWeaponClassID Emitter (PPC)
0xBD6 MechTechClassID HUD (cache hudSubsystem)
0xBD8 LegSubsystemClassID Searchlight (: PowerWatcher) TODO
0xBDC HeatableClassID MechTech TODO
0xBDE DisplayClassID ThermalSight (: PowerWatcher) TODO

Remaining subsystem classes for a full walk: Reservoir, HeatSink-bank variant, Searchlight, MechTech, ThermalSight, SubsystemMessageManager, Actuator (fallback). Then the Mech member layout (subsystemArray/subsystemCount + the capability chains controllable/heatable/weaponRoster/damageable + the alarms/reticle/state-indicators /SequenceControllers/NameFilter/CStrings embedded members) must be named in MECH.HPP for the ctor to set them.