Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
100 lines
8.4 KiB
Python
100 lines
8.4 KiB
Python
"""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/00_Core/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/00_Core/ERR_NativeTransportProbe.c').read_text()
|
|
smoke=(base/'addons/core/Scripts/Game/ERR/00_Core/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/00_Core/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.')
|