75 lines
4.9 KiB
C
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
|