#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 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 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