Files
BT411/engine/MUNGA/STATE.h
T
Joe DiPrimaandClaude Fable 5 1671b7d4b2 the REVERSE DISABLED voice (#78): SimulationState 3/4 IS the trigger -- mirror the gimp level into the engine cell
User + old-timers were right; the earlier "no voice exists" verdict was wrong.
The authored mech audio has state watchers on Entity.SimulationState==3/4
(the binary's one-cell mech+0x40) that start sequence notes 29,16,40 -- two
klaxon hits then Warnings01 zone 8 (key 40-41) = the "reverse disabled"
voice line the testers remember.  The port's cell split (graphicAlarm vs
engine simulationState, gotcha #23) meant the trigger value never arrived.

- mechdmg: mirror gimp 3/4 into SetSimulationState at the leg-half crossing
  (guarded: never stomps disabled/fall/dead states).  Voice verified playing
  end-to-end on the bench: SetupPatch bank2 patch113 note=40 ->
  Warnings01_z7.wav.
- mech.cpp: BT_GIMP_SAFE_BASE_READ on all seven Simulation::ReadUpdateRecord
  sites -- gimp is monotonic per life; a record captured pre-gimp must not
  stomp the cell (the loopback otherwise perpetuates the stale value and
  restarts the warning on every damage event).
- diagnostics (all env-gated): [statefire]/[startreq]/[animind]/[gimp-sim]/
  [simstomp]/[indstomp] + StateIndicator::DebugAudioWatcherCount + raised
  spatial-log caps.  These traced the whole chain and PROVED no SetState
  path stomps the cell.

OPEN (follow-up): a RAW writer (bypasses SetState entirely; invisible to the
indicator-level trap) resets the cell between damage events -- under the
bench's 1 Hz metronome harness it restarted the sequence before the 1.8 s
voice note; sporadic real-play damage is unaffected (one edge -> full
sequence).  Needs a cdb write-watchpoint session; candidates: a recon raw
+0x2c-equivalent write or a struct copy spanning it.

Also decoded en route: the AnimationState triggers on the limp states play
EngineShiftRev01 (the downshift foley) -- working, and NOT the voice.

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

69 lines
1.4 KiB
C++

#pragma once
#include "cmpnnt.h"
#include "schain.h"
class StateIndicator : public Node
{
public:
StateIndicator();
StateIndicator(unsigned max_states);
StateIndicator(const StateIndicator &state_indicator);
~StateIndicator();
StateIndicator& operator=(const StateIndicator&);
Logical operator==(const StateIndicator&) const;
public:
unsigned GetState()
{
Check(this);
return currentState;
}
unsigned GetOldState()
{
Check(this);
return oldState;
}
void SetState(unsigned new_state);
protected:
unsigned stateCount, oldState, currentState;
public:
void AddAudioWatcher(Component *watcher)
{
Check(&audioWatcherSocket);
audioWatcherSocket.Add(watcher);
}
void AddVideoWatcher(Component *watcher)
{
Check(&videoWatcherSocket);
videoWatcherSocket.Add(watcher);
}
void AddGaugeWatcher(Component *watcher)
{
Check(&gaugeWatcherSocket);
gaugeWatcherSocket.Add(watcher);
}
int DebugAudioWatcherCount() // DEBUG (#78 audio flake): registered audio watchers
{
int n = 0;
SChainIteratorOf<Component*> it(audioWatcherSocket);
while (it.ReadAndNext() != NULL) ++n;
return n;
}
private:
SChainOf<Component*> audioWatcherSocket;
SChainOf<Component*> videoWatcherSocket;
SChainOf<Component*> gaugeWatcherSocket;
public:
friend std::ostream& operator << (std::ostream &strm, const StateIndicator &state_indicator);
public:
Logical TestInstance() const;
static Logical TestClass();
};