Wait for both convoy cargo phases and use actual magazine stock. Resolve empty primary weapon ammunition from muzzle metadata and recover cleanly from failed initial settings saves. Update native fixtures, scoped cleanup guards, packaging evidence and validation documentation. Make reviewed fixture tests checkout-relative. All repository checks pass against the isolated staged tree; native resupply completion and multiplayer qualification remain outstanding.
71 lines
6.6 KiB
Python
71 lines
6.6 KiB
Python
"""Execute fixture cargo readiness/selection against staged or repository source."""
|
|
import os,re,sys
|
|
from pathlib import Path
|
|
REPO=Path(os.environ.get('ERR_REPO', Path(__file__).resolve().parents[1]))
|
|
sys.path.insert(0,str(REPO/'tests'))
|
|
from policy_harness import body,run
|
|
P=Path(os.environ.get('ERR_INFANTRY_PROBE_SOURCE',REPO/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c'))
|
|
s='\n'.join(body(P,x) for x in ('protected int CargoReady(', 'protected bool SelectMagazine(', 'protected int MagazineCount('))
|
|
s=s.replace('protected ','').replace('foreach (','for (').replace('array<IEntity>', 'Array<Entity*>')
|
|
s=s.replace('ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(task);','Task* supply = task->phased ? task : nullptr;')
|
|
s=s.replace('ERR_ConvoyTask task','Task* task').replace('ERR_ConvoyCargoCallback operation','Operation* operation').replace('ERR_HQ hq','HQ* hq').replace('IEntity ','Entity* ')
|
|
s=s.replace('InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent));','Inventory* inventory = owner->inventory;')
|
|
s=s.replace('InventoryStorageManagerComponent recipient = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));','Inventory* recipient = actor->inventory;')
|
|
s=s.replace('BaseMagazineComponent.Cast(candidate.FindComponent(BaseMagazineComponent))','candidate->magazine').replace('BaseMagazineComponent.Cast(item.FindComponent(BaseMagazineComponent))','item->magazine')
|
|
s=s.replace('ERR_Inventory.Items','ERR_Inventory::Items').replace('ERR_Actors.CanFight','ERR_Actors::CanFight').replace('ERR_InfantryAmmoTransfer.Compatible','ERR_InfantryAmmoTransfer::Compatible').replace('EStoragePurpose.PURPOSE_DEPOSIT','0')
|
|
for v in ('task','supply','operation','hq','m_Unit','actor','recipient','inventory','owner','item'):s=s.replace(v+'.',v+'->')
|
|
s=s.replace('StatusSampler.','StatusSampler->').replace('Resupply().','Resupply()->')
|
|
s=re.sub(r'\bnull\b','nullptr',s)
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <algorithm>
|
|
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}};
|
|
struct Entity;
|
|
struct Inventory {bool space=true;Array<Entity*> items;bool FindStorageForItem(Entity*,int){return space;}};
|
|
struct Entity {bool magazine=true,alive=true,captured=true;int caliber=1;Inventory* inventory=nullptr;};
|
|
struct Operation{bool Finished=true;};
|
|
struct Task {bool Stopped=false,Ready=true,CargoIssued=true,phased=true,MagazinesIssued=true;Array<int> Vehicles={0,1,2,3,4,5};Array<Operation*> Cargo;};
|
|
struct Sampler{Array<Entity*> actors;bool attributed=true;int InitialStrength(){return actors.Count();}Entity* InitialMember(int i){return actors[i];}bool CanAttribute(int,Entity*){return attributed;}};
|
|
struct Unit {int Group=1;Sampler* StatusSampler;};
|
|
struct ResupplyService {bool idle=true;bool ERR_InfantryFixtureStock(Entity* e){return idle&&e->captured;}};
|
|
struct HQ {ResupplyService service;std::map<int,Unit*> recipients;Array<int> selected;int releases=0;ResupplyService*Resupply(){return &service;}
|
|
Unit* ERR_InfantryFixtureRecipient(Entity* m){selected.push_back(m->caliber);return recipients[m->caliber];}
|
|
void ReleaseLogistics(int,int token){assert(token==200001);releases++;}};
|
|
struct ERR_Actors{static bool CanFight(Entity* e){return e->alive;}};
|
|
struct ERR_InfantryAmmoTransfer{static bool Compatible(Entity*a,Entity*m){return a->caliber==m->caliber;}};
|
|
struct ERR_Inventory{static void Items(Inventory*i,Array<Entity*>&out){if(i)out=i->items;}};
|
|
struct Probe{static constexpr int TOKEN=200001;Unit*m_Unit=nullptr;Entity*m_Actor=nullptr,*m_Magazine=nullptr;
|
|
METHODS
|
|
};
|
|
int main(){
|
|
Probe p;Operation done,pending;pending.Finished=false;Task t;t.Cargo={&done};
|
|
assert(p.CargoReady(&t)==1);t.MagazinesIssued=false;assert(p.CargoReady(&t)==0);
|
|
t.phased=false;assert(p.CargoReady(&t)==1);t.phased=true;t.MagazinesIssued=true;
|
|
t.Ready=false;t.Vehicles.clear();assert(p.CargoReady(&t)==0);t.Vehicles={0,1,2,3,4,5};t.Ready=true;
|
|
t.CargoIssued=false;assert(p.CargoReady(&t)==0);t.CargoIssued=true;t.Ready=false;assert(p.CargoReady(&t)==0);t.Ready=true;
|
|
t.Cargo={&done,&pending};assert(p.CargoReady(&t)==0);pending.Finished=true;assert(p.CargoReady(&t)==1);
|
|
t.Cargo={nullptr};assert(p.CargoReady(&t)==-1);t.Cargo.assign(104,&done);assert(p.CargoReady(&t)==1);t.Cargo.push_back(&done);assert(p.CargoReady(&t)==-1);
|
|
t.Cargo={&done};t.Stopped=true;assert(p.CargoReady(&t)==-1);t.Stopped=false;t.Vehicles.pop_back();assert(p.CargoReady(&t)==-1);assert(p.CargoReady(nullptr)==-1);
|
|
Inventory inventory;Entity actor;actor.caliber=2;actor.inventory=&inventory;Sampler sampler{{&actor}};Unit unit{1,&sampler};HQ hq;hq.recipients[2]=&unit;
|
|
Entity rifle;rifle.magazine=false;Entity wrong;wrong.caliber=1;Entity right;right.caliber=2;Entity foreign=right;foreign.captured=false;
|
|
Array<Entity*> stock={nullptr,&rifle,&foreign,&wrong,&right};
|
|
assert(p.SelectMagazine(&hq,stock));assert(p.m_Magazine==&right&&p.m_Actor==&actor&&p.m_Unit==&unit);assert(hq.selected.Count()==2&&hq.selected[0]==1&&hq.selected[1]==2);
|
|
// A reservation whose actor changed cannot hide another compatible original item.
|
|
Probe retry;Entity secondActor;secondActor.caliber=3;secondActor.inventory=&inventory;Sampler secondSampler{{&secondActor}};Unit second{2,&secondSampler};hq.recipients[3]=&second;Entity alternate;alternate.caliber=3;
|
|
sampler.attributed=false;assert(retry.SelectMagazine(&hq,{&right,&alternate}));assert(retry.m_Magazine==&alternate&&hq.releases==1);
|
|
// Item counts include all physical magazine types and refuse unbounded scans.
|
|
inventory.items={&rifle,&wrong,&right,nullptr};Entity owner;owner.inventory=&inventory;assert(p.MagazineCount(&owner)==2);
|
|
inventory.items.assign(129,&right);assert(p.MagazineCount(&owner)==-1);owner.inventory=nullptr;assert(p.MagazineCount(&owner)==-1);
|
|
Probe unavailable;hq.service.idle=false;assert(!unavailable.SelectMagazine(&hq,{&right}));hq.service.idle=true;
|
|
Array<Entity*> tooMany(129,&right);assert(!unavailable.SelectMagazine(&hq,tooMany));
|
|
}
|
|
'''.replace('METHODS',s))
|
|
source=P.read_text();tick=body(P,'int Tick(ERR_HQ hq, float now)')
|
|
assert 'task.Cargo.Count() == 56' not in tick and 'ERR_ConvoyResources.Magazine()' not in source
|
|
assert 'm_Stock.Contains(magazine) && !m_Spent.Contains(magazine)' in source
|
|
assert 'moved.GetAmmoCount() == m_Rounds' in tick and 'm_Mode.Forces().Count() == m_OriginalLedger' in tick
|
|
assert '!Has(m_Truck.Entity, m_Magazine) && Has(m_Actor, m_Magazine)' in tick
|
|
print('PASS: actual fixture phased-cargo readiness, bounded callbacks, captured-stock mixed-caliber selection/continuation, reservation cleanup and component magazine counts')
|