Extend results countdown and stabilize spectator hints; record Workshop 0.0.128
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-10-30 15:20:21 +01:00
parent 213c31dfb2
commit 681d5e5eae
10 changed files with 100 additions and 30 deletions
@@ -284,6 +284,8 @@ modded class SCR_PlayerController
protected ERR_ObserverReason m_ERRShownObserverReason;
protected bool m_ERRShownObserverAvailable;
protected string m_ERRShownRecoveryStatus;
protected string m_ERRPendingRecoveryStatus;
protected int m_ERRRecoveryStatusSince;
protected float m_ERRLastCycle = -1000;
protected IEntity m_ERRRecoveryBody;
protected float m_ERRRecoveryDeadline = -1;
@@ -468,13 +470,24 @@ modded class SCR_PlayerController
string recovery = mode.RecoveryStatus();
string selfEpiHint = ERR_SelfEpinephrineHint();
if (!selfEpiHint.IsEmpty()) recovery += "\n" + selfEpiHint;
if (ERR_ObserverGuidance.Refresh(m_ERRObserverReady, m_ERRShownObserverReason, m_ERRObserverReason, m_ERRShownObserverAvailable, survivorAvailable) || m_ERRShownRecoveryStatus != recovery)
bool contextChanged = ERR_ObserverGuidance.Refresh(m_ERRObserverReady, m_ERRShownObserverReason, m_ERRObserverReason, m_ERRShownObserverAvailable, survivorAvailable);
int now = System.GetTickCount();
// Medical samples can alternate between improving and stalled. Keep the
// accepted hint readable until the new status has remained stable for 3s.
// This affects presentation only, never the authoritative defeat timer.
if (m_ERRPendingRecoveryStatus != recovery || now < m_ERRRecoveryStatusSince)
{
m_ERRPendingRecoveryStatus = recovery;
m_ERRRecoveryStatusSince = now;
}
if (!contextChanged && m_ERRShownRecoveryStatus != recovery && now - m_ERRRecoveryStatusSince < 3000) return;
if (contextChanged || m_ERRShownRecoveryStatus != recovery)
{
SCR_HintManagerComponent hints = SCR_HintManagerComponent.GetInstance();
if (!hints) return; // retry on the existing monitor; do not lose the first hint
string message = ERR_ObserverGuidance.Message(m_ERRObserverReason, survivorAvailable);
if (!recovery.IsEmpty()) message += "\n" + recovery;
if (!hints.ShowCustom(message, "Spectating", 12)) return;
if (!hints.ShowCustom(message, "Spectating", 12, m_ERRObserverReady)) return;
m_ERRObserverReady = true;
m_ERRShownObserverReason = m_ERRObserverReason;
m_ERRShownObserverAvailable = survivorAvailable;
@@ -510,6 +523,8 @@ modded class SCR_PlayerController
{
m_ERRObserverReady = false;
m_ERRShownRecoveryStatus = "";
m_ERRPendingRecoveryStatus = "";
m_ERRRecoveryStatusSince = 0;
if (!m_ERRObserverCamera) return;
if (GetGame().GetPlayerController() == this) m_ERRObserverCamera.TrySwitchToControlledEntityCamera();
m_ERRObserverCamera.Terminate();
@@ -40,7 +40,9 @@ modded class SCR_PlayerController
}
ERR_GameMode mode = ERR_GameMode.Get();
if (!mode) return;
if (mode.Phase() != ERR_Phase.PREPARING && (ERR_ObserverState() != ERR_ObserverReason.NONE || !ERR_Actors.Alive(GetControlledEntity()))) return;
// Local unconsciousness can arrive before the replicated observer reason.
// Do not let objective hints compete with casualty/spectator guidance then.
if (mode.Phase() != ERR_Phase.PREPARING && (ERR_ObserverState() != ERR_ObserverReason.NONE || !ERR_Actors.CanFight(GetControlledEntity()))) return;
string message = ERR_ObjectiveText.Description(mode, false);
if (message.IsEmpty()) return;
if (m_ERRGuidePhase == mode.Phase() && m_ERRGuideMessage == message) return;
@@ -208,7 +208,8 @@ modded class ERR_GameMode
m_ERRCameraBody = pc.GetControlledEntity();
m_ERRCameraDamage = SCR_CharacterDamageManagerComponent.Cast(m_ERRCameraBody.FindComponent(SCR_CharacterDamageManagerComponent));
if (!ERR_CameraCheck(m_ERRCameraDamage && m_ERRCameraDamage.ERR_IsRevivablePlayer(), "admitted player retains treatable body")) return;
ERR_CameraKnockout(); m_ERRCameraStage = 1; m_ERRCameraWait = now + 3000; return;
// Allow the server medical sample plus the 3s spectator hint settling window.
ERR_CameraKnockout(); m_ERRCameraStage = 1; m_ERRCameraWait = now + 6000; return;
}
if (m_ERRCameraStage == 1)
{