diff --git a/restoration/source410/BT/MECH.CPP b/restoration/source410/BT/MECH.CPP index aefc563c..dd544bbe 100644 --- a/restoration/source410/BT/MECH.CPP +++ b/restoration/source410/BT/MECH.CPP @@ -87,6 +87,9 @@ const Receiver::HandlerEntry Mech::MessageHandlerEntries[] = { MESSAGE_ENTRY(Mech, TakeDamage), + MESSAGE_ENTRY(Mech, RealMaxSpeed), + MESSAGE_ENTRY(Mech, SetBurningState), + MESSAGE_ENTRY(Mech, ClearBurningState), MESSAGE_ENTRY(Mech, DuckRequest) }; @@ -308,6 +311,9 @@ Mech::Mech( defaultStateRequests = 0; // the streamed mode-request counters gimpLeftRequests = 0; // (binary ctor @004a1674 zeroes gimpRightRequests = 0; // +0x334/+0x338/+0x33c) + realMaxSpeed = 0.0f; // the 0x15 share triplet (+0x7a0/4/8) + realMaxSpeedKnown = 0; + realMaxSpeedSent = 0; collisionVolumeState.Initialize(2); collisionVolumeState.SetLevel(1); standingVolumeHeight = 0.0f; @@ -855,6 +861,70 @@ void } } +// +//############################################################################# +// RealMaxSpeedMessageHandler -- binary @0049f604 (authentic name from the +// handler table). Adopt the streamed real max speed only while our own is +// unknown. The wire shape is the entity-stream family: 12-byte header, +// sender EntityID at +0xc (stamped by Entity's network send @0041f640), +// reserved pair, payload at +0x1c. +//############################################################################# +// +void + Mech::RealMaxSpeedMessageHandler(Receiver::Message *message) +{ + Check(this); + Check_Pointer(message); + + if (realMaxSpeedKnown == 0) + { + realMaxSpeed = *(Scalar *)((char *)message + 0x1c); + } +} + +// +//############################################################################# +// SetBurningStateMessageHandler -- binary @0049f674. The burning wreck is +// parked in a per-host off-field slot: x = localHostID x 10000, y = +// localHostID x -1000 (the data words @0049f6fc/@0049f6f8; the id read is +// HostManager::GetLocalHostID -- the accessor the entity-instance dispatch +// compares against ownerID), z untouched. The mode alarm drops to 2 -- +// BURNING, the second InDeathTransition state (its missing writer, found) +// -- the position dirty mark fires, and execution is forced back on so the +// state runs even on a DontExecute replicant. +//############################################################################# +// +void + Mech::SetBurningStateMessageHandler(Receiver::Message *message) +{ + Check(this); + + HostID + local_host = application->GetHostManager()->GetLocalHostID(); + localOrigin.linearPosition.x = (Scalar)local_host * 10000.0f; + localOrigin.linearPosition.y = (Scalar)local_host * -1000.0f; + localToWorld = localOrigin; + SetSimulationState(2); + ForceUpdate(1); + AlwaysExecute(); +} + +// +//############################################################################# +// ClearBurningStateMessageHandler -- binary @0049f700: back to +// DefaultState, dirty the position, re-arm execution. +//############################################################################# +// +void + Mech::ClearBurningStateMessageHandler(Receiver::Message *message) +{ + Check(this); + + SetSimulationState(0); + ForceUpdate(1); + AlwaysExecute(); +} + // //############################################################################# // The collision-volume swap (binaries @004ac04c / @004ac064): write the diff --git a/restoration/source410/BT/MECH.HPP b/restoration/source410/BT/MECH.HPP index d264dc67..1ff405e0 100644 --- a/restoration/source410/BT/MECH.HPP +++ b/restoration/source410/BT/MECH.HPP @@ -958,8 +958,28 @@ int gimpLeftRequests; int gimpRightRequests; + // + // The real-max-speed share (binary +0x7a0/+0x7a4/+0x7a8). +0x7a0 + // is the base every throttle command snaps to (5 notches, master + // perf head). A mech that has COMPUTED its own value (+0x7a4 set; + // that writer is still undecoded) sends it once over the wire + // (message 0x15, payload at byte 0x1c; latch +0x7a8) and ignores + // incoming shares; anyone else adopts the streamed value (handler + // @0049f604). The send rides the EntityManager stream path + // (@0041f640) -- staged with the ForceUpdate/update-record feed. + // + Scalar realMaxSpeed; + int realMaxSpeedKnown; + int realMaxSpeedSent; + void DuckRequestMessageHandler(Receiver::Message *message); + void + RealMaxSpeedMessageHandler(Receiver::Message *message); + void + SetBurningStateMessageHandler(Receiver::Message *message); + void + ClearBurningStateMessageHandler(Receiver::Message *message); void SetStandingCollisionVolume(); // binary @004ac04c... see .CPP void diff --git a/restoration/source410/BT/MECH4.NOTES.md b/restoration/source410/BT/MECH4.NOTES.md index f82b9a6a..67f2ea3d 100644 --- a/restoration/source410/BT/MECH4.NOTES.md +++ b/restoration/source410/BT/MECH4.NOTES.md @@ -282,3 +282,38 @@ advance dispatch death-guarded. SIDE EFFECT: `Mech::InDeathTransition` and the camera director's cut-away are now LIVE (mode 9 is finally written on kills) -- the director path needs a rig eyeball when a pod is back. + +## 5.3.122 -- the message roster fills (three of the six landed) + +Landed: **RealMaxSpeed** (@0049f604: adopt streamed +0x7a0 while +0x7a4 +clear; wire payload at +0x1c, sender EntityID stamped at +0xc by Entity's +network send @0041f640 = {stamp id, msg+0x14 <- entity+0x194, EntityManager +(app+0x30) send @00434ea0}), **SetBurningState** (@0049f674: park the wreck +at (localHostID x 10000, localHostID x -1000) -- constants @0049f6fc/f8, +host id = HostManager::GetLocalHostID, THE accessor the instance dispatch +compares against ownerID -- then MODE 2 = BURNING, the second +InDeathTransition state's missing writer, + ForceUpdate(1) + +AlwaysExecute), **ClearBurningState** (@0049f700: mode 0 + same pair). +simulationFlags bit 1 == DontExecuteFlag (SIMULATE.HPP) -- the binary's +`&= ~2` IS AlwaysExecute(). + +Still to land from the roster: + +* **BalanceCoolant @0049f728** (decoded): if payload > 0, mark item+0x1d0=1 + across the mech+0x7cc roster, then the redistribute pass @0049f788: total + the marks, per item fraction = mark/total (0.0 @0049f850 when empty), + blip the item's alarm at +0x1dc (level 2 if fraction <= stored else 1, + then 0 -- the gauge flash), store fraction at item+0x15c. BLOCKED ON: + identifying the mech tail chain triple +0x7ac (legs -- the mobility + scan) / +0x7bc / +0x7cc (coolant holders) against our capability chains + -- @004aefa4 walks all three plus the plug at +0x590 to collect the + coolant set, so decode that fn to pin them. +* **EjectPilot @0049f854** (head read): gated on payload > 0 AND + **mech+0x414** -- THE EFFECTIVENESS-CENSUS CONSUMER FOUND: you can only + eject a CRIPPLED mech (@0049fa1c's weapons/coolant/generator/limp + census) -- and !InDeathTransition; notifies via an app+0x2c accessor + (@00429078) + app+0x20 vcall (score/event, code 5, ownerID +0x18c); + sets **MODE 10 = EJECTED** (which is WHY IsMechDestroyed tests >= 9: + 9 killed, 10 ejected); then builds a large effect/explosion struct -- + tail still unread. Mode roster now: 0 default, 2 burning, 3/4 gimp + L/R, 5-8 falls, 9 killed, 10 ejected; writers of 5-8 still open.