#156 layer 2+3, both field-caught watching the fade live: (a) the fade-out completed into a phase-0 re-arm that RESTORED normal fog for the ~2s before teardown -- the binary's zone fog stays closed, so the machine now holds a terminal black phase until the next MissionStarting edge; (b) the 3.0s end window itself never existed on ANY node: a REPLICANT player copy mirrors the remote master's MissionEndingState through its record header, and its never-armed fadeTimeRemaining (<=0 at first tick) dispatched the second StopMission instantly -- Stop() killed the mission loop before the fade could render ([fade-clk] receipts: a clean 3->2.976->... countdown interleaved with a stray remaining=-0.976). ManageApplicationStatus is now owner-gated (a replicant player must never drive application state -- the same authority discipline as scoring). This was the FIELD half of the no-fade report too: steam nodes hold up to 7 replicant players, any of which cut the window to ~one record heartbeat. Receipts now: 124-tick single countdown, phases 1-5 on both nodes, fade rendered + black held to teardown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Joe DiPrima
2026-08-12 01:43:14 -05:00
co-authored by Claude Fable 5
parent fc71f9c0bb
commit 880ee20005
2 changed files with 37 additions and 4 deletions
+21
View File
@@ -415,6 +415,23 @@ void
// //
Check(this); Check(this);
Check(application); Check(application);
// #156 (BT, field-caught watching the fade live): ONLY the local mission
// player may drive application state. A REPLICANT player copy mirrors the
// remote master's simulationState through its update-record header -- so at
// mission end every replicant player on this node also reads
// MissionEndingState here, and its fadeTimeRemaining was never armed by a
// MissionEnding message (ctor value, already <= 0) -> it dispatched the
// second StopMissionMessage on its FIRST tick and Stop() killed the mission
// loop instantly: the 3.0s fade window (and the fade itself) never rendered.
// Receipts: [fade-clk] interleaving remaining=3,2.976,... with a stray
// remaining=-0.976 from the replicant copy. The 1995 pod's replicant
// players never executed this arm; the port's replicant-executable wave
// made them tick, so gate the app-control arm to the owner.
if (GetInstance() == ReplicantInstance)
{
return;
}
switch (GetSimulationState()) switch (GetSimulationState())
{ {
case MissionStartingState: case MissionStartingState:
@@ -442,6 +459,10 @@ void
} }
break; break;
case MissionEndingState: case MissionEndingState:
// #156 diag: the 3.0s fade window's actual clock, tick by tick.
if (getenv("BT_FADE_LOG"))
DEBUG_STREAM << "[fade-clk] slice=" << time_slice
<< " remaining=" << fadeTimeRemaining << "\n" << std::flush;
fadeTimeRemaining -= time_slice; fadeTimeRemaining -= time_slice;
if (fadeTimeRemaining <= 0.0f) if (fadeTimeRemaining <= 0.0f)
{ {
+16 -4
View File
@@ -8504,9 +8504,21 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
fn = fogNear * local + kNearFloor; fn = fogNear * local + kNearFloor;
ff = fogFar * local + kFarFloor; ff = fogFar * local + kFarFloor;
s_T += fdt; s_T += fdt;
if (local <= 0.0f) { s_phase = 0; } // re-armed; final frame stays black // FIELD-CAUGHT (first live watch): completing into phase 0 hit
// the restore branch -- the world POPPED BACK for the ~2s
// between fade end and teardown, which read as "no fade at
// all". The binary's zone fog STAYS closed after the fade-out
// (nothing reopens it until the next mission's flash). Hold
// black in a terminal phase instead; the next MissionStarting
// edge re-arms through it.
if (local <= 0.0f) { s_phase = 5; }
break; break;
} }
case 5: // held black until the next mission starts
r = 0.0f; g = 0.0f; b = 0.0f;
fn = kNearFloor; ff = kFarFloor;
if (st == gBTFadeStart) { s_phase = 1; s_T = 0.0f; }
break;
} }
if (r >= 0.0f) if (r >= 0.0f)
{ {
@@ -8516,10 +8528,10 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
D3DCOLOR_XRGB((int)(255 * r), (int)(255 * g), (int)(255 * b))); D3DCOLOR_XRGB((int)(255 * r), (int)(255 * g), (int)(255 * b)));
mDevice->SetRenderState(D3DRS_FOGENABLE, TRUE); mDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
} }
else if (s_phase == 3 || s_phase == 0) else if (s_phase == 3)
{ {
// Out of the fade: restore the style planes once so a fade that // Fade-in complete: restore the style planes once so the world
// ended mid-style leaves the world exactly on its authored fog. // lands exactly on its authored fog.
static int s_prev = -1; static int s_prev = -1;
if (s_prev != s_phase) if (s_prev != s_phase)
{ {