"""Exercise production placement vetoes for players, spectators and editor cameras.""" import re from policy_harness import ROOT, body, run p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_GarageVehicles.c' s=body(p,'protected bool Observers(').replace('protected ','').replace('array', 'Array').replace('array', 'Array').replace('array ids = {};','std::vector ids;').replace('foreach (int id : ids)','for (int id : ids)').replace('null','nullptr') s=s.replace('Array positions','Array& positions').replace('Array actors','Array& actors') s=s.replace('ERR_ForceRules.', 'ERR_ForceRules::').replace('ERR_ObserverReason.NONE','ERR_ObserverReason::NONE') for cls in ['SCR_PlayerController','SCR_EditorManagerEntity','SCR_EditorManagerCore','IEntity']: s=s.replace(cls+'.',cls+'::') s=re.sub(r'\b'+cls+r' (\w+)',cls+r'* \1',s) s=s.replace('SCR_EditorManagerCore::GetInstance(SCR_EditorManagerCore)','SCR_EditorManagerCore::GetInstance()') s=s.replace('SCR_EditorManagerEntity* editor;', 'SCR_EditorManagerEntity* editor = nullptr;') for prefix in ['GetGame()','GetPlayerManager()','controller','body','watched','editors','editor']: s=s.replace(prefix+'.',prefix+'->') run(r''' #include #include #include struct Vec{float x=0,z=0;}; templatestruct Array:std::vector{void Clear(){this->clear();}void Insert(T t){this->push_back(t);}}; namespace ERR_ForceRules{bool FiniteVector(Vec v){return std::isfinite(v.x)&&std::isfinite(v.z);}} namespace Geometry{float DistanceXZ(Vec a, Vec b){return std::hypot(a.x-b.x,a.z-b.z);}} namespace ERR_ObserverReason{const int NONE=0;} struct IEntity{Vec p;Vec GetOrigin(){return p;}}; struct SCR_PlayerController{ IEntity* body=nullptr;IEntity* watched=nullptr;int state=0; IEntity* GetControlledEntity(){return body;}IEntity* ERR_ObservedEntity(){return watched;}int ERR_ObserverState(){return state;} static SCR_PlayerController* Cast(SCR_PlayerController* p){return p;} }; struct SCR_EditorManagerEntity{bool opened=false;bool IsOpened(){return opened;}}; SCR_EditorManagerEntity editor; struct SCR_EditorManagerCore{ static SCR_EditorManagerCore* GetInstance(){static SCR_EditorManagerCore c;return &c;} static SCR_EditorManagerCore* Cast(SCR_EditorManagerCore* p){return p;} SCR_EditorManagerEntity* GetEditorManager(int){return &editor;} }; struct Manager{ std::vector clients; void GetPlayers(std::vector& ids){for(unsigned i=0;i positions;Array actors; assert(Observers(positions,actors)&&positions.empty()); game.players.clients={nullptr};assert(!Observers(positions,actors)); SCR_PlayerController c;game.players.clients={&c};assert(!Observers(positions,actors)); IEntity player{{10,0}}, watched{{500,0}};c.body=&player; assert(Observers(positions,actors)&&positions.size()==1&&actors[0]==&player); editor.opened=true;assert(!Observers(positions,actors));editor.opened=false; c.state=1;assert(!Observers(positions,actors));c.watched=&watched; assert(Observers(positions,actors)&&positions.size()==2&&actors[1]==&watched); c.body=nullptr;assert(Observers(positions,actors)&&positions.size()==1&&actors[0]==&watched); watched.p={NAN,0};assert(!Observers(positions,actors));watched.p={500,0}; c.state=0;assert(!Observers(positions,actors)); } ''') print('PASS: bodies and spectator targets are collected; unknown, nonfinite and editor views veto spawning/cleanup; no connected players yields an empty known view')