"""Execute production direct-callout routing with HTTP/radio/native entities doubled.""" import re from policy_harness import ROOT,body,run p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_SoldierSpeech.c' rules=body(p,'static string Text(')+body(p,'static bool Near(') names=re.findall(r'case ECommunicationType\.(\w+)',rules) rules=rules.replace('ECommunicationType.','ECommunicationType::') s='\n'.join(body(p,x) for x in ['bool Current()', 'void Prepared(', 'bool Speak(', 'bool ReadyClip(', 'bool Clip(']) s=s.replace('ERR_BakedSpeech.', 'ERR_BakedSpeech::') s=s.replace('out string url','string& url').replace('array listeners,','Array listeners,') s=s.replace('protected ','').replace('null','nullptr').replace('ref ','') for typ in ['IEntity','SCR_AITalkRequest','VoNComponent','RplComponent','SCR_PlayerController','ERR_SpeechService']: s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s) s=s.replace('array players = {}','Array players').replace('array listeners = {}','Array listeners') s=s.replace('foreach (','for (') s=s.replace('RplComponent.Cast(actor.FindComponent(RplComponent))','actor->rpl') s=s.replace('SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(player))','GetGame()->GetPlayerManager()->GetPlayerController(player)') for n in ['GetGame()','m_Mode','actor','request','von','service','m_Request','component','controller','listener','recipient']: s=s.replace(n+'.',n+'->') s=s.replace('GetPlayerManager().','GetPlayerManager()->').replace('ERR_Speech().','ERR_Speech()->').replace('GetControlledEntity().','GetControlledEntity()->') s=s.replace('m_Clips.','m_Clips.').replace('ERR_GameMode.Get()','ERR_GameMode::Get()').replace('ERR_SoldierSpeechRules.','ERR_SoldierSpeechRules::').replace('ERR_Actors.','ERR_Actors::').replace('vector.Distance','Distance').replace('ECommMethod.DIRECT','ECommMethod::DIRECT').replace('LogLevel.WARNING','1') run(r''' #include #include #include #include #include #include struct string:std::string {using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}}; templatestruct Array:std::vector{bool IsEmpty(){return this->empty();}void Insert(T v){this->push_back(v);}int Count(){return this->size();}}; struct Map{std::mapvalues;bool Find(int k,string&v){if(!values.count(k))return false;v=values[k];return true;}void Set(int k,string v){values[k]=v;}}; #define Print(...) #define PrintFormat(...) namespace ECommunicationType{enum{'''+','.join(names)+r''',REPORT_CONTACT=100,REPORT_MOVE};} struct ERR_SoldierSpeechRules{ '''+rules+r''' }; bool baked=false;struct ERR_BakedSpeech{static string Soldier(int kind){return baked&&!ERR_SoldierSpeechRules::Text(kind).IsEmpty()?"baked:line":"";}}; namespace ECommMethod{enum{DIRECT,RADIO};} struct VoNComponent{int method=ECommMethod::DIRECT;int GetCommMethod(){return method;}}; struct SCR_AITalkRequest{int m_eCommType=ECommunicationType::REPORT_MOVING;}; struct RplComponent{int Id(){return 77;}}; struct IEntity{bool fit=true,player=false;float pos=0;RplComponent value;RplComponent*rpl=&value;float GetOrigin(){return pos;}}; namespace ERR_Actors{bool CanFight(IEntity*a){return a&&a->fit;}bool Player(IEntity*a){return a&&a->player;}} float Distance(float a,float b){return std::abs(a-b);} struct ERR_SoldierSpeechPreparation{void*Server=nullptr;int Kind=0;}; struct ERR_SpeechService{bool ready=true,idle=true,accept=true;int requests=0;string endpoint="bridge",text;bool Ready(){return ready;}string CacheNamespace(){return endpoint;}bool IdleFor(float n){assert(n==65000);return idle;}bool Request(string t,ERR_SoldierSpeechPreparation*){requests++;text=t;return accept;}}; struct ERR_GameMode{static ERR_GameMode*live;bool active=true,recordings=true;bool ERR_RecordingsEnabled(){return recordings;}ERR_SpeechService voice;bool Active(){return active;}auto ERR_Speech(){return &voice;}static auto Get(){return live;}};ERR_GameMode*ERR_GameMode::live=nullptr; struct SCR_PlayerController{IEntity*body=nullptr;bool ready=false;int preparations=0,delivered=0;IEntity*GetControlledEntity(){return body;}bool ERR_SoldierClipReady(ERR_GameMode*,int,string){return ready;}void ERR_PrepareSoldierClip(int,string){preparations++;}void ERR_DeliverSoldierLine(int,string,int){delivered++;}}; struct Manager{Arraycontrollers;void GetPlayers(Array&ids){for(int i=0;i::quiet_NaN())); assert(ERR_SoldierSpeechRules::Text(100).IsEmpty()); {Fixture f;assert(!f.Speak()&&f.mode.voice.requests==1);assert(!f.Speak()&&f.mode.voice.requests==1);f.Prepared();assert(!f.Speak()&&f.c1.preparations==1&&f.c2.preparations==1);f.c1.ready=true;assert(!f.Speak()&&!f.c1.delivered&&!f.c2.delivered);f.c2.ready=true;assert(f.Speak()&&f.c1.delivered==1&&f.c2.delivered==1);assert(f.server.Clip(f.request.m_eCommType,"clip")&&!f.server.Clip(f.request.m_eCommType,"other"));} {Fixture f;f.mode.voice.accept=false;assert(!f.Speak()&&!f.server.m_Request);} {Fixture f;f.Speak();f.server.Prepared(f.request.m_eCommType,"");assert(f.server.m_Clips.values.empty()&&!f.server.m_Request);} {Fixture f;f.c1.ready=true;f.c2.ready=true; assert(!f.server.Speak(&f.actor,&f.request,&f.von,1100)&&f.mode.voice.requests==1); f.server.Prepared(1100,"opening"); assert(!f.server.Speak(&f.actor,&f.request,&f.von,1100)&&f.mode.voice.requests==2&&!f.c1.delivered); f.server.Prepared(1101,"reply"); assert(f.server.Speak(&f.actor,&f.request,&f.von,1100)&&f.c1.delivered==1); } for(int bad=0;bad<9;bad++){Fixture f; if(bad==0)f.mode.voice.ready=false; if(bad==1)f.mode.active=false; if(bad==2)f.mode.voice.endpoint="changed"; if(bad==3)f.von.method=ECommMethod::RADIO; if(bad==4)f.actor.fit=false; if(bad==5)f.actor.player=true; if(bad==6)f.actor.rpl=nullptr; if(bad==7)f.request.m_eCommType=100; if(bad==8){f.one.pos=100;f.two.pos=100;} assert(!f.Speak()&&f.mode.voice.requests==0); } {Fixture f;f.mode.voice.idle=false;assert(!f.Speak()&&f.mode.voice.requests==0);} {Fixture f;f.Prepared();f.c1.ready=true;f.two.pos=100;assert(f.Speak()&&f.c1.delivered==1&&f.c2.delivered==0);} {Fixture f;f.Prepared();f.c1.ready=true;f.two.fit=false;assert(f.Speak()&&f.c1.delivered==1&&f.c2.delivered==0);} } ''') print('PASS: actual-callout mapping, nearby listeners, all-client readiness, native fallback, no radio hijack, rate guard, changed endpoint and failed preparation')