Files
EscapistsReintroduced/docs/evidence/preparation-exit-2026-10-25/native-fixture.c
T
jakub 9233320fd1
continuous-integration/drone/push Build is passing
Allow leaving failed-start screens; record Workshop 0.0.122
2026-10-25 14:55:36 +01:00

114 lines
4.1 KiB
C

#ifdef WORKBENCH
class ERR_PreparationExitProbe
{
static int s_Pauses, s_ExitAt;
static bool s_Armed, s_Clean, s_Ended, s_Complete;
static void Finish()
{
if (!s_Armed || !s_Clean || !s_Ended || s_Complete || System.GetTickCount() - s_ExitAt >= 5000) return;
s_Complete = true;
Check(true, "native gameplay end after exit click and menu-listener cleanup observed");
Print("ERR SMOKE COMPLETE: preparation-exit native gameplay-end transition");
}
static bool Enabled()
{
string outcome;
return System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "preparation-exit";
}
static bool Check(bool ok, string detail)
{
if (ok) Print("ERR SMOKE PASS: preparation exit " + detail);
else Print("ERR SMOKE FAIL: preparation exit " + detail, LogLevel.ERROR);
return ok;
}
}
modded class ERR_GameMode
{
override protected void StartScenario()
{
if (ERR_PreparationExitProbe.Enabled())
{
FailPreparation("Fixture: no safe navigable prison. Checks: water=120; uneven ground=30");
return;
}
super.StartScenario();
}
}
modded class SCR_RespawnSystemComponent
{
bool ERR_TestUnderlayHidden() { return m_wLoadingPlaceholder && !m_wLoadingPlaceholder.IsVisible(); }
}
modded class PauseMenuUI
{
protected bool m_ERRExitTestClosed;
override void OnMenuUpdate(float tDelta)
{
super.OnMenuUpdate(tDelta);
if (!ERR_PreparationExitProbe.Enabled() || m_ERRExitTestClosed) return;
m_ERRExitTestClosed = true;
SCR_RespawnSystemComponent respawn = SCR_RespawnSystemComponent.GetInstance();
if (!ERR_PreparationExitProbe.Check(IsFocused() && respawn && respawn.ERR_TestUnderlayHidden(), "native pause has focus and black underlay remains hidden")) return;
ERR_PreparationExitProbe.s_Pauses++;
Close();
}
}
modded class ERR_PreparationFailureMenu
{
protected float m_ERRExitTestAge;
protected int m_ERRExitTestStage;
override void OnMenuUpdate(float tDelta)
{
super.OnMenuUpdate(tDelta);
if (!ERR_PreparationExitProbe.Enabled() || !IsFocused() || m_ERRExitTestStage < 0) return;
m_ERRExitTestAge += tDelta;
if (m_ERRExitTestAge < 1) return;
m_ERRExitTestAge = 0;
if (m_ERRExitTestStage == 0)
{
SCR_RespawnSystemComponent respawn = SCR_RespawnSystemComponent.GetInstance();
if (!ERR_PreparationExitProbe.Check(Visible(m_Mode) && m_Bound && respawn && respawn.ERR_TestUnderlayHidden(), "real focused error menu has both bound buttons, exact error and hidden loading layer")) { m_ERRExitTestStage = -1; return; }
m_ERRExitTestStage = 1;
m_PauseButton.m_OnClicked.Invoke(m_PauseButton);
return;
}
if (m_ERRExitTestStage == 1)
{
if (!ERR_PreparationExitProbe.Check(ERR_PreparationExitProbe.s_Pauses == 1 && Failed(m_Mode), "pause button returns to the same failed round without admitting a player")) { m_ERRExitTestStage = -1; return; }
m_ERRExitTestStage = 2;
OnBack(); // Actual handler bound to MenuBack; no physical key-input claim.
return;
}
if (m_ERRExitTestStage == 2)
{
if (!ERR_PreparationExitProbe.Check(ERR_PreparationExitProbe.s_Pauses == 2, "bound Back handler opens native pause and restores failure-menu focus")) { m_ERRExitTestStage = -1; return; }
m_ERRExitTestStage = 3;
ERR_PreparationExitProbe.s_Armed = true;
ERR_PreparationExitProbe.s_ExitAt = System.GetTickCount();
m_ReturnButton.m_OnClicked.Invoke(m_ReturnButton);
}
}
override void OnMenuClose()
{
super.OnMenuClose();
if (ERR_PreparationExitProbe.s_Armed)
{
ERR_PreparationExitProbe.s_Clean = !m_Bound && !m_Mode && !m_ReturnButton && !m_PauseButton;
PrintFormat("ERR EXIT TEST: menu closed; cleaned=%1", ERR_PreparationExitProbe.s_Clean);
ERR_PreparationExitProbe.Finish();
}
}
}
modded class ArmaReforgerScripted
{
override void OnGameEnd()
{
bool expected = ERR_PreparationExitProbe.Enabled() && ERR_PreparationExitProbe.s_Armed && System.GetTickCount() - ERR_PreparationExitProbe.s_ExitAt < 5000;
super.OnGameEnd();
if (!expected) return; // Runner shutdown cannot qualify the exit button.
ERR_PreparationExitProbe.s_Ended = true;
Print("ERR EXIT TEST: native gameplay ended after the real exit button");
ERR_PreparationExitProbe.Finish();
}
}
#endif