"""Actual fixture staging and hitzone cap, with vanilla max-health damage boundary.""" import os from pathlib import Path from policy_harness import ROOT, body, run base=Path(os.environ.get('ERR_DEATH_FIXTURE_ROOT', ROOT)) p=base/'addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c' f=base/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c' def convert(s): s=s.replace('protected ', '').replace('override ','').replace('notnull Instigator instigator','int instigator').replace('IEntity expectedActor','Actor* expectedActor') s=s.replace('Replication.IsServer()','server').replace('System.GetCLIParam','System::GetCLIParam').replace('super.','Native::') s=s.replace('SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));','Medical* damage = &medical;') s=s.replace('CharacterControllerComponent character = CharacterControllerComponent.Cast(m_ERRSmokePlayer.FindComponent(CharacterControllerComponent));','Actor* character = m_ERRSmokePlayer;') s=s.replace('Instigator.CreateInstigator(m_ERRSmokePlayer)','0').replace('ERR_Actors.Alive(m_ERRSmokePlayer)','m_ERRSmokePlayer->alive') s=s.replace('IEntity actor = GetOwner();','Actor* actor = GetOwner();').replace('ERR_GameMode mode = ERR_GameMode.Get();','Mode* mode = Mode::current;').replace('ERR_Actors.Alive(actor)','(actor && actor->alive)') s=s.replace('mode.', 'mode->').replace('Players().CurrentActor','Players()->CurrentActor') s=s.replace('damage.','damage->').replace('character.','character->') return s kill=convert(body(p,'override void Kill(')) fatal=convert(body(p,'bool ERR_ForceFatalLossForTest(')) # Permit the unchanged helper's older signature for the runtime red test. if 'Actor* expectedActor' not in fatal: fatal=fatal.replace('int instigator)', 'int instigator, Actor* expectedActor)') begin=convert(body(f,'protected void ERR_BeginProtectedDeathProbe(')) complete=convert(body(f,'protected void ERR_CompleteProtectedDeathProbe(')) complete=complete.replace('ERR_ForceFatalLossForTest(0)', 'ERR_ForceFatalLossForTest(0, m_ERRSmokePlayer)') cap=body(p,'static float AllowedDamage(').replace('Math.Clamp','std::clamp').replace('Math.Min','std::min').replace('Math.Max','std::max').replace('0.01','0.01f').replace(', 1)',', 1.0f)').replace('(0,','(0.0f,') effective=body(p,'override float ComputeEffectiveDamage(') effective=effective.replace('override ', '').replace('notnull BaseDamageContext damageContext','float damageContext').replace('super.','NativeZone::') effective=effective.replace('Replication.IsServer()','server').replace('SCR_CharacterResilienceHitZone.Cast(this)','resilience') effective=effective.replace('SCR_CharacterDamageManagerComponent manager = SCR_CharacterDamageManagerComponent.Cast(GetHitZoneContainer());','Medical* manager = medical;').replace('manager.','manager->').replace('ERR_PlayerMedicalRules.','').replace('EDamageState.DESTROYED','0') run(r''' #include #include #include #include using string=std::string; bool server=true; namespace System { std::map args; bool GetCLIParam(string key,string& out){auto it=args.find(key);if(it==args.end())return false;out=it->second;return true;} } struct Actor {bool alive=true, unconscious=false;bool IsUnconscious(){return unconscious;}}; struct Roster {Actor* owned=nullptr;bool CurrentActor(Actor* actor){return actor==owned;}}; struct Mode {static inline Mode* current=nullptr;bool active=true,haveRoster=true;Roster roster;bool Active(){return active;}Roster* Players(){return haveRoster?&roster:nullptr;}}; struct Native {Actor* actor;int fatalities=0;bool deferred=false,damagePending=false;virtual float AppliedDamage(float)=0;void Kill(int){fatalities++;if(deferred){damagePending=true;return;}Damage();}void Damage(){damagePending=false;actor->alive=AppliedDamage(100)<100;}Actor* GetOwner(){return actor;}}; struct Medical: Native { bool m_ERRRevivablePlayer=true,pending=false; int requests=0; void ERR_RequestKnockout(){requests++;pending=true;} void Settle(){if(pending){actor->unconscious=true;pending=false;}} bool ERR_IsRevivablePlayer(){return m_ERRRevivablePlayer;} float AppliedDamage(float damage) override; ''' + kill+fatal+r''' }; ''' + cap + r''' struct NativeZone {float ComputeEffectiveDamage(float damage,bool){return damage;}}; struct Zone: NativeZone {bool m_ERRWoundQuery=false,resilience=false;Medical* medical;float GetHealth(){return 100;}float GetMaxHealth(){return 100;}float GetDamageStateThreshold(int){return 0;} ''' + effective + r''' }; float Medical::AppliedDamage(float damage){Zone zone;zone.medical=this;return zone.ComputeEffectiveDamage(damage,false);} void Print(string){} struct Fixture { Actor actor;Medical medical;Mode mode;Actor* m_ERRSmokePlayer=&actor;int m_ERRSmokeStep=0;float m_ERRSmokeWait=0;int failures=0; Fixture(){medical.actor=&actor;mode.roster.owned=&actor;Mode::current=&mode;} bool ERR_Check(bool ok,string){if(!ok)failures++;return ok;} ''' + begin+complete+r''' }; int main(){ System::args={{"errSmoke","1"}}; Fixture f; f.ERR_BeginProtectedDeathProbe(100); assert(f.m_ERRSmokeStep==92 && f.actor.alive && f.medical.requests==1 && f.medical.fatalities==0); assert(!f.actor.unconscious && f.m_ERRSmokeWait==1100); f.medical.Settle(); f.ERR_CompleteProtectedDeathProbe(1100); // Old helper failed here: super.Kill still goes through the actual hitzone cap. assert(f.failures==0 && f.m_ERRSmokeStep==9 && !f.actor.alive && f.medical.fatalities==1); assert(!f.medical.m_ERRRevivablePlayer && f.medical.requests==1 && f.m_ERRSmokeWait==5100); {Fixture q;q.medical.deferred=true;assert(q.medical.ERR_ForceFatalLossForTest(0,&q.actor));assert(q.actor.alive&&q.medical.damagePending&&!q.medical.m_ERRRevivablePlayer);q.medical.Damage();assert(!q.actor.alive);} // An unrelated ordinary actor retains full protection; test flag never global. {Fixture q;q.medical.Kill(0);assert(q.actor.alive&&q.medical.requests==1&&q.medical.fatalities==0&&q.medical.m_ERRRevivablePlayer);} {Fixture q;q.ERR_CompleteProtectedDeathProbe(1100);assert(q.failures==1&&q.medical.fatalities==0);} {Fixture q;q.actor.alive=false;q.ERR_CompleteProtectedDeathProbe(1100);assert(q.failures==1&&q.medical.fatalities==0);} {Fixture q;q.medical.m_ERRRevivablePlayer=false;q.ERR_BeginProtectedDeathProbe(100);assert(q.failures==1&&q.medical.requests==0&&q.medical.fatalities==0);} {Fixture q;Actor other;assert(!q.medical.ERR_ForceFatalLossForTest(0,&other)&&q.medical.m_ERRRevivablePlayer&&q.actor.alive);assert(!q.medical.ERR_ForceFatalLossForTest(0,nullptr)&&q.medical.m_ERRRevivablePlayer);} {Fixture q;q.mode.roster.owned=nullptr;assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.medical.m_ERRRevivablePlayer);} {Fixture q;q.mode.active=false;assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.medical.m_ERRRevivablePlayer);} {Fixture q;q.mode.haveRoster=false;assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.medical.m_ERRRevivablePlayer);} {Fixture q;Mode::current=nullptr;assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.medical.m_ERRRevivablePlayer);} {Fixture q;server=false;assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.actor.alive&&q.medical.m_ERRRevivablePlayer);server=true;} {Fixture q;System::args.clear();assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.actor.alive&&q.medical.m_ERRRevivablePlayer);System::args["errSmoke"]="0";assert(!q.medical.ERR_ForceFatalLossForTest(0,&q.actor)&&q.actor.alive&&q.medical.m_ERRRevivablePlayer);} {Fixture q;q.medical.m_ERRRevivablePlayer=false;q.medical.Kill(0);assert(!q.actor.alive&&q.medical.requests==0&&q.medical.fatalities==1);} } ''') s=p.read_text();at=s.index('bool ERR_ForceFatalLossForTest(') assert s.rfind('#ifdef WORKBENCH',0,at)>s.rfind('#endif',0,at) tick=body(f,'protected void ERR_SmokeTick()') assert tick.count('damage.ERR_ForceFatalLossForTest(')==7 assert 'damage.Kill(' not in tick print('PASS: actual protected/capped damage plus exact-actor terminal fixture bypass through delayed native damage, fail-closed ownership and untouched ordinary actor; no native claim')