# MESSMGR.CPP — SubsystemMessageManager reconstruction notes The per-mech damage/explosion hub: subsystems queue damage during a frame (`AddDamageMessage`), the Performance (`ConsolidateAndSendDamage`) folds the queue into ONE `TakeDamageStreamMessage` for the hit entity and flushes the bundled weapon explosions (`CreateWeaponExplosions`). The surviving MESSMGR.HPP (CODE/BT/BT) is authentic and untouched. ## Reconstructed 2026-08-04 (5.3.115), decomp-verified (part_012.c) - **ctor @0049bca4**: `weaponExplosions(NULL, True)` — the binary constructs the explosion chain UNIQUE-keyed (0049bfde(.., 0, 1)); the damage chain allows duplicate keys. Installs `ConsolidateAndSendDamage` as the Performance (member-pointer triple @0050b6fc); copies the two streamed resource fields (res+0x30/+0x34); zeros the common record. [T3] The binary also allocates a 0x160-byte engine-internal helper at this+0xE0 (FUN_0041de1c) — not declared in the surviving header, untouched by the reconstructed paths, STAGED until identified. - **AddDamageMessage @0049b6d8**: first hit of the frame wins each common field (entity / impact point via epsilon-against-origin / zone); every message queues a `DamageInformation` plug KEYED BY DAMAGE AMOUNT (the chain key is read back with `GetValue()` at consolidation). - **ConsolidateAndSendDamage @0049b784**: wire format pinned by the ENGINE'S OWN PARSER (`Entity::TakeDamageStreamMessageHandler`, RP ENTITY.CPP:855): a `Receiver::DynamicMessage(TakeDamageStreamMessageID == 0x13, sizeof == 0x34)` with header {impactPoint@+0x1c, damageZoneIndex@+0x28, shootingEntity@+0x2c}, then `<< count`, then `<< type << amount << subsystemID` per record. Explosion bundling reads the FIRING weapon's resource (binary: blind `roster[subsystemID]+0x3e4`); [T1] guarded here (range + IsDerivedFrom(MechWeapon)) — the binary is unguarded and relies on well-formed feeders. Dispatches the stream directly at the hit entity, flushes explosions, purges with `DeletePlugs()` (binary FUN_00417858(,1) — the explicit teardown), resets the commons. - **CreateWeaponExplosions @0049baa0**: the authentic HEADER signature (terrain_hit, entity_hit, explode_position) — the BT411 donor's "SendQueuedExplosions" rename was port drift. Per queued resource: `Explosion::MakeMessage(MakeMessageID(3), sizeof(0x5c), RegisteredClass::ExplosionClassID(0x31 — our VDATA enum ordinal matches the binary byte-for-byte), no owner, resourceID, instanceFlags 0x100, Origin{impact position, identity rotation}, entity_hit, owner mech)`, posted at `CreationEventPriority(3)` to `application->GetRegistry()` with delivery `Now() + 0.1s × n` (impacts in one frame stagger). Then purge. ## The inert terrain-hit flag (recorded, not tuned) The binary computes `terrain_hit = entityHit->IsDerivedFrom()` before calling CreateWeaponExplosions. The class at 0x4e6f54 is UNRESOLVED (BSS object; no static-ctor reference survives in the decomp parts). It does not matter: @0049baa0 NEVER READS its first argument, and `terrainHitExplosionID` is never consumed anywhere in the shipped cluster — a declared, resourced, abandoned 1995 feature. We pass `False` [T3]; shipped behavior is preserved exactly. If the constant is ever resolved (candidates: a terrain/cultural class), only the dead flag changes. ## Status / staging - `CreateStreamedSubsystem` @0049be10 remains a Fail stub — the authoring- side CSS family (8 fns) is batched separately; missions load prebuilt streams from BTL4.RES and never call it. - **No feeders yet**: nothing in source410 calls `AddDamageMessage` (the weapon damage paths still dispatch TakeDamage directly), so the consolidator runs empty every frame — verified live (5-period soak, wheel turning, no faults). When the weapon-fire damage path is rebased onto the manager, this TU is ready for it.