Integrate startup optics and supply vehicle lock picking

This commit is contained in:
2026-09-20 05:34:30 +02:00
parent 9205e2129a
commit 963cab50c0
104 changed files with 16171 additions and 25 deletions
+26 -10
View File
@@ -13,9 +13,9 @@ code=code.replace('static const ResourceName','static constexpr const char*').re
code=code.replace('string result','std::string result').replace('array<IEntity>','std::vector<IEntity*>')
code=code.replace('BaseWeaponManagerComponent.Cast(Actor.FindComponent(BaseWeaponManagerComponent))','Actor->weapons')
code=code.replace('InventoryStorageManagerComponent.Cast(Actor.FindComponent(InventoryStorageManagerComponent))','Actor->inventory')
for cls in ('ERR_GameMode','SCR_AIGroup','SCR_AIGroupUtilityComponent','IEntity','SCR_AICombatComponent','ERR_EnemyEquipmentCallback','BaseWeaponManagerComponent','InventoryStorageManagerComponent'):
for cls in ('ERR_GameMode','SCR_AIGroup','SCR_AIGroupUtilityComponent','IEntity','SCR_AICombatComponent','ERR_EnemyEquipmentCallback','ERR_EnemyOptics','BaseWeaponManagerComponent','InventoryStorageManagerComponent'):
code=re.sub(r'\b'+cls+r' ([a-zA-Z_]\w*)',cls+r'* \1',code)
for obj in ('mode','group','utility','Actor','Group','Combat','Operation','item','weapons','inventory'):
for obj in ('mode','group','utility','Actor','Group','Combat','Optics','Operation','item','weapons','inventory'):
code=code.replace(obj+'.',obj+'->')
for cls in ('Replication','SCR_Global','ERR_GameMode','ERR_Actors','ERR_EnemyEquipmentRules','EAISkill','ERR_HQ','Math','EStoragePurpose'):
code=code.replace(cls+'.',cls+'::')
@@ -67,13 +67,14 @@ struct NativeCombat {
IEntity* GetOwner(){return owner;}EAISkill GetAISkill(){return skill;}
virtual void SetAISkill(EAISkill value){skill=value;}virtual void ResetAISkill(){skill=EAISkill::ROOKIE;}
};
struct ERR_EnemyOptics{int stops=0;void Stop(){stops++;}};
''' + code + r'''
std::vector<std::unique_ptr<ERR_EnemyEquipmentCallback>> operations;
ERR_EnemyEquipmentCallback* NewOperation(){operations.emplace_back(new ERR_EnemyEquipmentCallback());return operations.back().get();}
struct Soldier {
SCR_AIGroup group;BaseWeaponManagerComponent weapons;InventoryStorageManagerComponent inventory;IEntity actor;SCR_AICombatComponent combat;
SCR_AIGroup group;BaseWeaponManagerComponent weapons;InventoryStorageManagerComponent inventory;IEntity actor;SCR_AICombatComponent combat;ERR_EnemyOptics optics;
Soldier(){actor.group=&group;actor.weapons=&weapons;actor.inventory=&inventory;combat.owner=&actor;}
ERR_EnemyEquipmentEntry Entry(){ERR_EnemyEquipmentEntry e;e.Actor=&actor;e.Group=&group;e.Combat=&combat;return e;}
ERR_EnemyEquipmentEntry Entry(){ERR_EnemyEquipmentEntry e;e.Actor=&actor;e.Group=&group;e.Combat=&combat;e.Optics=&optics;return e;}
};
int main(){
ERR_GameMode mode;ERR_GameMode::current=&mode;
@@ -123,7 +124,7 @@ int main(){
skill.combat.SetAISkill(EAISkill::ROOKIE);assert(skill.combat.GetAISkill()==EAISkill::ROOKIE);
Soldier moved;SCR_AIGroup replacement;moved.combat.ERR_BindEnemySkill(&mode,&moved.group);moved.actor.group=&replacement;
moved.combat.SetAISkill(EAISkill::ROOKIE);assert(moved.combat.GetAISkill()==EAISkill::ROOKIE);
Soldier stopped;auto terminal=stopped.Entry();terminal.Check(&mode);terminal.Stop(&mode);stopped.inventory.callback->OnComplete();
Soldier stopped;auto terminal=stopped.Entry();terminal.Check(&mode);terminal.Stop(&mode);assert(stopped.optics.stops==1);stopped.inventory.callback->OnComplete();
for(int n=0;n<10;n++){terminal.Check(&mode);}assert(stopped.inventory.requests==1&&terminal.Complete);
}
''')
@@ -136,7 +137,7 @@ for cls in ('ERR_GameMode','SCR_AIGroup','ERR_EnemyEquipmentGroup','ERR_EnemyEqu
coordinator=re.sub(r'\b'+cls+r' ([a-zA-Z_]\w*)',cls+r'* \1',coordinator)
for obj in ('m_Mode','existing','state','group','agent','entry','actor'):
coordinator=coordinator.replace(obj+'.',obj+'->')
coordinator=coordinator.replace('Group.GetAgents','Group->GetAgents').replace('Combat.ERR_','Combat->ERR_')
coordinator=coordinator.replace('Group.GetAgents','Group->GetAgents').replace('Combat.ERR_','Combat->ERR_').replace('Optics.Check','Optics->Check')
for cls in ('Replication','ERR_GameMode','ERR_EnemyEquipmentRules'):coordinator=coordinator.replace(cls+'.',cls+'::')
coordinator=coordinator.replace('void ERR_EnemyEquipment(', 'ERR_EnemyEquipment(')
coordinator=coordinator.replace('GetGame().GetWorld().GetWorldTime()','worldTime').replace('foreach (','for (').replace('null','nullptr')
@@ -155,9 +156,15 @@ struct IEntity{SCR_AICombatComponent* combat=nullptr;bool eligible=true;};
struct AIAgent{IEntity* actor=nullptr;IEntity* GetControlledEntity(){return actor;}};
struct SCR_AIGroup{Array<AIAgent*> agents;void GetAgents(Array<AIAgent*>& out){out=agents;}};
namespace ERR_EnemyEquipmentRules{bool Eligible(ERR_GameMode*,SCR_AIGroup*,IEntity* actor){return actor&&actor->eligible;}}
struct ERR_EnemyOptics{
IEntity* actor;SCR_AIGroup* group;int checks=0,stops=0;
ERR_EnemyOptics(IEntity* a,SCR_AIGroup* g):actor(a),group(g){}
void Check(ERR_GameMode*){checks++;}void Stop(){stops++;}
};
struct ERR_EnemyEquipmentEntry{
ERR_EnemyOptics* Optics=nullptr;bool Complete=false;
IEntity* Actor=nullptr;SCR_AIGroup* Group=nullptr;SCR_AICombatComponent* Combat=nullptr;bool Released=false;int SkillChecks=0,checks=0,stops=0;
void Check(ERR_GameMode*){checks++;}void Stop(ERR_GameMode*){stops++;Released=true;Combat=nullptr;}
void Check(ERR_GameMode*){checks++;Complete=true;}void Stop(ERR_GameMode*){stops++;Released=true;if(Optics)Optics->Stop();Combat=nullptr;}
};
''' + coordinator + r'''
int main(){
@@ -165,8 +172,11 @@ int main(){
SCR_AIGroup group;IEntity soldier;SCR_AICombatComponent combat;soldier.combat=&combat;AIAgent agent;agent.actor=&soldier;group.agents.Insert(&agent);
service.RegisterGroup(&group);service.RegisterGroup(&group);assert(service.m_Groups.Count()==1);
service.Tick(0);assert(service.m_Entries.Count()==0);service.Tick(3000);assert(service.m_Entries.Count()==1&&combat.binds==1);
service.Tick(3001);assert(service.m_Entries[0]->checks==1);service.Tick(6000);assert(service.m_Entries[0]->checks==2&&combat.binds==1);
service.UnregisterGroup(&group);service.Tick(9000);assert(service.m_Entries[0]->Released&&service.m_Entries[0]->checks==2);
auto entry=service.m_Entries[0];assert(entry->Optics&&entry->Optics->actor==&soldier&&entry->Optics->group==&group);
assert(entry->Complete&&entry->Optics->checks==1); // Stinger is already complete; optics has its own startup completion.
service.Tick(3001);assert(entry->checks==1&&entry->Optics->checks==1);
service.Tick(6000);assert(entry->checks==2&&entry->Optics->checks==2&&combat.binds==1);
service.UnregisterGroup(&group);service.Tick(9000);assert(service.m_Entries[0]->Released&&service.m_Entries[0]->checks==2&&entry->Optics->checks==2&&entry->Optics->stops==1);
service.RegisterGroup(&group);service.Tick(12000);assert(service.m_Entries.Count()==1&&combat.binds==1);
service.Stop();service.RegisterGroup(&group);service.Tick(50000);assert(service.m_Groups.Count()==0&&service.m_Stopped);
ERR_EnemyEquipment delayed(&mode);SCR_AIGroup late;delayed.RegisterGroup(&late);delayed.Tick(3000);late.agents.Insert(&agent);delayed.Tick(6000);assert(delayed.m_Entries.Count()==1);
@@ -174,7 +184,13 @@ int main(){
ERR_EnemyEquipment bounded(&mode);for(int i=0;i<140;i++){bounded.RegisterGroup(new SCR_AIGroup());}assert(bounded.m_Groups.Count()==128);
ERR_EnemyEquipment incomplete(&mode);SCR_AIGroup unresolved;IEntity body;AIAgent bodyAgent;bodyAgent.actor=&body;unresolved.agents.Insert(&bodyAgent);incomplete.RegisterGroup(&unresolved);
for(int i=1;i<=12;i++){incomplete.Tick(i*3000);}assert(incomplete.m_Entries.Count()==1&&incomplete.m_Entries[0]->SkillChecks==5);
incomplete.Stop();
auto incompleteOptics=incomplete.m_Entries[0]->Optics;int checksBeforeStop=incompleteOptics->checks;
incomplete.Stop();incomplete.Tick(60000);assert(incompleteOptics->stops==1&&incompleteOptics->checks==checksBeforeStop);
ERR_EnemyEquipment capture(&mode);SCR_AIGroup capturedGroup;IEntity capturedBody;AIAgent capturedAgent;capturedAgent.actor=&capturedBody;
capturedGroup.agents.Insert(&capturedAgent);capture.RegisterGroup(&capturedGroup);capture.Tick(3000);
auto capturedOptics=capture.m_Entries[0]->Optics;capturedBody.eligible=false;capture.Tick(6000);
assert(capturedOptics->checks==1&&capturedOptics->stops==1&&capture.m_Entries[0]->Released);
capturedBody.eligible=true;capture.Tick(9000);assert(capturedOptics->checks==1);
}
''')
print('PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 128-group bound')
+113
View File
@@ -0,0 +1,113 @@
"""Execute actual startup optics service through native attachment API doubles; no native proof."""
from pathlib import Path
import os,re
from policy_harness import ROOT,run
P=Path(os.environ.get('ERR_OPTICS_SOURCE',ROOT/'addons/ai/Scripts/Game/ERR/ERR_EnemyOptics.c'))
s=P.read_text()
assert 'GetGame(' not in s and 'CallLater' not in s and 'DeleteEntity' not in s
callback=(ROOT/'addons/ai/Scripts/Game/ERR/ERR_EnemyEquipment.c').read_text().split('class ERR_EnemyEquipmentCallback',1)[1].split('class ERR_EnemyEquipmentEntry',1)[0]
code='class ERR_EnemyEquipmentCallback'+callback+s
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('override ','').replace('class ','struct ')
for src,dst in {
'BaseWeaponManagerComponent.Cast(m_Actor.FindComponent(BaseWeaponManagerComponent))':'m_Actor->manager',
'InventoryStorageManagerComponent.Cast(m_Actor.FindComponent(InventoryStorageManagerComponent))':'m_Actor->inventory',
'BaseWeaponComponent.Cast(job.Rifle.FindComponent(BaseWeaponComponent))':'job->Rifle->weapon',
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
'WeaponAttachmentsStorageComponent.Cast(job.Rifle.FindComponent(WeaponAttachmentsStorageComponent))':'job->Rifle->storage',
'entity.FindComponent(SCR_2DOpticsComponent)':'entity->scope2D',
'entity.FindComponent(SCR_2DPIPSightsComponent)':'entity->scope2DPip',
'entity.FindComponent(SCR_PIPSightsComponent)':'entity->scopePip',
}.items():code=code.replace(src,dst)
code=code.replace('ref array<ref ERR_EnemyOpticsJob>','Array<ERR_EnemyOpticsJob*>').replace('ref array<','Array<').replace('array<','Array<')
code=code.replace('out Array<ResourceName> result','Array<ResourceName>& result')
for name in ('ERR_EnemyEquipmentCallback','ERR_EnemyOpticsJob','ERR_EnemyOpticsInspection'):
code=re.sub(r'\b(?:ref )?'+name+r' (?=\w)',name+'* ',code)
code=code.replace('void ERR_EnemyOptics(','ERR_EnemyOptics(')
code=code.replace('EWeaponType type','int type').replace('foreach (','for (').replace('null','nullptr')
for name in ('ERR_EnemyEquipmentRules','ERR_HQ','Math','EStoragePurpose','EWeaponType'):code=code.replace(name+'.',name+'::')
for name in ('entity','child','weapon','sights','slot','job','manager','inventory','storage','inspection'):
code=re.sub(r'\b'+name+r'\.',name+'->',code)
code=code.replace('job->Operation.','job->Operation->')
code=re.sub(r'\b(bool|int|IEntity|SCR_AIGroup) (\w+);',r'\1 \2{};',code)
code=re.sub(r'\b(ERR_EnemyEquipmentCallback\*) (\w+);',r'\1 \2{};',code)
code=code.replace('\n}\n','\n};\n')
preamble=r'''
#include <cassert>
#include <algorithm>
#include <string>
#include <vector>
using string=std::string;using ResourceName=std::string;
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void Remove(int index){this->erase(this->begin()+index);}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}};
struct Entity;struct Group;struct Weapon;struct Manager;struct Inventory;struct Storage;struct Slot;struct Sights;struct ERR_GameMode{};
using IEntity=Entity*;using SCR_AIGroup=Group*;using BaseWeaponComponent=Weapon*;using BaseWeaponManagerComponent=Manager*;
using InventoryStorageManagerComponent=Inventory*;using WeaponAttachmentsStorageComponent=Storage*;using InventoryStorageSlot=Slot*;using AttachmentSlotComponent=Slot*;using BaseSightsComponent=Sights*;
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnFailed(){}virtual void OnAllComplete(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
struct EWeaponType{static const int WT_SNIPERRIFLE=1,WT_RIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4;};
struct EStoragePurpose{static const int PURPOSE_ANY=0;};struct Math{static int RandomInt(int,int){return 0;}};
struct Group{};
struct Slot{IEntity attached=nullptr;IEntity GetAttachedEntity(){return attached;}};
struct Storage{Array<Slot*>slots;int GetSlotsCount(){return slots.Count();}Slot* GetSlot(int n){return slots[n];}};
struct Sights{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
struct Weapon{IEntity owner=nullptr;int kind=EWeaponType::WT_RIFLE;Sights*sights=nullptr;Array<Slot*>slots;
IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}Sights* GetAttachedSights(){return sights;}void GetAttachments(Array<Slot*>&out){out=slots;}};
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&out){out=weapons;}};
struct Entity{Manager*manager=nullptr;Inventory*inventory=nullptr;Weapon*weapon=nullptr;Storage*storage=nullptr;
Entity*child=nullptr,*sibling=nullptr;Group*group=nullptr;bool eligible=true,scope2D=false,scope2DPip=false,scopePip=false;
IEntity GetChildren(){return child;}IEntity GetSibling(){return sibling;}};
struct Inventory{int submits=0,checks=0;bool accept=true,fit=true;int callback=0;ScriptedInventoryOperationCallback*last=nullptr;Array<int>requested;
bool CanInsertResourceInStorage(ResourceName,Storage*,int){checks++;return fit;}
bool TrySpawnPrefabToStorage(ResourceName,Storage*,int slot,int,ScriptedInventoryOperationCallback*cb){submits++;requested.Insert(slot);last=cb;
if(callback==1){cb->OnComplete();}if(callback==2){cb->OnFailed();}return accept;}};
struct ERR_EnemyEquipmentRules{static bool Eligible(ERR_GameMode* mode,Group*group,IEntity actor){return mode&&group&&actor&&actor->eligible&&actor->group==group;}};
struct ERR_HQ{static void Event(string,string){}};
'''
# Enforce class arguments are reference types.
code=re.sub(r'\bERR_GameMode (?=\w)','ERR_GameMode* ',code)
main=r'''
struct Fixture{ERR_GameMode mode;Group group,other;Entity actor,rifle;Weapon weapon;Manager manager;Inventory inv;Storage storage;Slot slot;
Fixture(){actor.group=&group;actor.manager=&manager;actor.inventory=&inv;manager.weapons={&rifle};rifle.weapon=&weapon;rifle.storage=&storage;weapon.owner=&rifle;storage.slots={&slot};}
};
int main(){
// Existing mounted/nested/sights magnified optics are preserved. Occupied red dots aren't overwritten.
for(int style=0;style<3;style++){Fixture f;Entity optic,adapter;Sights sights;Slot attach;
optic.scope2D=style==0;optic.scope2DPip=style==1;optic.scopePip=style==2;if(style==0){f.rifle.child=&adapter;adapter.child=&optic;}
if(style==1){sights.owner=&optic;f.weapon.sights=&sights;}
if(style==2){attach.attached=&optic;f.weapon.slots={&attach};}
ERR_EnemyOptics s(&f.actor,&f.group);assert(s.Check(&f.mode));assert(f.inv.submits==0&&s.m_Jobs[0]->Confirmed);}
{Fixture f;Entity reddot;f.slot.attached=&reddot;ERR_EnemyOptics s(&f.actor,&f.group);for(int i=0;i<6;i++)s.Check(&f.mode);assert(f.inv.submits==0);}
// Positive grant targets one concrete native free compatible slot; accepted unknown is never repeated.
{Fixture f;ERR_EnemyOptics s(&f.actor,&f.group);assert(!s.Check(&f.mode));assert(f.inv.submits==1&&f.inv.requested[0]==0);
for(int i=0;i<20;i++){s.Check(&f.mode);}assert(f.inv.submits==1&&s.m_Checks==5&&s.m_Jobs[0]->Terminal);
f.inv.last->OnFailed();s.Check(&f.mode);assert(f.inv.submits==1);}
// Both sync/async success terminate even if the optic disappears before physical observation.
for(int sync=0;sync<2;sync++){Fixture f;f.inv.callback=sync;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);
if(!sync){f.inv.last->OnAllComplete();}assert(s.Check(&f.mode));assert(f.inv.submits==1&&!s.m_Jobs[0]->Confirmed);}
// Callback first terminal result wins; never turn a success into another grant.
{Fixture f;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);f.inv.last->OnComplete();f.inv.last->OnFailed();s.Check(&f.mode);assert(f.inv.submits==1);}
// Explicit failures permit a different prefab/mount, but only one request per check and never fifth.
for(int kind=0;kind<3;kind++){Fixture f;f.inv.accept=kind!=0;f.inv.callback=kind==1?2:0;ERR_EnemyOptics s(&f.actor,&f.group);
for(int i=0;i<5;i++){s.Check(&f.mode);if(kind==2&&f.inv.last)f.inv.last->OnAllFailed();}
assert(f.inv.submits==4&&s.m_Jobs[0]->Rejected.Count()>=3);assert(s.m_Jobs[0]->Attempt==48);}
{Fixture f;f.inv.accept=false;f.inv.callback=1;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);s.Check(&f.mode);assert(f.inv.submits==1);}
// Delayed inventory is bounded; fifth check can observe a starting rifle but cannot issue it.
{Fixture f;f.actor.inventory=nullptr;ERR_EnemyOptics s(&f.actor,&f.group);for(int i=0;i<4;i++)assert(!s.Check(&f.mode));f.actor.inventory=&f.inv;assert(s.Check(&f.mode));assert(f.inv.submits==0);}
{Fixture f;f.inv.fit=false;ERR_EnemyOptics s(&f.actor,&f.group);for(int i=0;i<5;i++)s.Check(&f.mode);assert(f.inv.submits==0&&f.inv.checks==28);}
// Exact original actor and original physical weapon identity are terminal; no picked-up replacements.
{Fixture f;f.inv.fit=false;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);Entity replacement;replacement.weapon=&f.weapon;replacement.storage=&f.storage;
f.manager.weapons={&replacement};f.inv.fit=true;assert(s.Check(&f.mode));f.manager.weapons={&f.rifle};s.Check(&f.mode);assert(f.inv.submits==0&&s.m_Jobs.Count()==1);}
{Fixture f;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);f.actor.group=&f.other;assert(s.Check(&f.mode));f.actor.group=&f.group;f.inv.last->OnFailed();s.Check(&f.mode);assert(f.inv.submits==1);}
{Fixture f;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);s.Stop();f.inv.last->OnFailed();s.Check(&f.mode);assert(f.inv.submits==1);}
{Fixture f;f.actor.eligible=false;ERR_EnemyOptics s(&f.actor,&f.group);assert(s.Check(&f.mode));assert(f.inv.submits==0);}
// Duplicate native weapon roster entries don't create duplicate requests; nonrifles are ignored.
{Fixture f;f.manager.weapons={&f.rifle,&f.rifle};ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);assert(f.inv.submits==1&&s.m_Jobs.Count()==1);}
{Fixture f;f.weapon.kind=EWeaponType::WT_HANDGUN;ERR_EnemyOptics s(&f.actor,&f.group);for(int i=0;i<5;i++)s.Check(&f.mode);assert(f.inv.submits==0);}
// Malformed/oversized hierarchies fail closed, including cycles and too-deep adapters.
{Fixture f;f.rifle.child=&f.rifle;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);assert(f.inv.submits==0);}
{Fixture f;Entity child;f.rifle.child=&child;child.sibling=&child;ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);assert(f.inv.submits==0);}
{Fixture f;for(int i=0;i<17;i++)f.weapon.slots.Insert(&f.slot);ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);assert(f.inv.submits==0);}
{Fixture f;for(int i=0;i<17;i++)f.storage.slots.Insert(&f.slot);ERR_EnemyOptics s(&f.actor,&f.group);s.Check(&f.mode);assert(f.inv.submits==0);}
{Fixture f;for(int i=0;i<9;i++)f.manager.weapons.Insert(&f.rifle);ERR_EnemyOptics s(&f.actor,&f.group);assert(s.Check(&f.mode));assert(f.inv.submits==0);}
}
'''
run(preamble+code+main)
print('Enemy optics actual-service ownership, preservation, callback, deadline and bounded-inspection policies passed')
+20 -4
View File
@@ -1,9 +1,11 @@
"""Execute both production monitor bodies; native hint/camera boundaries are fakes."""
from policy_harness import ROOT, body, run
GUIDE=ROOT/'addons/core/Scripts/Game/ERR/ERR_PlayerGuide.c'
from pathlib import Path
import os
GUIDE=Path(os.environ.get('ERR_GUIDE_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/ERR_PlayerGuide.c'))
OBSERVER=ROOT/'addons/core/Scripts/Game/ERR/ERR_Observer.c'
def cpp(text):
text=text.replace('protected ', '')
text=text.replace('protected ', '').replace('override ', '').replace('super.OnControlledEntityChanged(from, to);', 'nativeChanges++;')
for name in ('ERR_GameMode','ERR_Phase','ERR_ObserverReason','ERR_Actors','ERR_ObjectiveText','SCR_HintManagerComponent','ERR_ObserverGuidance','Resource','ETransformMode','SCR_ManualCamera','SCR_RespawnSystemComponent','RplId'):
text=text.replace(name+'.',name+'::')
for typename in ('ERR_GameMode','SCR_HintManagerComponent','Resource','SCR_RespawnSystemComponent','CameraManager'):
@@ -12,14 +14,14 @@ def cpp(text):
text=text.replace(variable+'.',variable+'->')
text=text.replace('GetGame().','GetGame()->').replace('EntitySpawnParams params = new EntitySpawnParams();','EntitySpawnParams params;')
return text
methods=cpp(body(GUIDE,'protected void ERR_UpdateGuide('))+'\n'+cpp(body(OBSERVER,'protected void ERR_UpdateObserverClient('))
methods=cpp(body(GUIDE,'override void OnControlledEntityChanged('))+'\n'+cpp(body(GUIDE,'protected void ERR_UpdateGuide('))+'\n'+cpp(body(OBSERVER,'protected void ERR_UpdateObserverClient('))
guidance=cpp(body(OBSERVER,'static string Message('))+'\n'+cpp(body(OBSERVER,'static bool Refresh('))
run(r'''#include <cassert>
#include <string>
struct string:std::string {using std::string::string;using std::string::operator=;string(std::string s):std::string(s){}bool IsEmpty()const{return empty();}};
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION};}
namespace ERR_ObserverReason {enum {NONE,SPENT_LIFE,LATE_EXTRACTION,SPAWN_UNAVAILABLE};}
struct Actor {bool alive=true;bool unconscious=false;} actor;
struct Actor {bool alive=true;bool unconscious=false;} actor;using IEntity=Actor*;
struct ERR_Actors {static bool Alive(Actor* a){return a&&a->alive;}};
struct ERR_GameMode {int phase=ERR_Phase::PRISON;bool active=true;string message="prison";static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}int Phase(){return phase;}bool Active(){return active;}} mode;
ERR_GameMode* ERR_GameMode::current=&mode;
@@ -42,6 +44,7 @@ struct RplId {static int Invalid(){return -1;}};
struct Game {int spawns=0;SCR_ManualCamera* SpawnEntityPrefab(Resource*,int,EntitySpawnParams){spawns++;return &camera;}int GetWorld(){return 1;}CameraManager* GetCameraManager(){return &manager;}} game;
Game* GetGame(){return &game;}
struct Controller {
int nativeChanges=0,starts=0;void ERR_StartGuide(){starts++;}
int m_ERRGuidePhase=-1;string m_ERRGuideMessage;
Actor* controlled=&actor;int m_ERRObserverReason=ERR_ObserverReason::NONE;
SCR_ManualCamera* m_ERRObserverCamera=nullptr;Vec m_ERRObserverAnchor;
@@ -64,6 +67,19 @@ int main(){
mode.message="transmission interrupted";hints.accepts=false;g.ERR_UpdateGuide();assert(g.m_ERRGuideMessage=="prison");
hints.accepts=true;g.ERR_UpdateGuide();assert(hints.shown==2&&g.m_ERRGuideMessage==mode.message);
mode.phase=ERR_Phase::RADIO_SEARCH;g.ERR_UpdateGuide();assert(hints.shown==3);
// Reacquiring a character in the same phase clears delivery once; native
// lifecycle and the existing monitor remain responsible for actual delivery.
Actor replacement;int shown=hints.shown;
g.OnControlledEntityChanged(&actor,&replacement);g.controlled=&replacement;
assert(g.nativeChanges==1&&g.starts==1&&g.m_ERRGuidePhase==-1);
hints.accepts=false;g.ERR_UpdateGuide();assert(hints.shown==shown&&g.m_ERRGuidePhase==-1);
hints.accepts=true;g.ERR_UpdateGuide();assert(hints.shown==shown+1);
g.ERR_UpdateGuide();assert(hints.shown==shown+1);
g.OnControlledEntityChanged(&replacement,&replacement);g.ERR_UpdateGuide();assert(hints.shown==shown+1);
g.OnControlledEntityChanged(&replacement,nullptr);g.controlled=nullptr;
g.ERR_UpdateGuide();assert(hints.shown==shown+1);
g.OnControlledEntityChanged(nullptr,&replacement);g.controlled=&replacement;
g.ERR_UpdateGuide();assert(hints.shown==shown+2&&g.nativeChanges==4&&g.starts==4);
// Explicit observation, death and absence suppress ordinary phase instructions.
for(int excluded=0;excluded<3;excluded++){
Controller c;if(excluded==0)c.m_ERRObserverReason=ERR_ObserverReason::SPENT_LIFE;
+129
View File
@@ -0,0 +1,129 @@
"""Execute production cover-fixture event transitions with native boundaries mocked."""
from pathlib import Path
import os,re,subprocess,sys
from policy_harness import ROOT,body,run
P=Path(os.environ.get('ERR_CONVOY_COVER_SOURCE',ROOT/'addons/chat/Scripts/Game/ERR/ERR_NativeConvoyCoverProbe.c'))
s=P.read_text()
def cpp(s):
s=s.replace('protected ','').replace('ref ','').replace('foreach (','for (').replace('null','nullptr')
for t in ('ERR_NativeConvoyCoverReport','ERR_HQUnit','ERR_HQReport','ERR_HQRoute','ERR_ConvoyCombatOrder'):
s=re.sub(r'\b'+t+r' (?=\w)',t+'* ',s)
for v in ('entry','unit','report','order','route','observer','m_Lead','m_Damage'):
s=re.sub(r'\b'+v+r'\.',v+'->',s)
for field in ('Report','PendingReport','Uplink','Utility','Combat','Entity'):
s=s.replace('->'+field+'.','->'+field+'->')
return s
methods='\n'.join(cpp(body(P,k)) for k in ('protected ERR_NativeConvoyCoverReport Find(', 'void Observed(', 'void Accepted(', 'void Delivered(', 'void Stop('))
run(r'''
#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
using string=std::string;
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}void Insert(T x){this->push_back(x);}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}};
struct Actor{float origin=7;float GetOrigin(){return origin;}};using IEntity=Actor*;
struct ERR_HQReport{int MessageId=1;IEntity Target=nullptr;ERR_HQReport* Snapshot(){return new ERR_HQReport(*this);}};
struct ERR_HQRoute{bool Failed=false,Downlink=false;float StartedAt=1;int Cursor=0;Array<int>Nodes={1,2};};
struct Utility{IEntity observer=nullptr;IEntity ERR_ResponseVisualObserver(ERR_HQReport*,float){return observer;}};
struct ERR_HQUnit{ERR_HQReport* PendingReport=nullptr;ERR_HQRoute* Uplink=nullptr;struct Utility* Utility=nullptr;};
struct ERR_NativeConvoyCoverReport{ERR_HQReport* Report=nullptr;ERR_HQRoute* Uplink=nullptr;bool Accepted=false;};
struct ERR_ConvoyCombatOrder{int Group=1,CommandId=1,ReportId=1;bool Hold=true;float ObservedAt=10;};
struct Combat{bool Held=false;int LastCommandId=1;};
struct Lead{int Group=1;struct Combat* Combat=nullptr;bool Waypoint=false;int RouteIndex=2;Actor* Entity=nullptr;};
struct Damage{bool enabled=true;int writes=0;void EnableDamageHandling(bool b){enabled=b;writes++;}};
struct Probe{
bool m_Stopped=false,m_Failed=false,m_Held=false,m_Resumed=false,m_Protected=false,m_DamageWasEnabled=true;
int m_RouteIndex=0,checks=0;float m_HeldAt=0,m_ResumedAt=0,m_HoldPosition=0,m_ResumePosition=0;
Lead* m_Lead=nullptr;IEntity m_Player=nullptr;Damage* m_Damage=nullptr;
Array<IEntity>m_Forces;Array<ERR_NativeConvoyCoverReport*>m_Reports;inline static Probe* s_Active=nullptr;
bool Check(bool ok,string){checks++;
if(!ok){m_Failed=true;Stop();}return ok;}
'''+methods+r'''
};
struct Setup{
Actor player,enemy,stranger;ERR_HQReport report;ERR_HQRoute uplink,downlink;Utility utility;ERR_HQUnit unit;
Combat combat;Lead lead;ERR_ConvoyCombatOrder order;Probe p;Damage damage;
Setup(){report.Target=&player;utility.observer=&enemy;unit.PendingReport=&report;unit.Uplink=&uplink;unit.Utility=&utility;
lead.Combat=&combat;lead.Entity=&enemy;p.m_Lead=&lead;p.m_Player=&player;p.m_Forces={&enemy};
p.m_Damage=&damage;p.m_Protected=true;damage.enabled=false;Probe::s_Active=&p;downlink.Downlink=true;downlink.Cursor=1;}
void observed(){p.Observed(&unit,20);}
void accepted(){uplink.Cursor=2;p.Accepted(&report,22);}
void hold(){combat.Held=true;lead.Waypoint=false;p.Delivered(&order,&downlink,true,30);}
void resume(){order.Hold=false;order.CommandId=2;combat.LastCommandId=2;combat.Held=false;lead.Waypoint=true;p.Delivered(&order,&downlink,false,60010);}
};
int main(){
// Observation snapshots the real pending report only for the existing prisoner and original observer.
Setup s;s.observed();assert(s.p.m_Reports.Count()==1);auto snapshot=s.p.m_Reports[0]->Report;
assert(snapshot!=&s.report&&snapshot->Target==&s.player);s.report.MessageId=9;assert(snapshot->MessageId==1);s.report.MessageId=1;
s.p.Accepted(&s.report,21);assert(!s.p.m_Reports[0]->Accepted); // radio still in transit
s.accepted();assert(s.p.m_Reports[0]->Accepted);s.hold();assert(s.p.m_Held&&!s.p.m_Failed&&s.p.m_RouteIndex==2&&s.p.m_HeldAt==30);
s.p.Delivered(&s.order,&s.downlink,false,40);assert(s.p.m_HeldAt==30); // repeated HOLD cannot replace first measurement
s.resume();assert(s.p.m_Resumed&&!s.p.m_Failed&&s.p.m_ResumedAt==60010);
s.p.Stop();assert(s.damage.enabled&&s.damage.writes==1&&Probe::s_Active==nullptr);s.p.Stop();assert(s.damage.writes==1);
int checks=s.p.checks;s.p.Delivered(&s.order,&s.downlink,false,61000);s.p.Observed(&s.unit,61000);assert(s.p.checks==checks&&s.p.m_Reports.Count()==1);
for(int exclusion=0;exclusion<5;exclusion++){
Setup x;
if(exclusion==0)x.report.Target=&x.stranger;
if(exclusion==1)x.unit.Uplink=nullptr;
if(exclusion==2)x.utility.observer=nullptr;
if(exclusion==3)x.utility.observer=&x.stranger;
if(exclusion==4)x.p.m_Reports.resize(64,nullptr);
int before=x.p.m_Reports.Count();x.observed();assert(x.p.m_Reports.Count()==before);
}
// Failed or unstarted uplinks cannot establish delivered evidence.
for(int invalid=0;invalid<3;invalid++){
Setup x;x.observed();x.uplink.Cursor=2;
if(invalid==0)x.uplink.Failed=true;
if(invalid==1)x.uplink.StartedAt=-1;
if(invalid==2)x.uplink.Cursor=1;
x.p.Accepted(&x.report,30);assert(!x.p.m_Reports[0]->Accepted);x.hold();assert(x.p.m_Failed&&!x.p.m_Held&&x.damage.enabled);
}
// Rejected production order is ignored; completed physical downlink requires exact cursor/direction.
for(int ignored=0;ignored<3;ignored++){
Setup x;x.observed();x.accepted();
if(ignored==0)x.order.Group=2;
if(ignored==1)x.combat.LastCommandId=2;
if(ignored==2)x.downlink.Failed=true;
x.hold();assert(!x.p.m_Held&&!x.p.m_Failed&&x.p.checks==0);
}
for(int invalid=0;invalid<3;invalid++){
Setup x;x.observed();x.accepted();
if(invalid==0)x.downlink.Downlink=false;
if(invalid==1)x.downlink.Cursor=0;
if(invalid==2)x.downlink.StartedAt=-1;
x.hold();assert(x.p.m_Failed&&!x.p.m_Held);
}
// A successful command cannot waive waypoint ownership, preserved route index or quiet period.
for(int invalid=0;invalid<4;invalid++){
Setup x;x.observed();x.accepted();x.hold();x.order.Hold=false;x.order.CommandId=2;x.combat.LastCommandId=2;
x.combat.Held=false;x.lead.Waypoint=true;bool hadWaypoint=false;float now=60010;
if(invalid==0)x.lead.RouteIndex=3;
if(invalid==1)hadWaypoint=true;
if(invalid==2)x.lead.Waypoint=false;
if(invalid==3)now=60009;
x.p.Delivered(&x.order,&x.downlink,hadWaypoint,now);assert(x.p.m_Failed&&!x.p.m_Resumed&&x.damage.enabled);
}
Setup previouslyDisabled;previouslyDisabled.p.m_DamageWasEnabled=false;previouslyDisabled.p.Stop();assert(!previouslyDisabled.damage.enabled&&previouslyDisabled.damage.writes==1);
}
''')
assert s.startswith('#ifdef WORKBENCH')
for signature,base,hook in [('protected override void Observe(', 'super.Observe(unit, now)', 'proof.Observed'),('protected override void Accept(', 'super.Accept(report, now)', 'proof.Accepted'),('protected override void DeliverConvoyOrder(', 'super.DeliverConvoyOrder(unit, now)', 'proof.Delivered')]:
method=body(P,signature);assert method.index(base)<method.index(hook)
assert 'entry.Report = unit.PendingReport.Snapshot()' in s
for forbidden in ('ApplyCombatOrder(', 'PendingReport = new', 'new ERR_HQRoute', 'SetAmmoCount(', 'TrySpawnPrefabToStorage(', 'SetOrigin('):assert forbidden not in s
convoy=(ROOT/'addons/chat/Scripts/Game/ERR/ERR_NativeConvoyProbe.c').read_text()
assert convoy.index('all six native vehicles drove at least 20m')<convoy.index('m_Cover = new')
assert 'if (m_Step == 4) return m_Cover.Tick(hq, now);' in convoy
assert 'void Stop() { if (m_Cover) m_Cover.Stop(); }' in convoy
smoke=(ROOT/'addons/chat/Scripts/Game/ERR/ERR_NativeSmoke.c').read_text();assert 'if (m_ERRConvoyProbe) m_ERRConvoyProbe.Stop();' in smoke
runner=ROOT/'tools/headless_workbench.py'
for variant in ('victory','hq-body'):
result=subprocess.run([sys.executable,str(runner),'--smoke',variant,'--convoy-cover','--project','chat','--rounds','1','--timeout','900','--compat','/tmp/erri-unused-cover-compat','--profile','/tmp/erri-unused-cover-profile'],capture_output=True,text=True)
assert result.returncode==2 and '--convoy-cover requires --smoke convoy' in result.stderr,result.stderr
# Cover receives its own full budget after ordinary convoy proof; default budget stays bounded.
assert 'if (m_ERRTestConvoy) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 540000;' in smoke
assert 'if (ERR_NativeConvoyCoverProbe.Enabled()) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 840000;' in smoke
result=subprocess.run([sys.executable,str(runner),'--smoke','convoy','--convoy-cover','--project','chat','--rounds','1','--timeout','899','--compat','/tmp/erri-unused-cover-compat','--profile','/tmp/erri-unused-cover-profile'],capture_output=True,text=True)
assert result.returncode==2 and '--convoy-cover requires timeout at least900 seconds' in result.stderr,result.stderr
assert "if a.convoy_cover: command += ['-errConvoyCover', '1']" in runner.read_text()
print('PASS: actual convoy cover observation/snapshot/uplink/HOLD/RESUME/cleanup transitions; native boundaries mocked, non-convoy runner opt-in refused')
+55
View File
@@ -0,0 +1,55 @@
"""Actual WORKBENCH-only native-context fallback; no production admission bypass."""
import os
from pathlib import Path
from policy_harness import ROOT,body,run
base=Path(os.environ.get('ERR_VEHICLE_DIAGNOSTICS_ROOT',str(ROOT)))
source=base/'addons/core/Scripts/Game/ERR/ERR_NativeVehicleSecurityProbe.c'
wrapped=body(source,'protected bool DriverAvailable(').replace('protected ','').replace('m_DriverAction.','m_DriverAction->')
run('''#include <cassert>
struct Action {bool allowed=false,fallback=true;int context=-1,checks=0,diagnostics=0,bindings=0;bool CanBePerformedScript(int){checks++;return allowed;}void ERR_ProbeRejectedEntry(int){diagnostics++;}int ERR_ProbeResolvedDoor(int){return context;}bool ERR_ProbeDeclaredDriverDoor(int){bindings++;return fallback;}};
struct Probe{Action* m_DriverAction;int m_Player=7;
'''+wrapped+'''
};
int main(){Action a;Probe p{&a};a.allowed=true;assert(p.DriverAvailable()&&a.checks==1&&a.diagnostics==0&&a.bindings==0);
a.allowed=false;a.context=2;assert(!p.DriverAvailable()&&a.diagnostics==1&&a.bindings==0); // real selected context cannot be overridden
a.context=-1;assert(p.DriverAvailable()&&a.diagnostics==2&&a.bindings==1);
a.fallback=false;assert(!p.DriverAvailable()&&a.diagnostics==3&&a.bindings==2);
}
''')
method=body(source,'bool ERR_ProbeDeclaredDriverDoor(')
method=method.replace('BaseCompartmentSlot seat','BaseCompartmentSlot* seat').replace('array<int> doors = {};','Array doors;').replace('seat.','seat->').replace('m_CompartmentManager.','m_CompartmentManager->')
method=method.replace('SCR_CompartmentAccessComponent.','SCR_CompartmentAccessComponent::').replace('ECompartmentType.PILOT','PILOT')
run('''#include <cassert>
#include <vector>
using IEntity=int;enum {PILOT=1,CARGO=2};
struct Array:std::vector<int>{int Count(){return size();}};
struct BaseCompartmentSlot{int type=PILOT;std::vector<int> doors={3};void GetAvailableDoorIndices(Array& a){a.assign(doors.begin(),doors.end());}};
struct Manager {int valid=3;bool GetDoorInfo(int i){return i==valid;}};
struct SCR_CompartmentAccessComponent{static int GetCompartmentType(BaseCompartmentSlot* s){return s->type;}};
void PrintFormat(const char*,int,int,bool){}
struct Action {Manager* m_CompartmentManager;BaseCompartmentSlot* seat;int context=-1,stored=-1,checks=0,sets=0,diagnostics=0;bool nativeAllowed=true;
int GetRelevantDoorIndex(IEntity){return context;}BaseCompartmentSlot* GetCompartmentSlot(){return seat;}
int GetCompartmentDoorInfoIndex(){return stored;}void SetCompartmentDoorInfoIndex(int i){stored=i;sets++;}
bool CanBePerformedScript(IEntity){checks++;return nativeAllowed&&stored==3;}
void ERR_ProbeRejectedEntry(IEntity){diagnostics++;}
'''+method+'''
};
int main(){Manager m;BaseCompartmentSlot s;Action a;a.m_CompartmentManager=&m;a.seat=&s;
assert(a.ERR_ProbeDeclaredDriverDoor(7)&&a.stored==-1&&a.checks==1&&a.sets==2); // derived door 3, never hardcoded driver 0
a.nativeAllowed=false;assert(!a.ERR_ProbeDeclaredDriverDoor(7)&&a.stored==-1&&a.diagnostics==1&&a.sets==4);
a.context=2;assert(!a.ERR_ProbeDeclaredDriverDoor(7)&&a.sets==4);a.context=-1;
s.type=CARGO;assert(!a.ERR_ProbeDeclaredDriverDoor(7)&&a.sets==4);s.type=PILOT;
s.doors={};assert(!a.ERR_ProbeDeclaredDriverDoor(7));s.doors={3,4};assert(!a.ERR_ProbeDeclaredDriverDoor(7));
s.doors={4};assert(!a.ERR_ProbeDeclaredDriverDoor(7)&&a.sets==4&&a.checks==2);
a.seat=nullptr;assert(!a.ERR_ProbeDeclaredDriverDoor(7));a.seat=&s;a.m_CompartmentManager=nullptr;assert(!a.ERR_ProbeDeclaredDriverDoor(7));
}
''')
diagnostics=body(source,'void ERR_ProbeRejectedEntry(')
for forbidden in ('SetCompartmentDoorInfoIndex(', 'SetAffiliatedFaction(', 'ClearAffiliatedFaction(', 'GetInVehicle(', 'EnableDamageHandling(', 'TryBreach('):assert forbidden not in diagnostics
assert 'GetCannotPerformReason()' in diagnostics and 'GetRelevantDoorIndex(user)' in diagnostics
assert 'CanGetInVehicleViaDoor' in diagnostics and 'GetStoredResources' in diagnostics
assert diagnostics.index('door >= 0 && m_CompartmentManager.GetDoorInfo(door)') < diagnostics.index('m_CompartmentManager.GetDoorUser(door)')
assert 'if (index < 0 || !m_CompartmentManager.GetDoorInfo(index))' in diagnostics
assert 'missing or invalid context; no indexed native query issued' in diagnostics
assert 'modded class ERR_SecureGetInAction' in source.read_text() and source.read_text().startswith('#ifdef WORKBENCH')
print('PASS: actual diagnostic fallback runs only on failed missing-context call, derives unique native pilot door, preserves stock eligibility and restores prior index on success/failure; diagnostics mutate no game state.')
+175
View File
@@ -0,0 +1,175 @@
"""Execute staged/production security methods; native held UI/replication pending."""
import os,re
from pathlib import Path
from policy_harness import ROOT,body,run
base=Path(os.environ.get('ERR_VEHICLE_SECURITY_ROOT',str(ROOT)))
component=base/'addons/core/Scripts/Game/ERR/ERR_VehicleSecurityComponent.c'
actions=base/'addons/core/Scripts/Game/ERR/ERR_VehicleSecurityActions.c'
def translate(value):
value=value.replace('out string reason','string& reason').replace('string.Empty','string{}').replace('override ','')
for t in ('ERR_GameMode','Physics','ERR_VehicleSecurityComponent'):
value=re.sub(r'\b'+t+r' (\w+)',t+r'* \1',value)
for t in ('ERR_GameMode','ERR_Actors','Replication','CompartmentAccessComponent','ERR_VehicleSecurityComponent','vector','Vehicle','ERR_Phase'):
value=value.replace(t+'.',t+'::')
for var in ('mode','physics','user','entity','security'):
value=value.replace(var+'.',var+'->')
value=value.replace('GetOwner().','GetOwner()->').replace('mode->Players().','mode->Players()->')
value=value.replace('super.','Base::').replace('null','nullptr')
value=re.sub(r'(?<![\w.])(\d+\.\d+)(?![\w.])',r'\1f',value)
return value
# Execute the actual preparation hook separately from breach eligibility.
configuration=translate(body(component,'bool Configure('))
run("""#include <cassert>
struct Entity {bool vehicle=true,alive=true;};using IEntity=Entity*;
struct Vehicle {static IEntity Cast(IEntity e){return e&&e->vehicle?e:nullptr;}};
struct ERR_Phase {static const int PREPARING=1,ACTIVE=2;};
struct ERR_GameMode {int phase=ERR_Phase::PREPARING;static ERR_GameMode* current;
static ERR_GameMode* Get(){return current;}int Phase(){return phase;}};
ERR_GameMode* ERR_GameMode::current=nullptr;
struct ERR_Actors {static IEntity observed;static bool Alive(IEntity e){observed=e;return e&&e->alive;}};
IEntity ERR_Actors::observed=nullptr;
struct Replication {static bool server;static int bumps;static bool IsServer(){return server;}static void BumpMe(){bumps++;}};
bool Replication::server=true;int Replication::bumps=0;
struct Security {IEntity owner=nullptr;bool m_Configured=false,m_Breached=false;IEntity GetOwner(){return owner;}
"""+configuration+"""
};
int main(){
// Reject every invalid preparation boundary without replication or state changes.
for(int variant=0;variant<6;variant++){
ERR_GameMode mode;ERR_GameMode::current=&mode;Entity vehicle;Security s;s.owner=&vehicle;
Replication::server=true;Replication::bumps=0;
if(variant==0)Replication::server=false;
if(variant==1)ERR_GameMode::current=nullptr;
if(variant==2)mode.phase=ERR_Phase::ACTIVE;
if(variant==3)s.owner=nullptr;
if(variant==4)vehicle.vehicle=false;
if(variant==5)vehicle.alive=false;
assert(!s.Configure()&&!s.m_Configured&&!s.m_Breached&&Replication::bumps==0);
}
ERR_GameMode mode;ERR_GameMode::current=&mode;Replication::server=true;
Entity vehicle,unrelated;unrelated.alive=false;Security s;s.owner=&vehicle;
assert(s.Configure()&&s.m_Configured&&!s.m_Breached&&Replication::bumps==1);
assert(ERR_Actors::observed==&vehicle); // Liveness is checked on this component's exact vehicle.
assert(s.Configure()&&Replication::bumps==1&&!s.m_Breached);
s.m_Breached=true;assert(s.Configure()&&s.m_Breached&&s.m_Configured&&Replication::bumps==1);
// Invalid repeat calls do not relock or reset configured state.
vehicle.alive=false;assert(!s.Configure()&&s.m_Breached&&s.m_Configured&&Replication::bumps==1);vehicle.alive=true;
mode.phase=ERR_Phase::ACTIVE;assert(!s.Configure()&&s.m_Breached&&s.m_Configured&&Replication::bumps==1);
mode.phase=ERR_Phase::PREPARING;Replication::server=false;
assert(!s.Configure()&&s.m_Breached&&s.m_Configured&&Replication::bumps==1);
}
""")
methods='\n'.join(translate(body(component,s)) for s in ('bool Locked(', 'static bool Motion(', 'static bool Reach(', 'bool CanBreach(', 'bool TryBreach('))
run('''#include <cassert>
#include <cmath>
#include <string>
using string=std::string;
struct vector {float x=0; float Length(){return x;} static float Distance(vector a,vector b){return std::abs(a.x-b.x);} };
struct Physics {vector speed,angular; vector GetVelocity(){return speed;} vector GetAngularVelocity(){return angular;} };
struct Entity {bool player=true,awake=true,alive=true,aboard=false; vector pos; Physics* physics=nullptr; vector GetOrigin(){return pos;} Physics* GetPhysics(){return physics;} vector CoordToParent(vector){return pos;} };
using IEntity=Entity*;
struct Roster {IEntity admitted=nullptr; bool CurrentActor(IEntity e){return e&&e==admitted;} };
struct ERR_GameMode {bool active=true;Roster roster;bool rosterExists=true; static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}bool Active(){return active;} Roster* Players(){return rosterExists?&roster:nullptr;} };
ERR_GameMode* ERR_GameMode::current=nullptr;
struct ERR_Actors {static bool Player(IEntity e){return e&&e->player;}static bool CanFight(IEntity e){return e&&e->alive&&e->awake;}static bool Alive(IEntity e){return e&&e->alive;} };
struct Replication {static bool server;static int bumps; static bool IsServer(){return server;}static void BumpMe(){bumps++;} };bool Replication::server=true;int Replication::bumps=0;
struct CompartmentAccessComponent {static bool GetVehicleIn(IEntity e){return e&&e->aboard;} };
struct Security {bool m_Configured=true,m_Breached=false,empty=true,clear=true;IEntity owner;vector m_LockAnchor; IEntity GetOwner(){return owner;}bool EmptyVehicle(){return empty;}bool ClearReach(IEntity,vector){return clear;}
'''+methods+'''
};
int main(){
Physics physics;Entity vehicle,player,other;vehicle.physics=&physics;
ERR_GameMode mode; ERR_GameMode::current=&mode;mode.roster.admitted=&player;
Security s;s.owner=&vehicle;string reason;
assert(s.CanBreach(&player,reason)&&reason.empty());
for(float bad : {-1.f,0.251f}) assert(!Security::Motion(bad,0));
assert(Security::Motion(0.25,0.1)&&!Security::Motion(0,0.101));
assert(Security::Reach(2)&&!Security::Reach(-1)&&!Security::Reach(2.001));
s.m_Configured=false;assert(!s.TryBreach(&player));s.m_Configured=true;
mode.active=false;assert(!s.TryBreach(&player));mode.active=true;
player.player=false;assert(!s.TryBreach(&player));player.player=true;
player.awake=false;assert(!s.TryBreach(&player));player.awake=true;
player.alive=false;assert(!s.TryBreach(&player));player.alive=true;
player.aboard=true;assert(!s.TryBreach(&player));player.aboard=false;
vehicle.alive=false;assert(!s.TryBreach(&player));vehicle.alive=true;
vehicle.physics=nullptr;assert(!s.TryBreach(&player));vehicle.physics=&physics;
physics.speed.x=0.26;assert(!s.TryBreach(&player));physics.speed.x=0;
physics.angular.x=0.11;assert(!s.TryBreach(&player));physics.angular.x=0;
s.empty=false;assert(!s.TryBreach(&player));s.empty=true;
player.pos.x=2.01;assert(!s.TryBreach(&player));player.pos.x=2;
s.clear=false;assert(!s.CanBreach(&player,reason)&&reason.find("obstructed")!=string::npos);assert(!s.TryBreach(&player));s.clear=true;
// Body replacement, absent roster and direct replica execution cannot unlock.
assert(!s.TryBreach(&other));mode.roster.admitted=nullptr;assert(!s.TryBreach(&player));mode.roster.admitted=&player;
mode.rosterExists=false;assert(!s.TryBreach(&player));mode.rosterExists=true;
Replication::server=false;assert(!s.TryBreach(&player));Replication::server=true;
ERR_GameMode::current=nullptr;assert(!s.TryBreach(&player));ERR_GameMode::current=&mode;
assert(Replication::bumps==0&&s.Locked());
assert(s.TryBreach(&player)&&!s.Locked()&&Replication::bumps==1);
assert(!s.TryBreach(&player)&&!s.TryBreach(&other)&&Replication::bumps==1);
}
''')
class Section:
def __init__(self,name,next_name=None):
source=actions.read_text();self.source=source[source.index('class '+name):]
if next_name:self.source=self.source[:self.source.index('class '+next_name)]
def read_text(self):return self.source
for name,next_name in [('ERR_SecureGetInAction','ERR_SecureOpenVehicleDoorAction'),('ERR_SecureOpenVehicleDoorAction',None)]:
section=Section(name,next_name)
methods='\n'.join(translate(body(section,s)) for s in ('override bool CanBePerformedScript(', 'override void PerformAction('))
run('''#include <cassert>
#include <string>
using IEntity=int;
using string=std::string;
struct ERR_VehicleSecurityComponent {bool locked=true;static ERR_VehicleSecurityComponent* security;static ERR_VehicleSecurityComponent* Find(IEntity){return security;}bool Locked(){return locked;}};
ERR_VehicleSecurityComponent* ERR_VehicleSecurityComponent::security=nullptr;
struct Base {bool allowed=true;int calls=0;IEntity GetOwner(){return 42;}void SetCannotPerformReason(std::string){}bool CanBePerformedScript(IEntity){return allowed;}void PerformAction(IEntity,IEntity){calls++;}};
struct Action:Base {
'''+methods+'''
};
int main(){Action a;ERR_VehicleSecurityComponent s;ERR_VehicleSecurityComponent::security=&s;
a.PerformAction(42,7);assert(a.calls==0);s.locked=false;a.allowed=false;a.PerformAction(42,7);assert(a.calls==0);
a.allowed=true;a.PerformAction(43,7);assert(a.calls==0);a.PerformAction(42,7);assert(a.calls==1);
s.locked=true;a.PerformAction(42,7);assert(a.calls==1);
ERR_VehicleSecurityComponent::security=nullptr;a.PerformAction(42,7);assert(a.calls==2); // unrelated owner delegates native policy
}
''')
# The held action invokes only the owning security component on the server; its
# TryBreach path above performs fresh checks rather than trusting availability.
execution=translate(body(Section('ERR_ForceVehicleLockAction','ERR_SecureGetInAction'),'override void PerformAction('))
run("""#include <cassert>
using IEntity=int;
struct Replication {static bool server;static bool IsServer(){return server;}};bool Replication::server=false;
struct ERR_VehicleSecurityComponent {int calls=0,last=0;static ERR_VehicleSecurityComponent* security;static ERR_VehicleSecurityComponent* Find(IEntity){return security;}void TryBreach(IEntity user){calls++;last=user;}};
ERR_VehicleSecurityComponent* ERR_VehicleSecurityComponent::security=nullptr;
struct Action {IEntity GetOwner(){return 42;}
"""+execution+"""
};
int main(){Action a;ERR_VehicleSecurityComponent s;ERR_VehicleSecurityComponent::security=&s;
a.PerformAction(42,7);assert(s.calls==0);Replication::server=true;
a.PerformAction(43,7);assert(s.calls==0);a.PerformAction(42,7);assert(s.calls==1&&s.last==7);
ERR_VehicleSecurityComponent::security=nullptr;a.PerformAction(42,7);assert(s.calls==1);
}
""")
# Exact resource overrides cover both front seats, three separately attached rear
# seats and all four door actions without replacing physical vehicle resources.
prefabs=base/'addons/core/Prefabs/ERR/Vehicles'
uaz=(prefabs/'SupplyUAZ.et').read_text();rear=(prefabs/'SupplyUAZRearSeats.et').read_text()
assert '"{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et"' in uaz
assert '"{780AAF0A51AEE61A}Prefabs/Vehicles/Wheeled/UAZ469/VehParts/Seats/UAZ469_seats_rear.et"' in rear
assert uaz.count('OpenDoorAction ERR_SecureOpenVehicleDoorAction')==4
assert uaz.count('CompartmentAction ERR_SecureGetInAction')==2
assert rear.count('CompartmentAction ERR_SecureGetInAction')==3
for slot in ['Passenger_l02','Passenger_r02','Passenger_m02']:assert 'CargoCompartmentSlot '+slot in rear
assert 'SupplyUAZRearSeats.et' in uaz and 'Duration 4' in uaz and 'VisibilityRange 2' in uaz
assert uaz.count('-0.95 1.05 0.3')==2 # reach anchor matches visible held-action context
for signature,result in [('override bool HasLocalEffectOnlyScript(',False),('override bool CheckOnServerFirstScript(',True),('override bool CanBroadcastScript(',False)]:
assert 'return '+str(result).lower()+';' in body(Section('ERR_ForceVehicleLockAction','ERR_SecureGetInAction'),signature)
assert '[RplProp()] protected bool m_Breached;' in component.read_text()
assert 'modded class' not in actions.read_text()+component.read_text()
print('PASS: actual preparation Configure guards/idempotence/breach preservation, security eligibility/final current-body server mutation and all scoped action guards; all five seat/four door resource overrides. Native hold, prefab merge, replication and boarding remain unverified.')
@@ -0,0 +1,99 @@
"""Native fixture cleanup and real SiteService admission wrapper, without engine claims."""
import os,re
from pathlib import Path
from policy_harness import ROOT,body,run
base=Path(os.environ.get('ERR_VEHICLE_NATIVE_ROOT',str(ROOT)))
source=base/'addons/core/Scripts/Game/ERR/ERR_NativeVehicleSecurityProbe.c'
stop=body(source,'void Stop(').replace('null','nullptr')
stop=stop.replace('ChimeraCharacter character = ChimeraCharacter.Cast(m_Player);','ChimeraCharacter* character = m_Player;')
for name in ('m_Damage','m_Mode','character'):stop=stop.replace(name+'.',name+'->')
stop=stop.replace('m_Mode->Players().','m_Mode->Players()->').replace('ERR_Actors.','ERR_Actors::').replace('CompartmentAccessComponent.','CompartmentAccessComponent::')
run('''#include <cassert>
struct Damage {bool enabled=true;int changes=0;void EnableDamageHandling(bool b){enabled=b;changes++;}};
struct ChimeraCharacter {bool awake=true,aboard=false;int teleports=0;void Teleport(int){teleports++;}};
struct Roster {ChimeraCharacter* current=nullptr;bool CurrentActor(ChimeraCharacter* e){return current==e;}};
struct Mode {Roster roster;bool hasRoster=true;Roster* Players(){return hasRoster?&roster:nullptr;}};
struct ERR_Actors{static bool CanFight(ChimeraCharacter* c){return c&&c->awake;}};
struct CompartmentAccessComponent {static bool GetVehicleIn(ChimeraCharacter* c){return c&&c->aboard;}};
struct Probe {bool m_Stopped=false,m_Moved=true,m_DamageChanged=true,m_PreviousDamageEnabled=true;Damage* m_Damage;Mode* m_Mode;ChimeraCharacter* m_Player;int m_Original=0;
'''+stop+'''
};
int main(){
Damage damage;Mode mode;ChimeraCharacter oldBody,replacement;mode.roster.current=&oldBody;
Probe p;p.m_Damage=&damage;p.m_Mode=&mode;p.m_Player=&oldBody;
damage.enabled=false;p.Stop();assert(damage.enabled&&damage.changes==1&&oldBody.teleports==1);
p.Stop();assert(damage.changes==1&&oldBody.teleports==1); // idempotent
p.m_Stopped=false;p.m_Moved=true;p.m_Damage=&damage;p.m_DamageChanged=true;p.m_PreviousDamageEnabled=false;mode.roster.current=&replacement;
p.Stop();assert(!damage.enabled&&damage.changes==2&&replacement.teleports==0&&oldBody.teleports==1); // restore exact old damage state, no stale-body teleport
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=false; // rejected before protection applied
p.Stop();assert(damage.changes==2);
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;p.m_PreviousDamageEnabled=true;mode.roster.current=&oldBody;oldBody.awake=false;
p.Stop();assert(damage.enabled&&damage.changes==3&&oldBody.teleports==1);
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;oldBody.awake=true;oldBody.aboard=true;
p.Stop();assert(damage.changes==4&&oldBody.teleports==1);
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;mode.hasRoster=false;
p.Stop();assert(damage.changes==5&&oldBody.teleports==1);
}
''')
text=source.read_text();tick=body(source,'int Tick(');inspect=body(source,'protected bool Inspect(')
assert tick.index('CurrentActor(m_Player)') < tick.index('m_Damage.EnableDamageHandling(false)') < tick.index('Teleport(transform)')
assert 'ERR_Actors.Spawn(' not in text and 'GetInVehicle(' not in text and 'SetTotalFuel' not in text
assert 'seats.Count() == 5' in inspect and 'slot.GetGetInAction()' in inspect
assert 'front == 2 && rear == 3' in inspect and 'doors.Count() == 4' in inspect
assert 'ERR_VehicleSecurityComponent.Find(action.GetOwner()) == m_Security' in inspect
assert '!action.CanBePerformedScript(m_Player)' in inspect and 'action.PerformAction(action.GetOwner(), m_Player);' in inspect
assert '!door.CanBePerformedScript(m_Player)' in inspect and 'door.PerformAction(door.GetOwner(), m_Player);' in inspect
assert 'm_Security.CanBreach(m_Player, reason)' in tick and '!m_Security.TryBreach(m_Player)' in tick
assert 'DriverAvailable()' in tick
assert 'm_DriverAction.CanBePerformedScript(m_Player)' in body(source,'protected bool DriverAvailable(')
transport=(base/'addons/core/Scripts/Game/ERR/ERR_NativeTransportProbe.c').read_text()
smoke=(base/'addons/core/Scripts/Game/ERR/ERR_NativeBaseSmoke.c').read_text()
assert 'new ERR_NativeTransportProbe(this, m_ERRBasePlayer)' in smoke and 'if (m_ERRTransportProbe) m_ERRTransportProbe.Stop();' in smoke
assert transport.index('m_SecurityProbe.Tick(now)') < transport.index('IEntity driver = Character(0)')
assert 'void Stop() { if (m_SecurityProbe) m_SecurityProbe.Stop(); }' in transport
print('PASS: actual native-prelude cleanup restores only original changed damage, refuses stale/incapacitated/aboard teleport; bounded five-seat/four-door fixture wiring checked. Native execution remains pending.')
# Existing transport tests did not extract CreateTransport. Test its real new
# Configure hook with native construction/FindComponent calls represented by doubles.
site=ROOT/'addons/core/Scripts/Game/ERR/ERR_SiteService.c'
create=body(site,'protected bool CreateTransport(').replace('protected ','').replace('null','nullptr')
for name in ('ERR_SiteRuntime','ERR_SiteTransport','CarControllerComponent','ERR_VehicleSecurityComponent'):
create=re.sub(r'\b'+name+r' (\w+)',name+r'* \1',create)
for name in ('site','spec','controller','security'):create=create.replace(name+'.',name+'->')
create=create.replace('site->Definition.','site->Definition->')
create=create.replace('ERR_Actors.','ERR_Actors::').replace('ERR_VehicleSecurityComponent.','ERR_VehicleSecurityComponent::')
create=create.replace('Vehicle.Cast(entity)','CastVehicle(entity)').replace('CarControllerComponent.Cast(site->Transport.FindComponent(CarControllerComponent))','FindController(site->Transport)')
run('''#include <cassert>
#include <string>
#include <vector>
using string=std::string;using vector=int;
int Vector(int x,int,int){return x;}
struct CarControllerComponent {bool parked=false;void SetPersistentHandBrake(bool b){parked=b;}};
struct Entity;
struct ERR_VehicleSecurityComponent {CarControllerComponent* controller;bool result=true;int calls=0;bool Configure(){assert(controller&&controller->parked);calls++;return result;}static ERR_VehicleSecurityComponent* Find(Entity* e);};
struct Entity {bool vehicle=true;CarControllerComponent* controller=nullptr;ERR_VehicleSecurityComponent* security=nullptr;};using IEntity=Entity*;
ERR_VehicleSecurityComponent* ERR_VehicleSecurityComponent::Find(Entity* e){return e->security;}
IEntity CastVehicle(IEntity e){return e->vehicle?e:nullptr;}
CarControllerComponent* FindController(IEntity e){return e->controller;}
struct ERR_SiteTransport {int Offset=0,ClearanceRadius=4,MaximumTerrainRange=1,Prefab=123,Heading=180;};
struct Definition {ERR_SiteTransport* Transport=nullptr;string Id="supply";};
struct ERR_SiteRuntime {struct Definition* Definition;IEntity Transport=nullptr;};
struct ERR_Actors {static IEntity spawned;static int calls;static int Ground(int p){return p;}static IEntity Spawn(int,int,int){calls++;return spawned;}};IEntity ERR_Actors::spawned=nullptr;int ERR_Actors::calls=0;
struct Array:std::vector<IEntity>{void Insert(IEntity e){push_back(e);}};
struct Service{bool clear=true;string failure;Array m_Entities;bool Fail(string s){failure=s;return false;}bool TransportClearance(int,int,int){return clear;}
'''+create+'''
};
int main(){Service service;Definition def;ERR_SiteRuntime site{&def};ERR_SiteTransport spec;
assert(service.CreateTransport(&site,0)&&ERR_Actors::calls==0);def.Transport=&spec;
service.clear=false;assert(!service.CreateTransport(&site,0)&&ERR_Actors::calls==0);service.clear=true;
assert(!service.CreateTransport(&site,0)&&service.m_Entities.empty());
Entity vehicle;CarControllerComponent controller;ERR_VehicleSecurityComponent security;ERR_Actors::spawned=&vehicle;
vehicle.vehicle=false;assert(!service.CreateTransport(&site,0)&&service.m_Entities.back()==&vehicle);vehicle.vehicle=true;
assert(!service.CreateTransport(&site,0));vehicle.controller=&controller;
assert(service.CreateTransport(&site,0)&&controller.parked); // ordinary vehicle has no security hook
vehicle.security=&security;security.controller=&controller;security.result=false;controller.parked=false;
assert(!service.CreateTransport(&site,0)&&security.calls==1&&service.failure.find("security configuration")!=string::npos);
security.result=true;controller.parked=false;assert(service.CreateTransport(&site,0)&&security.calls==2&&site.Transport==&vehicle);
}
''')
print('PASS: actual CreateTransport requires successful scoped Configure after handbrake, preserves ordinary vehicles, tracks spawned entity before failures and never treats failed lock registration as ready.')