Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

284 lines
24 KiB
Diff

--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c
@@ -35,6 +35,8 @@
protected bool m_FleetReady;
protected bool m_SwapEligibility;
protected bool m_MineStock;
+ protected bool m_BMP;
+ protected ref ERR_ConvoyVehicle m_BMPVehicle;
protected bool m_MountedDiagnosticPrinted;
protected ref ERR_ConvoyMineStock m_MineBatch;
protected ref ERR_ConvoyVehicle m_MineTruck;
@@ -58,11 +60,14 @@
void ERR_NativeMountedAmmoProbe(ERR_GameMode mode, float now)
{
m_Mode = mode; m_Deadline = now + 180000;
- string swap, mines, courier;
+ string swap, mines, courier, bmp;
+ m_BMP = System.GetCLIParam("errMountedBMP", bmp) && bmp == "1";
m_MineStock = System.GetCLIParam("errMineStock", mines) && mines == "1";
m_SwapEligibility = System.GetCLIParam("errMountedSwapEligibility", swap) && swap == "1";
if (m_MineStock && (m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
Check(false, "mine-stock proof requires the normal mounted radio path, without swap or courier flags");
+ if (m_BMP && (m_MineStock || m_SwapEligibility || (System.GetCLIParam("errMountedCourier", courier) && courier == "1")))
+ Check(false, "BMP proof requires the normal mounted radio path, without mine, swap or courier flags");
if (m_SwapEligibility) m_SwapProbe = new ERR_NativeMountedSwapProbe();
}
bool SwapEligibility() { return m_SwapEligibility; }
@@ -100,6 +105,13 @@
}
return !vehicle.Members.IsEmpty();
}
+ protected bool BMPReady(ERR_ConvoyVehicle vehicle, ERR_HQMountedAmmoSnapshot sample)
+ {
+ return vehicle && vehicle.Entity && vehicle.Entity.GetPrefabData()
+ && vehicle.Entity.GetPrefabData().GetPrefabName() == ERR_ConvoyResources.VehiclePrefab(4)
+ && sample && sample.Valid() && sample.Complete && sample.Weapons > 0 && sample.Magazines > 0
+ && sample.Rounds + sample.Chambers > 0;
+ }
protected void Capture(ERR_HQ hq, ERR_ConvoyVehicle vehicle, float now)
{
if (m_Queued || !vehicle || !vehicle.Registered) return;
@@ -107,10 +119,12 @@
if (!Original(vehicle, unit) || !unit.PendingStatus || !unit.Uplink) return;
ERR_HQStatusReport report = unit.PendingStatus;
if (!report.MountedAmmo || report.MountedAmmo.Weapons < 1 || report.MountedAmmo.Magazines < 1) return;
+ if (m_BMP && !BMPReady(vehicle, report.MountedAmmo)) return;
ERR_HQWatchEntry before = hq.Watch().Find(report.SourceId);
if (before && before.MessageId >= report.MessageId) return;
if (!Check(ERR_HQWatchRules.Valid(report, now) && report.SourceId == unit.StatusSampler.InitialSourceId()
&& unit.Uplink.MessageId == report.MessageId && unit.Uplink.Cursor < unit.Uplink.Nodes.Count(), "original mounted payload observed before real radio delivery")) return;
+ if (m_BMP) m_BMPVehicle = vehicle;
m_Unit = unit; m_Root = vehicle.Entity; m_Queued = report;
m_Payload = report.MountedAmmo.Snapshot(); m_Route = unit.Uplink; m_RoutePayload = m_Route.Payload;
Check(m_Payload != report.MountedAmmo && Same(m_Payload, report.MountedAmmo)
@@ -208,7 +222,7 @@
{
ERR_ConvoyVehicle vehicle = task.Vehicles[slot];
if (!Check(vehicle && Original(vehicle, hq.ERR_MountedFixtureUnit(vehicle.Group)), "root retains original admitted seated crew and ledger")) return false;
- bool diagnose = m_MineStock && slot == 1 && !m_MountedDiagnosticPrinted;
+ bool diagnose = ((m_MineStock && slot == 1) || (m_BMP && slot == 4)) && !m_MountedDiagnosticPrinted;
if (diagnose) ERR_HQMountedAmmoSampler.BeginDiagnostic();
ERR_HQMountedAmmoSnapshot sample = ERR_HQMountedAmmoSampler.Inspect(vehicle.Entity);
if (diagnose)
@@ -225,6 +239,7 @@
if (!Check(sample && sample.Valid(), "native root returns bounded valid snapshot")) return false;
PrintFormat("ERR MOUNTED SAMPLE: source=%1 slot=%2 complete=%3 weapons=%4 muzzles=%5 magazines=%6", task.Receipt.SourceId, slot, sample.Complete, sample.Weapons, sample.Muzzles, sample.Magazines);
PrintFormat("ERR MOUNTED COUNTS: slot=%1 rounds=%2 capacity=%3 chambers=%4 low=%5", slot, sample.Rounds, sample.Capacity, sample.Chambers, sample.LowMagazines);
+ if (m_BMP && slot == 4 && !Check(BMPReady(vehicle, sample), "original slot4 BMP has complete valid armed mounted counts")) return false;
if (sample.Weapons > 0 && sample.Magazines > 0) armed = true;
if (slot == 1)
{
@@ -277,7 +292,11 @@
{
ERR_ConvoyTask task = hq.Convoys().At(convoy);
if (!task || (m_ProofTask && task != m_ProofTask)) continue;
- for (int slot = 0; slot < task.Vehicles.Count() && slot < 6; slot++) Capture(hq, task.Vehicles[slot], now);
+ for (int slot = 0; slot < task.Vehicles.Count() && slot < 6; slot++)
+ {
+ if (m_BMP && slot != 4) continue;
+ Capture(hq, task.Vehicles[slot], now);
+ }
}
if (!m_FleetReady) m_FleetReady = Fleet(hq);
if (m_Failed) return -1;
@@ -301,6 +320,10 @@
&& delivered.Fit == m_Queued.Fit && m_Route.MessageId == m_Queued.MessageId
&& m_Route.Payload == m_RoutePayload, "delivered observation age, roster counts and radio payload preserved")) return -1;
if (!Check(hq.ERR_MountedFixtureUnit(m_Unit.Group) == m_Unit && ERR_Actors.Alive(m_Root), "original source and root retained through delivery")) return -1;
+ if (m_BMP && !Check(m_ProofTask && m_ProofTask.Vehicles.Count() == 6
+ && m_BMPVehicle && m_ProofTask.Vehicles[4] == m_BMPVehicle && m_BMPVehicle.Entity == m_Root
+ && Original(m_BMPVehicle, m_Unit) && BMPReady(m_BMPVehicle, m_Payload),
+ "same original slot4 BMP and complete armed queued snapshot retained through actual radio delivery")) return -1;
if (!Mines(m_ProofTask, false)) return -1;
return 1;
}
@@ -309,7 +332,7 @@
if (hq.SupplyConvoys().Target() == 3 && hq.Convoys().Count() <= 3) return true;
return Check(false, "unchanged default three-convoy production target");
}
- protected void Forget() { m_Unit = null; m_Root = null; m_Queued = null; m_Payload = null; m_Route = null; m_RoutePayload = string.Empty; }
+ protected void Forget() { m_BMPVehicle = null; m_Unit = null; m_Root = null; m_Queued = null; m_Payload = null; m_Route = null; m_RoutePayload = string.Empty; }
void Stop()
{
m_Stopped = true; if (m_SwapProbe) m_SwapProbe.Stop();
--- a/tools/headless_workbench.py
+++ b/tools/headless_workbench.py
@@ -18,6 +18,7 @@
p.add_argument('--trace-random-radius', action='store_true', help='Workbench-only read-only zero-radius caller traces; one normal Chat round, capped at sixteen records')
p.add_argument('--maintenance-refuel', action='store_true', help='Opt-in normal-route check: original held Southern fuel can transfers finite fuel through its native UAZ action; one arranged tank depletion, no stock creation')
p.add_argument('--mounted-swap-eligibility', action='store_true', help='Read-only mounted-ammo variant: one exact finite cargo/mounted magazine CanSwap call; no transfer or radio proof')
+p.add_argument('--mounted-bmp', action='store_true', help='Read-only original BMP slot4 complete mounted counts and its natural HQ radio delivery; isolates unrelated opening hunters before unlock')
p.add_argument('--mine-stock', action='store_true', help='Read-only mounted-ammo check of exact callback-proved finite PMN4 cargo before and after natural radio delivery')
p.add_argument('--mounted-courier', action='store_true', help='Mounted-ammo variant: intentionally deplete one original installed magazine, then require natural HQ radio, finite pickup, native exchange and original-seat return')
p.add_argument('--mounted-intercept', action='store_true', help='After convoy driving, two synthetic witness samples exercise real HQ radio/planning and original escort detour/hold/expiry/resume')
@@ -71,6 +72,7 @@
if a.smoke == 'supply-convoys' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 900): p.error('supply-convoys requires Chat, one round, and at least900 seconds')
if a.smoke == 'alarm-hearing' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('alarm-hearing requires Chat, exactly one round, and timeout at least360 seconds')
if a.smoke == 'mounted-ammo' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('mounted-ammo requires Chat, exactly one round, and timeout at least360 seconds')
+if a.mounted_bmp and (a.smoke != 'mounted-ammo' or a.project != 'chat' or a.rounds != 1 or a.timeout < 360 or a.mine_stock or a.mounted_courier or a.mounted_swap_eligibility): p.error('--mounted-bmp requires Chat mounted-ammo, one round, timeout at least360 seconds, without mine/courier/swap flags')
if a.smoke == 'convoy' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 600): p.error('convoy requires Chat, exactly one round, and timeout at least600 seconds')
if a.smoke == 'infantry-transfer' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('infantry-transfer requires Chat, one round and timeout at least360 seconds')
if a.smoke == 'hq-local-handoff' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('hq-local-handoff requires Chat, one round and timeout at least360 seconds')
@@ -137,6 +139,7 @@
if a.mounted_intercept: command += ['-errMountedIntercept', '1']
if a.mounted_swap_eligibility: command += ['-errMountedSwapEligibility', '1']
if a.mounted_courier: command += ['-errMountedCourier', '1']
+if a.mounted_bmp: command += ['-errMountedBMP', '1']
if a.mine_stock: command += ['-errMineStock', '1']
if a.maintenance_refuel: command += ['-errMaintenanceRefuel', '1']
if a.trace_random_radius: command += ['-errTraceRandomRadius', '1']
--- a/tests/test_native_mounted_ammo_probe.py
+++ b/tests/test_native_mounted_ammo_probe.py
@@ -4,8 +4,8 @@
from policy_harness import ROOT, body, run
ROOT=Path(os.environ.get('ERR_NATIVE_SWAP_ROOT',ROOT))
p=Path(os.environ.get('ERR_NATIVE_MOUNTED_AMMO_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c'))
-s=p.read_text();smoke=(ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c').read_text()
-runner=(ROOT/'tools/headless_workbench.py').read_text()
+s=p.read_text();smoke=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c')).read_text()
+runner=Path(os.environ.get('ERR_NATIVE_MOUNTED_RUNNER',ROOT/'tools/headless_workbench.py')).read_text()
assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif')
for forbidden in ('Spawn(', 'SpawnEntity', 'TrySpawn', '.Ingest(', '.Advance(', '.Dispatch(', '.BindVehicle(', '.Sample(',
'.SetOrigin(', '.SetAmmoCount(', '.Kill(', '.SetHealth(', 'NextStatus =', 'PendingStatus =', 'Uplink =', 'new ERR_HQStatusReport'):
@@ -34,7 +34,7 @@
code=code.replace('string.Empty','string{}').replace('protected ','').replace('null','nullptr').replace('ERR_GameMode.Get()', 'ERR_GameMode::Get()').replace('ERR_Actors.Alive(', 'ERR_Actors::Alive(')
for t in ('ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_ConvoyTask','ERR_HQWatchEntry'):
code=re.sub(r'\b'+t+r' (?=\w)',t+'* ',code)
-for var in ('a','b','hq','m_Mode','task','m_Queued','delivered','m_Unit','m_Route','m_ProofTask','m_SwapProbe'):
+for var in ('a','b','hq','m_Mode','task','m_Queued','delivered','m_Unit','m_Route','m_ProofTask','m_SwapProbe','m_BMPVehicle'):
code=re.sub(r'\b'+var+r'\.',var+'->',code)
for call in ('Convoys()','SupplyConvoys()','Watch()'):code=code.replace(call+'.',call+'->')
run(r'''
@@ -49,16 +49,16 @@
struct Route{int MessageId=7;string Payload="original";};struct Unit{int Group=1;Report* PendingStatus=nullptr;Route* Uplink=nullptr;};
struct ERR_GameMode{bool active=true;static inline ERR_GameMode* current=nullptr;static ERR_GameMode* Get(){return current;}bool Active(){return active;}};
template<class T>struct Arr:std::vector<T>{int Count(){return this->size();}void Clear(){this->clear();}};
-struct ERR_ConvoyTask{bool Stopped=false;Arr<int> Vehicles;};struct Pool{int count=3;int Count(){return count;}ERR_ConvoyTask* At(int){return nullptr;}};
+struct Escort{Root* Entity=nullptr;};struct ERR_ConvoyTask{bool Stopped=false;Arr<Escort*> Vehicles;};struct Pool{ERR_ConvoyTask* task=nullptr;int count=3;int Count(){return count;}ERR_ConvoyTask* At(int){return task;}};
struct Supply{int target=3;int Target(){return target;}string Status(){return "fixture production status";}};struct Watch{ERR_HQWatchEntry* entry=nullptr;ERR_HQWatchEntry* Find(string){return entry;}};
struct ERR_HQ{Pool pool;Supply supply;struct Watch watch;Unit* unit=nullptr;
Pool* Convoys(){return &pool;}Supply* SupplyConvoys(){return &supply;}struct Watch* Watch(){return &watch;}Unit* ERR_MountedFixtureUnit(int){return unit;}};
template<class... T>void PrintFormat(T...){}
struct SwapProbe{int result=1,calls=0,stops=0;int Tick(ERR_GameMode*,ERR_HQ*,ERR_ConvoyTask*){calls++;return result;}void Stop(){stops++;}};
-struct Probe{bool m_MineStock=false,mineProof=true;int mineChecks=0;void*m_MineBatch=nullptr,*m_MineTruck=nullptr,*m_MineInventory=nullptr;Arr<int>m_Mines,m_PrimaryCargo;bool Mines(ERR_ConvoyTask*,bool){mineChecks++;return !m_MineStock||mineProof;}bool m_SwapEligibility=false;SwapProbe* m_SwapProbe=nullptr;ERR_ConvoyTask* candidate=nullptr;ERR_ConvoyTask* Candidate(ERR_HQ*){return candidate;}bool m_Stopped=false,m_Failed=false,m_FleetReady=false,fleet=true;float m_Deadline=180000,m_NextLog=0;
+struct Probe{bool m_BMP=false,original=true;Escort*m_BMPVehicle=nullptr;bool Original(Escort*,Unit*){return original;}bool BMPReady(Escort*,ERR_HQMountedAmmoSnapshot*s){return s&&s->Complete&&s->Weapons>0&&s->Magazines>0&&s->Rounds+s->Chambers>0;}bool m_MineStock=false,mineProof=true;int mineChecks=0;void*m_MineBatch=nullptr,*m_MineTruck=nullptr,*m_MineInventory=nullptr;Arr<int>m_Mines,m_PrimaryCargo;bool Mines(ERR_ConvoyTask*,bool){mineChecks++;return !m_MineStock||mineProof;}bool m_SwapEligibility=false;SwapProbe* m_SwapProbe=nullptr;ERR_ConvoyTask* candidate=nullptr;ERR_ConvoyTask* Candidate(ERR_HQ*){return candidate;}bool m_Stopped=false,m_Failed=false,m_FleetReady=false,fleet=true;float m_Deadline=180000,m_NextLog=0;
ERR_ConvoyTask* m_ProofTask=nullptr;ERR_GameMode* m_Mode=nullptr;Report* m_Queued=nullptr;ERR_HQMountedAmmoSnapshot* m_Payload=nullptr;Route* m_Route=nullptr;
int captures=0;string m_RoutePayload="original";Unit* m_Unit=nullptr;Root* m_Root=nullptr;
- bool Check(bool b,string){if(!b)m_Failed=true;return b;}bool Fleet(ERR_HQ*){return fleet;}void Capture(ERR_HQ*,int,float){captures++;}
+ bool Check(bool b,string){if(!b)m_Failed=true;return b;}bool Fleet(ERR_HQ*){return fleet;}void Capture(ERR_HQ*,Escort*,float){captures++;}
'''+code+r'''
};
struct Setup{ERR_GameMode mode;ERR_HQ hq;Probe p;Root root;Unit unit;Route route;Report queued;ERR_HQWatchEntry delivered;
@@ -67,6 +67,14 @@
unit.PendingStatus=&queued;unit.Uplink=&route;queued.MountedAmmo=&original;delivered.MountedAmmo=&received;hq.watch.entry=&delivered;hq.unit=&unit;}
};
int main(){
+ // BMP delivery cannot succeed through a different slot/root, lost ownership or incomplete payload.
+ for(int fault=0;fault<6;fault++){Setup s;ERR_ConvoyTask task;Escort bmp,other;Root replacement;
+ task.Vehicles.resize(6);bmp.Entity=&s.root;task.Vehicles[4]=&bmp;s.p.m_BMP=true;s.p.m_BMPVehicle=&bmp;s.p.m_ProofTask=&task;s.hq.pool.task=&task;
+ if(fault==1)task.Vehicles[4]=&other;if(fault==2)bmp.Entity=&replacement;if(fault==3)s.p.original=false;
+ if(fault==4){s.payload.Complete=false;s.original.Complete=false;s.received.Complete=false;}
+ if(fault==5){s.payload.Rounds=0;s.payload.Chambers=0;s.original=s.payload;s.received=s.payload;}
+ assert(s.p.Tick(&s.hq,3000)==(fault==0?1:-1));assert(s.p.captures==3); // exactly slot4 per observed task, never other slots
+ }
{Setup s;s.p.m_MineStock=true;s.p.mineProof=false;assert(s.p.Tick(&s.hq,3000)==-1&&s.p.mineChecks==1);}
{Setup s;s.p.m_MineStock=true;s.p.m_Mines.push_back(1);s.p.m_PrimaryCargo.push_back(2);s.p.m_MineBatch=&s;s.p.Stop();assert(s.p.m_Mines.empty()&&s.p.m_PrimaryCargo.empty()&&!s.p.m_MineBatch);}
{Setup s;SwapProbe dry;ERR_ConvoyTask task;s.p.m_SwapEligibility=true;s.p.m_SwapProbe=&dry;s.p.candidate=&task;
@@ -143,3 +151,95 @@
}
''')
print('PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound')
+
+# Execute the exact Capture and BMPReady methods; native identity/roster/watch
+# boundaries are explicit doubles, while the snapshot validator has its own full suite.
+selected=[]
+if 'protected bool BMPReady(' in s: selected.append(body(p,'protected bool BMPReady('))
+selected.append(body(p,'protected void Capture('))
+capture='\n'.join(selected).replace('protected ','').replace('null','nullptr')
+for ns in ('ERR_ConvoyResources','ERR_HQWatchRules'):
+ capture=capture.replace(ns+'.',ns+'::')
+for t in ('ERR_ConvoyVehicle','ERR_HQMountedAmmoSnapshot','ERR_HQ','ERR_HQUnit','ERR_HQStatusReport','ERR_HQWatchEntry'):
+ capture=re.sub(r'\b'+t+r' (?=\w)',t+'* ',capture)
+for v in ('vehicle','sample','hq','unit','report','before','m_Route','m_Payload'):
+ capture=re.sub(r'\b'+v+r'\.',v+'->',capture)
+for x in ('Entity','MountedAmmo','StatusSampler','Uplink'):
+ capture=capture.replace('.'+x+'.','.'+x+'->').replace('->'+x+'.','->'+x+'->')
+for x in ('GetPrefabData()','Watch()'):
+ capture=capture.replace(x+'.',x+'->')
+capture=capture.replace('unit->Uplink->Nodes.Count()', 'int(unit->Uplink->Nodes.size())')
+run(r'''
+#include <cassert>
+#include <string>
+#include <vector>
+struct string:std::string{using std::string::string;string(const std::string&s):std::string(s){}bool Contains(const char*s){return find(s)!=npos;}};
+struct Prefab{string name="bmp";string GetPrefabName(){return name;}};
+struct Entity{Prefab prefab;Prefab*GetPrefabData(){return &prefab;}};
+struct ERR_ConvoyResources{static string VehiclePrefab(int slot){assert(slot==4);return "bmp";}};
+struct ERR_HQMountedAmmoSnapshot{bool Complete=true,valid=true;int Weapons=3,Magazines=3,Rounds=80,Chambers=1;
+ bool Valid(){return valid;}ERR_HQMountedAmmoSnapshot*Snapshot(){return new ERR_HQMountedAmmoSnapshot(*this);}};
+struct ERR_ConvoyVehicle{struct Entity*Entity=nullptr;bool Registered=true;int Group=1;};
+struct ERR_HQStatusReport{ERR_HQMountedAmmoSnapshot*MountedAmmo=nullptr;int MessageId=7;string SourceId="source";};
+struct ERR_HQWatchEntry{int MessageId=6;};
+struct Sampler{string InitialSourceId(){return "source";}};
+struct Route{int MessageId=7,Cursor=0;std::vector<int>Nodes={1,2};string Payload="mounted ammunition=original";};
+struct ERR_HQUnit{ERR_HQStatusReport*PendingStatus=nullptr;Route*Uplink=nullptr;Sampler*StatusSampler=nullptr;};
+struct Watch{ERR_HQWatchEntry*entry=nullptr;ERR_HQWatchEntry*Find(string){return entry;}};
+struct ERR_HQ{ERR_HQUnit*unit=nullptr;struct Watch watch;ERR_HQUnit*ERR_MountedFixtureUnit(int){return unit;}struct Watch*Watch(){return &watch;}};
+struct ERR_HQWatchRules{static bool Valid(ERR_HQStatusReport*,float){return true;}};
+struct Probe{bool m_BMP=true,original=true,failed=false;ERR_ConvoyVehicle*m_BMPVehicle=nullptr;ERR_HQStatusReport*m_Queued=nullptr;ERR_HQUnit*m_Unit=nullptr;Entity*m_Root=nullptr;ERR_HQMountedAmmoSnapshot*m_Payload=nullptr;Route*m_Route=nullptr;string m_RoutePayload;
+ bool Original(ERR_ConvoyVehicle*,ERR_HQUnit*){return original;}bool Check(bool x,const char*){if(!x)failed=true;return x;}
+ bool Same(ERR_HQMountedAmmoSnapshot*a,ERR_HQMountedAmmoSnapshot*b){return a->Complete==b->Complete&&a->Weapons==b->Weapons&&a->Magazines==b->Magazines&&a->Rounds==b->Rounds&&a->Chambers==b->Chambers;}
+'''+capture+r'''
+};
+struct Setup{Probe p;Entity root;ERR_ConvoyVehicle vehicle;ERR_HQ hq;ERR_HQUnit unit;Sampler sampler;Route route;ERR_HQStatusReport report;ERR_HQMountedAmmoSnapshot sample;
+ Setup(){vehicle.Entity=&root;hq.unit=&unit;unit.PendingStatus=&report;unit.Uplink=&route;unit.StatusSampler=&sampler;report.MountedAmmo=&sample;}};
+int main(){
+ {Setup s;s.root.prefab.name="uaz";s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_Payload);}
+ for(int bad=0;bad<6;bad++){Setup s;if(bad==0)s.sample.Complete=false;if(bad==1)s.sample.valid=false;
+ if(bad==2)s.sample.Weapons=0;if(bad==3)s.sample.Magazines=0;if(bad==4){s.sample.Rounds=0;s.sample.Chambers=0;}if(bad==5)s.p.original=false;
+ s.p.Capture(&s.hq,&s.vehicle,1000);assert(!s.p.m_Queued&&!s.p.m_BMPVehicle);}
+ {Setup s;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&s.p.m_BMPVehicle==&s.vehicle&&s.p.m_Root==&s.root);
+ assert(s.p.m_Payload!=&s.sample&&s.p.m_Payload->Complete&&s.p.m_Route==&s.route&&!s.p.failed);
+ s.sample.Rounds=0;assert(s.p.m_Payload->Rounds==80);}
+ {Setup s;s.p.m_BMP=false;s.root.prefab.name="uaz";s.sample.Complete=false;s.p.Capture(&s.hq,&s.vehicle,1000);assert(s.p.m_Queued==&s.report&&!s.p.m_BMPVehicle);}
+}
+'''.replace(';if(', ';\n if('))
+node=next(n for n in ast.parse(runner).body if isinstance(n,ast.If) and ast.unparse(n.test).startswith('a.mounted_bmp and'))
+condition=compile(ast.Expression(node.test),'<bmp-selector>','eval')
+for field in [None,'smoke','project','rounds','timeout','mine_stock','mounted_courier','mounted_swap_eligibility']:
+ values=dict(mounted_bmp=True,smoke='mounted-ammo',project='chat',rounds=1,timeout=360,mine_stock=False,mounted_courier=False,mounted_swap_eligibility=False)
+ if field:values[field]={'smoke':'convoy','project':'core','rounds':2,'timeout':359}.get(field,True)
+ assert eval(condition,{'a':SimpleNamespace(**values)})==(field is not None)
+assert "if a.mounted_bmp: command += ['-errMountedBMP', '1']" in runner
+print('PASS: actual BMP capture requires complete armed exact original resource; pinned delivery/slot checks and isolated CLI flag')
+
+# WORKBENCH isolation changes only unrelated services before the real unlock.
+assert start.index('!mixedBMP && StartMode() == 0 && Phase() == ERR_Phase.PRISON') < start.index('bmpHQ.ERR_IsolateMountedBMP()') < start.index('UnlockPrison(')
+assert all(x in start for x in ('errMineStock','errMountedSwapEligibility','errMountedCourier'))
+hook_path=Path(os.environ.get('ERR_NATIVE_SMOKE_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c'))
+hook=body(hook_path,'bool ERR_IsolateMountedBMP(').replace('ERR_NativeMountedAmmoProbe.','ERR_NativeMountedAmmoProbe::').replace('System.','System::').replace('ERR_GameMode.','ERR_GameMode::').replace('ERR_Phase.','ERR_Phase::')
+for v in ('m_Mode','m_Hunters','m_Towns'):hook=hook.replace(v+'.',v+'->')
+run(r'''
+#include <cassert>
+#include <string>
+using string=std::string;
+struct ERR_NativeMountedAmmoProbe{static inline bool enabled=true;static bool Enabled(){return enabled;}};
+struct System{static inline string flag="1";static bool GetCLIParam(string key,string&out){assert(key=="errMountedBMP");out=flag;return !flag.empty();}};
+struct ERR_Phase{static constexpr int PRISON=1;};
+struct ERR_GameMode{int start=0,phase=1;static inline ERR_GameMode*current=nullptr;static ERR_GameMode*Get(){return current;}int StartMode(){return start;}int Phase(){return phase;}};
+struct Service{int deployed=0,stops=0;int Deployed(){return deployed;}void Stop(){stops++;}};
+struct HQ{ERR_GameMode*m_Mode=nullptr;Service*m_Hunters=nullptr,*m_Towns=nullptr;
+'''+hook+r'''
+};
+int main(){for(int fault=0;fault<10;fault++){
+ ERR_GameMode mode,other;ERR_GameMode::current=&mode;Service hunters,towns;HQ h;h.m_Mode=&mode;h.m_Hunters=&hunters;h.m_Towns=&towns;
+ ERR_NativeMountedAmmoProbe::enabled=true;System::flag="1";
+ if(fault==1)ERR_NativeMountedAmmoProbe::enabled=false;if(fault==2)System::flag="";if(fault==3)System::flag="0";
+ if(fault==4)ERR_GameMode::current=&other;if(fault==5)mode.start=1;if(fault==6)mode.phase=2;
+ if(fault==7)hunters.deployed=1;if(fault==8)h.m_Hunters=nullptr;if(fault==9)h.m_Towns=nullptr;
+ assert(h.ERR_IsolateMountedBMP()==(fault==0));assert(hunters.stops==(fault==0?1:0)&&towns.stops==(fault==0?1:0));
+}}
+'''.replace(';if(', ';\n if('))
+print('PASS: actual opt-in pre-unlock isolation refuses wrong mode/phase/flag and existing hunters; no baseline service changes')