Files
EscapistsReintroduced/docs/evidence/recovery-forecast-2026-10-31/native-probe.c
T
2026-10-31 14:32:30 +01:00

75 lines
4.9 KiB
C

#ifdef WORKBENCH
modded class ERR_GameMode
{
protected IEntity m_Patient;
protected float m_Predicted, m_Started;
protected override void StartScenario() {}
protected override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
if (!SCR_Global.IsEditMode()) GetGame().GetCallqueue().CallLater(RecoveryProbe, 8000, false);
}
void RecoveryProbe()
{
array<ref ERR_RecoveryFlow> flows = {};
ERR_RecoveryFlow r = new ERR_RecoveryFlow(); r.ResilienceRate = 0.002; flows.Insert(r);
float early = ERR_RecoveryForecast.Predict(1,0,0.3,0.5,flows);
r.End = 100;
float expires = ERR_RecoveryForecast.Predict(1,0,0.3,0.5,flows);
if (early < 249 || early > 252 || expires != -1) { Print("ERR SMOKE FAIL: recovery forecast boundaries",LogLevel.ERROR); return; }
IEntity actor = ERR_Actors.Spawn(ERR_CivilianTraffic.DriverPrefab(), ERR_Actors.Ground("9730 0 1560"));
SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(actor.FindComponent(SCR_CharacterDamageManagerComponent));
damage.ERR_EnableCasualtyProtection();
float before = damage.GetBloodHitZone().GetHealth();
float result = ERR_RecoveryForecast.Estimate(damage);
if (before != damage.GetBloodHitZone().GetHealth()) { Print("ERR SMOKE FAIL: forecast mutated patient",LogLevel.ERROR); return; }
PrintFormat("ERR RECOVERY FORECAST: early=%1 finiteMedicine=%2 nativeSnapshot=%3 bloodUnchanged=%4",early,expires,result,before);
Print("ERR SMOKE PASS: forecast boundaries and read-only native snapshot");
m_Patient = actor;
damage.ForceUnconsciousness();
GetGame().GetCallqueue().CallLater(Treat, 1000, false);
}
void Treat()
{
IEntity injector = ERR_Actors.Spawn("{C68512DB5FC74698}Prefabs/ERR/Epinephrine.et", m_Patient.GetOrigin());
SCR_ConsumableItemComponent item = SCR_ConsumableItemComponent.Cast(injector.FindComponent(SCR_ConsumableItemComponent));
SCR_ConsumableMorphine effect = SCR_ConsumableMorphine.Cast(item.GetConsumableEffect());
item.ApplyItemEffect(m_Patient, m_Patient, effect.GetAnimationParameters(injector, m_Patient), injector, effect.GetDeleteOnUse());
m_Predicted = ERR_RecoveryForecast.Estimate(SCR_CharacterDamageManagerComponent.Cast(m_Patient.FindComponent(SCR_CharacterDamageManagerComponent)));
SCR_CharacterDamageManagerComponent dm = SCR_CharacterDamageManagerComponent.Cast(m_Patient.FindComponent(SCR_CharacterDamageManagerComponent));
PrintFormat("ERR RECOVERY LEVELS: blood=%1 resilience=%2 max=%3 threshold=%4 scale=%5",dm.GetBloodHitZone().GetHealthScaled(),dm.GetResilienceHitZone().GetHealth(),dm.GetResilienceHitZone().GetMaxHealth(),dm.GetResilienceHitZone().GetDamageStateThreshold(ECharacterResilienceState.WEAKENED),dm.GetResilienceRegenScale());
array<ref SCR_PersistentDamageEffect> effects = dm.GetAllPersistentEffectsOfType(SCR_PersistentDamageEffect,true);
foreach (SCR_PersistentDamageEffect e : effects)
{
DotDamageEffect dot = DotDamageEffect.Cast(e);
if (dot) PrintFormat("ERR RECOVERY EFFECT: kind=%1 rate=%2 end=%3 current=%4",e.Type().ToString(),dot.GetDPS(),dot.GetMaxDuration(),dot.GetCurrentDuration());
}
PrintFormat("ERR RECOVERY MULTIPLIERS: base=%1 heal=%2 regen=%3",dm.GetResilienceHitZone().GetBaseDamageMultiplier(),dm.GetResilienceHitZone().GetDamageMultiplier(EDamageType.HEALING),dm.GetResilienceHitZone().GetDamageMultiplier(EDamageType.REGENERATION));
foreach (SCR_PersistentDamageEffect stateEffect : effects)
{
SCR_PassiveHitZoneRegenDamageEffect passive = SCR_PassiveHitZoneRegenDamageEffect.Cast(stateEffect);
if (passive) PrintFormat("ERR RECOVERY PASSIVE: active=%1 delay=%2 zoneResilience=%3",passive.IsActive(),passive.ERR_RemainingRegenDelay(),passive.GetAffectedHitZone() == dm.GetResilienceHitZone());
}
m_Started = GetWorld().GetWorldTime();
PrintFormat("ERR RECOVERY MEDICINE: predictionSeconds=%1",m_Predicted);
if (m_Predicted < 0) { Print("ERR SMOKE FAIL: known medicine forecast unavailable",LogLevel.ERROR); return; }
GetGame().GetCallqueue().CallLater(Observe, 500, true);
}
void Observe()
{
float elapsed = (GetWorld().GetWorldTime() - m_Started) / 1000;
SCR_CharacterDamageManagerComponent dm = SCR_CharacterDamageManagerComponent.Cast(m_Patient.FindComponent(SCR_CharacterDamageManagerComponent));
PrintFormat("ERR RECOVERY SAMPLE: elapsed=%1 resilience=%2",elapsed,dm.GetResilienceHitZone().GetHealth());
if (ERR_Actors.CanFight(m_Patient))
{
GetGame().GetCallqueue().Remove(Observe);
PrintFormat("ERR RECOVERY NATIVE WAKE: predicted=%1 actual=%2",m_Predicted,elapsed);
if (Math.AbsFloat(elapsed-m_Predicted) > 2) { Print("ERR SMOKE FAIL: native wake disagrees with prediction",LogLevel.ERROR); return; }
Print("ERR SMOKE PASS: native finite epinephrine wake agrees with prediction");
Print("ERR SMOKE COMPLETE: recovery-forecast");
}
else if (elapsed > 60) { GetGame().GetCallqueue().Remove(Observe); Print("ERR SMOKE FAIL: native wake timeout",LogLevel.ERROR); }
}
}
#endif