"""Production reader regression: proxy body corrections cannot move the camera. Native animation/weapon alignment and live network behavior remain mission tests. """ from policy_harness import ROOT, body, run source = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_ObserverPlayerView.c' conversion = '\n'.join(body(source, signature) for signature in ('static void Encode(', 'static vector WorldPosition(')).replace('out vector', 'vector') readers = '\n'.join(body(source, signature) for signature in ('bool ERR_ReadPlayerView(', 'bool ERR_ReadPlayerEye(')) for cls in ('ERR_Actors', 'ERR_ObserverScope', 'RplId'): readers = readers.replace(cls+'.', cls+'::') readers = (readers.replace('out vector', 'vector').replace('out float ', 'float& ') .replace('GetGame().', 'GetGame()->').replace('GetWorld().', 'GetWorld()->') .replace('Rpc(ERR_RequestPlayerView)', 'Request()')) # Both reader bodies execute below. Buffer interpolation and receive/authority # are executed separately by view_buffer and view_relay, not replaced by regex guards. run(r''' #include #include struct vector { float x=0,y=0,z=0; vector operator+(vector b)const{return{x+b.x,y+b.y,z+b.z};} vector operator-(vector b)const{return{x-b.x,y-b.y,z-b.z};} vector operator*(float n)const{return{x*n,y*n,z*n};} }; bool close(vector a,vector b){return std::abs(a.x-b.x)<.002&&std::abs(a.y-b.y)<.002&&std::abs(a.z-b.z)<.002;} void yaw(float a,vector origin,vector* m){m[0]={std::cos(a),0,-std::sin(a)};m[1]={0,1,0};m[2]={std::sin(a),0,std::cos(a)};m[3]=origin;} struct Rules {'''+conversion+r'''}; struct RplId{int id=-1;static RplId Invalid(){return{-1};}bool operator!=(RplId b){return id!=b.id;}}; struct Actor{bool canFight=true;vector root;};using IEntity=Actor*; struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->canFight;}}; struct ERR_ObserverScope{static inline bool resolved=true;static bool Resolve(IEntity,RplId,vector){return resolved;}}; struct Game{void* local=nullptr;float now=100;void* GetPlayerController(){return local;}Game* GetWorld(){return this;}float GetWorldTime(){return now;}}game; Game* GetGame(){return &game;} struct Buffer{ vector position{15000.125,301.5,-15999.75};float play=123,aligned=-1;int reads=0;bool fresh=true;RplId weapon; bool Read(RplId,float,float,vector* out,float& fov,float& nearPlane){reads++;if(!fresh)return false;yaw(.7,position,out);fov=60;nearPlane=.02;return true;} float Playback(){return play;}void Align(float time,float){aligned=time;} void Scope(RplId& id,vector& data){id=weapon;data={};} void PIP(float& fov,vector& geometry,float& vignette){fov=6;geometry={0,0,1};vignette=.5;} }; struct Controller{ bool m_ERRHasPIP=true;float m_ERRViewRequestAt=0;RplId m_ERRObservedId{1};int requests=0; Buffer m_ERRViewBuffer,m_ERREyeBuffer; void Request(){requests++;} '''+readers+r''' }; int main(){ // Encoding preserves sampled world axes/roll. Reconstruction uses the origin // captured with that pose, including far and negative terrain coordinates. vector owner[4],view[4],pose[4]; for(int a=-180;a<=180;a+=15){ yaw(a*.0174532925,{15000,300,-16000},owner); yaw(.7,{15000.125,301.5,-15999.75},view); auto right=view[0],up=view[1];view[0]=right*.8+up*.6;view[1]=up*.8-right*.6; Rules::Encode(owner,view,pose); for(int axis=0;axis<3;axis++)assert(close(pose[axis],view[axis])); assert(close(Rules::WorldPosition(owner[3],pose[3]),view[3])); } Controller c;Actor proxy;game.local=&c;vector out[4],eye[4],geometry;float fov,near,pip,vignette; c.m_ERREyeBuffer.position={15000,301.625,-16000}; // A jittering proxy root used to move the camera by exactly its correction. // Actual production readers must leave both sampled positions unchanged. for(int frame=0;frame<300;frame++){ proxy.root={15000+((frame%2)? .25f:-.25f),300,-16000+frame*.02f}; assert(c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); assert(close(out[3],c.m_ERRViewBuffer.position)&&fov==60&&near==.02f); assert(c.ERR_ReadPlayerEye(&proxy,.016,eye,fov,near,pip,geometry,vignette)); assert(close(eye[3],c.m_ERREyeBuffer.position)&&pip==6&&vignette==.5); assert(c.m_ERREyeBuffer.aligned==c.m_ERRViewBuffer.Playback()); } // Scope resolution may refuse a frame without exposing a proxy head estimate. c.m_ERRViewBuffer.weapon={22};ERR_ObserverScope::resolved=false; assert(!c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); ERR_ObserverScope::resolved=true;assert(c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); assert(close(out[3],c.m_ERRViewBuffer.position)); c.m_ERRViewBuffer.fresh=false;assert(!c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); c.m_ERRViewBuffer.fresh=true;c.m_ERREyeBuffer.fresh=false; assert(!c.ERR_ReadPlayerEye(&proxy,.016,eye,fov,near,pip,geometry,vignette)); c.m_ERREyeBuffer.fresh=true;c.m_ERRHasPIP=false; assert(!c.ERR_ReadPlayerEye(&proxy,.016,eye,fov,near,pip,geometry,vignette)); proxy.canFight=false;assert(!c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); proxy.canFight=true;game.local=nullptr;assert(!c.ERR_ReadPlayerView(&proxy,.016,out,fov,near)); game.local=&c;game.now=600;assert(c.ERR_ReadPlayerView(&proxy,.016,out,fov,near));assert(c.requests==1); assert(!c.ERR_ReadPlayerView(nullptr,.016,out,fov,near)); } ''') print('PASS: production first-person and PiP readers ignore independently corrected proxy position, retain captured world poses, align playback and preserve scope/stale/ownership gates')