Capture current mission, AI, map and administration development

Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
2026-10-13 22:52:53 +02:00
parent a951a96edc
commit 6a667d8deb
8104 changed files with 2124945 additions and 2061 deletions
@@ -0,0 +1,320 @@
--- /dev/null
+++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c
@@ -0,0 +1,167 @@
+// Historical evidence bound to an exact physical document. Undisclosed records
+// stay server-local; no live mine or soldier position is queried on recovery.
+class ERR_MineIntelRecord
+{
+ IEntity Mine;
+ vector Area;
+ ref array<IEntity> Folders = {};
+ bool Revealed;
+}
+class ERR_MineIntel
+{
+ protected ERR_GameMode m_Mode;
+ protected ref array<ref ERR_MineIntelRecord> m_Records = {};
+ protected int m_Bindings;
+ protected bool m_Stopped;
+ void ERR_MineIntel(ERR_GameMode mode) { m_Mode = mode; }
+ protected bool Current()
+ {
+ return Replication.IsServer() && !m_Stopped && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active();
+ }
+ protected bool Generic(IEntity folder)
+ {
+ return folder && folder.GetPrefabData() && folder.GetPrefabData().GetPrefabName() == ERR_Resources.IntelFolder()
+ && !folder.FindComponent(ERR_DocumentComponent) && m_Mode.Discovery() && !m_Mode.Discovery().IsSpent(folder);
+ }
+ // Called once at accepted engineer-job admission, before approaching the site.
+ void Candidates(IEntity actor, out array<IEntity> folders)
+ {
+ folders.Clear();
+ if (!Current() || !ERR_Actors.CanFight(actor) || ERR_Actors.Player(actor)) return;
+ if (!m_Mode.EnemyFaction() || SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction()) return;
+ InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));
+ if (!inventory) return;
+ array<IEntity> found = {}; ERR_DiscoveryService.Folders(inventory, found);
+ if (found.Count() > 128) return;
+ foreach (IEntity folder : found)
+ {
+ if (folders.Count() >= 16) break;
+ if (Generic(folder) && ERR_InfantryAmmoTransfer.StoredUnder(folder, actor) && !folders.Contains(folder)) folders.Insert(folder);
+ }
+ }
+ bool Seal(IEntity actor, IEntity mine, vector position, array<IEntity> candidates)
+ {
+ if (!Current() || !ERR_Actors.CanFight(actor) || ERR_Actors.Player(actor)) return false;
+ if (!m_Mode.EnemyFaction() || SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction()) return false;
+ if (!candidates || candidates.IsEmpty() || candidates.Count() > 16 || m_Records.Count() >= 32 || m_Bindings >= 128) return false;
+ if (!ERR_ForceRules.FiniteVector(position) || !ERR_Actors.Alive(mine) || !mine.GetPrefabData()) return false;
+ if (mine.GetPrefabData().GetPrefabName() != ERR_EnemyLoadoutCatalog.MINE || mine.GetParent()) return false;
+ if (vector.Distance(mine.GetOrigin(), position) > 1) return false;
+ InventoryItemComponent item = InventoryItemComponent.Cast(mine.FindComponent(InventoryItemComponent));
+ SCR_PressureTriggerComponent trigger = SCR_PressureTriggerComponent.Cast(mine.FindComponent(SCR_PressureTriggerComponent));
+ if (!item || item.GetParentSlot() || !trigger || !trigger.IsActivated()) return false;
+ foreach (ERR_MineIntelRecord known : m_Records) if (known.Mine == mine) return false;
+ array<IEntity> held = {}; Candidates(actor, held);
+ ref ERR_MineIntelRecord record = new ERR_MineIntelRecord();
+ foreach (IEntity folder : candidates)
+ {
+ if (m_Bindings + record.Folders.Count() >= 128) break;
+ if (held.Contains(folder) && !record.Folders.Contains(folder)) record.Folders.Insert(folder);
+ }
+ if (record.Folders.IsEmpty()) return false;
+ record.Mine = mine;
+ record.Area = Vector(ERR_DiscoveryMapRules.Coordinate(position[0], 1), 0, ERR_DiscoveryMapRules.Coordinate(position[2], 1));
+ m_Bindings += record.Folders.Count();
+ m_Records.Insert(record);
+ return true;
+ }
+ bool Recover(IEntity player, IEntity folder)
+ {
+ if (!Current() || !m_Mode.Players() || !m_Mode.Players().CurrentActor(player) || !ERR_Actors.Alive(player)) return false;
+ if (!m_Mode.PlayerFaction() || SCR_FactionManager.SGetFaction(player) != m_Mode.PlayerFaction() || !Generic(folder)) return false;
+ if (!ERR_InfantryAmmoTransfer.StoredUnder(folder, player)) return false;
+ InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(player.FindComponent(InventoryStorageManagerComponent));
+ if (!inventory) return false;
+ array<IEntity> held = {}; ERR_DiscoveryService.Folders(inventory, held);
+ if (held.Count() > 128 || !held.Contains(folder)) return false;
+ bool revealed = false;
+ foreach (ERR_MineIntelRecord record : m_Records)
+ {
+ if (record.Revealed || !record.Folders.Contains(folder)) continue;
+ if (m_Mode.ERR_RevealMineArea(record.Area)) { record.Revealed = true; revealed = true; }
+ }
+ return revealed;
+ }
+ void Stop() { m_Stopped = true; m_Records.Clear(); m_Bindings = 0; }
+}
+
+modded class ERR_GameMode
+{
+ protected ref ERR_MineIntel m_ERRMineIntel;
+ // Only recovered, quantized historical warnings are replicated, including JIP.
+ [RplProp()]
+ protected ref array<vector> m_ERRMineAreas = {};
+ protected ref array<ref ERR_DiscoveryMarker> m_ERRMineMarkers = {};
+ protected bool m_ERRMineIntelStopped;
+ protected SCR_MapMarkerManagerComponent m_ERRMineMarkerOwner;
+ ERR_MineIntel MineIntel() { return m_ERRMineIntel; }
+ protected override void EOnInit(IEntity owner)
+ {
+ super.EOnInit(owner);
+ if (SCR_Global.IsEditMode()) return;
+ if (Replication.IsServer()) m_ERRMineIntel = new ERR_MineIntel(this);
+ OnStop().Insert(ERR_StopMineIntel);
+ if (RplSession.Mode() != RplMode.Dedicated) GetGame().GetCallqueue().CallLater(ERR_UpdateMineMarkers, 1500, true);
+ }
+ bool ERR_RevealMineArea(vector area)
+ {
+ if (!Replication.IsServer() || m_ERRMineIntelStopped || this != ERR_GameMode.Get() || !Active()) return false;
+ if (!ERR_ForceRules.FiniteVector(area)) return false;
+ // Canonicalize at the publication boundary too: never publish precise points.
+ vector cell = Vector(ERR_DiscoveryMapRules.Coordinate(area[0], 1), 0, ERR_DiscoveryMapRules.Coordinate(area[2], 1));
+ if (m_ERRMineAreas.Contains(cell)) return true;
+ if (m_ERRMineAreas.Count() >= 32) return false;
+ m_ERRMineAreas.Insert(cell);
+ Replication.BumpMe();
+ return true;
+ }
+ protected void ERR_ClearMineMarkers()
+ {
+ SCR_MapMarkerManagerComponent manager = m_ERRMineMarkerOwner;
+ foreach (ERR_DiscoveryMarker marker : m_ERRMineMarkers)
+ {
+ if (manager) manager.ERR_RemoveDiscoveryMarker(marker);
+ else if (marker) marker.OnDelete();
+ }
+ m_ERRMineMarkers.Clear();
+ m_ERRMineMarkerOwner = null;
+ }
+ protected void ERR_UpdateMineMarkers()
+ {
+ if (!GetGame() || m_ERRMineIntelStopped || this != ERR_GameMode.Get() || !Active()) { ERR_ClearMineMarkers(); return; }
+ if (!GetGame().GetPlayerController()) return;
+ SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance();
+ if (manager != m_ERRMineMarkerOwner) ERR_ClearMineMarkers();
+ if (!manager || !manager.GetMarkerConfig()) return;
+ if (m_ERRMineAreas.Count() > 32) { ERR_ClearMineMarkers(); return; }
+ if (m_ERRMineMarkers.Count() > m_ERRMineAreas.Count()) ERR_ClearMineMarkers();
+ m_ERRMineMarkerOwner = manager;
+ for (int i = m_ERRMineMarkers.Count(); i < m_ERRMineAreas.Count(); i++)
+ {
+ ERR_DiscoveryMarker marker = new ERR_DiscoveryMarker();
+ marker.SetType(SCR_EMapMarkerType.PLACED_CUSTOM);
+ marker.SetMarkerConfigID(0);
+ marker.SetDiscoveryPosition(m_ERRMineAreas[i], 1);
+ marker.SetLocationIcon(ERR_LocationKind.OUTPOST, "", 1);
+ marker.SetCustomText("Reported mine area (500 m); may still be active");
+ manager.InsertStaticMarker(marker, true);
+ m_ERRMineMarkers.Insert(marker);
+ }
+ }
+ protected void ERR_StopMineIntel()
+ {
+ if (m_ERRMineIntelStopped) return;
+ m_ERRMineIntelStopped = true;
+ if (m_ERRMineIntel) m_ERRMineIntel.Stop();
+ if (GetGame() && GetGame().GetCallqueue()) GetGame().GetCallqueue().Remove(ERR_UpdateMineMarkers);
+ ERR_ClearMineMarkers();
+ if (Replication.IsServer()) { m_ERRMineAreas.Clear(); Replication.BumpMe(); }
+ OnStop().Remove(ERR_StopMineIntel);
+ }
+ void ~ERR_GameMode()
+ {
+ if (GetGame() && GetGame().GetCallqueue()) GetGame().GetCallqueue().Remove(ERR_UpdateMineMarkers);
+ if (m_ERRMineIntel) m_ERRMineIntel.Stop();
+ ERR_ClearMineMarkers();
+ }
+}
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c
@@ -55,6 +55,7 @@
protected ref SCR_AIBehaviorBase m_Action;
protected ref ERR_EngineerMineRemoval m_Removal;
protected ref array<IEntity> m_Attempted;
+ protected ref array<IEntity> m_IntelFolders = {};
protected vector m_Position;
protected vector m_Rally;
protected float m_Started = -1;
@@ -204,6 +205,7 @@
// The shared exact-item tombstone survives pickup, transfer and late callbacks.
m_Attempted.Insert(m_Mine);
if (!Carried()) return Refuse();
+ if (m_Mode.MineIntel()) m_Mode.MineIntel().Candidates(m_Actor, m_IntelFolders);
m_Started = now; m_LastTick = now; m_State = 0;
Move(m_Position);
ERR_HQ.Event("ENGINEER MINE", "original carried PMN4 assigned; one approach and finite 180s deadline");
@@ -261,7 +263,11 @@
if (!ERR_EngineerMineRules.MayArm(Placed(), Owned() && Quiet(), vector.DistanceXZ(m_Actor.GetOrigin(), m_Position), m_FriendlyNear)) return;
m_Trigger.SetUser(m_Actor);
m_Trigger.ActivateTrigger();
- if (m_Trigger.IsActivated()) ERR_HQ.Event("ENGINEER MINE", "original PMN4 armed after engineer withdrawal and physical friendly clearance");
+ if (m_Trigger.IsActivated())
+ {
+ if (m_Mode.MineIntel()) m_Mode.MineIntel().Seal(m_Actor, m_Mine, m_Position, m_IntelFolders);
+ ERR_HQ.Event("ENGINEER MINE", "original PMN4 armed after engineer withdrawal and physical friendly clearance");
+ }
Stop();
}
}
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c
@@ -53,6 +53,8 @@
foreach (IEntity folder : folders)
{
if (!folder || m_Spent.Contains(folder) || m_Spent.Count() >= 4096) continue;
+ bool mineRecovered = false;
+ if (m_Mode.MineIntel()) mineRecovered = m_Mode.MineIntel().Recover(player, folder);
array<ERR_LocationComponent> locations = {};
m_Mode.Locations(locations);
array<ERR_LocationComponent> eligible = {};
@@ -70,7 +72,7 @@
}
if (eligible.IsEmpty())
{
- if (!document && MarkSpent(folder)) m_Mode.ERR_IntelExhausted(!sealedTarget.IsEmpty());
+ if (!document && MarkSpent(folder) && !mineRecovered) m_Mode.ERR_IntelExhausted(!sealedTarget.IsEmpty());
continue;
}
ERR_LocationComponent chosen = eligible.GetRandomElement();
--- /dev/null
+++ b/tests/test_mine_intel.py
@@ -0,0 +1,96 @@
+"""Actual mine evidence/publication/marker bodies with native doubles, not engine/MP proof."""
+import os,re
+from pathlib import Path
+from policy_harness import ROOT,body,run
+P=Path(os.environ.get('ERR_MINE_INTEL_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c'))
+def cpp(s):
+ s=s.replace('protected ','').replace('ref ','').replace('out ','').replace('null','nullptr').replace('array<','Array<').replace(' = {};',';').replace('foreach (','for (')
+ s=s.replace('Array<IEntity> folders)', 'Array<IEntity>& folders)').replace('Array<IEntity> candidates)', 'Array<IEntity>& candidates)').replace('!candidates || ','')
+ for t in ['InventoryStorageManagerComponent','InventoryItemComponent','SCR_PressureTriggerComponent','ERR_MineIntelRecord','ERR_DiscoveryMarker','SCR_MapMarkerManagerComponent']:
+ s=re.sub(r'\b'+t+r' (\w+)',t+r'* \1',s)
+ for ns in ['Replication','ERR_GameMode','ERR_Actors','SCR_FactionManager','ERR_Resources','ERR_DiscoveryService','ERR_InfantryAmmoTransfer','ERR_ForceRules','ERR_EnemyLoadoutCatalog','ERR_DiscoveryMapRules','InventoryStorageManagerComponent','InventoryItemComponent','SCR_PressureTriggerComponent','SCR_MapMarkerManagerComponent','ERR_LocationKind','SCR_EMapMarkerType','vector']:
+ s=s.replace(ns+'.',ns+'::')
+ for obj in ['m_Mode','folder','actor','mine','player','inventory','item','trigger','record','known','manager','marker','m_ERRMineIntel']:
+ s=re.sub(r'\b'+obj+r'\.',obj+'->',s)
+ s=s.replace('bool revealed;', 'bool revealed=false;')
+ s=s.replace('GetPrefabData().','GetPrefabData()->').replace('Discovery().','Discovery()->').replace('Players().','Players()->').replace('GetGame().','GetGame()->').replace('GetCallqueue().','GetCallqueue()->').replace('OnStop().','OnStop()->')
+ s=re.sub(r'FindComponent\((\w+)\)',r'FindComponent("\1")',s)
+ s=s.replace('Remove(ERR_UpdateMineMarkers)','Remove(1)').replace('Remove(ERR_StopMineIntel)','Remove(2)')
+ return s
+service='\n'.join(body(P,x) for x in ['protected bool Current(','protected bool Generic(','void Candidates(','bool Seal(','bool Recover(','void Stop('])
+destructor=body(P,'void ~ERR_GameMode(')
+mode='\n'.join(body(P,x) for x in ['bool ERR_RevealMineArea(','protected void ERR_ClearMineMarkers(','protected void ERR_UpdateMineMarkers(','protected void ERR_StopMineIntel('])
+# Enforce references are not modelled by raw C++ pointers. Lifecycle bodies only.
+run(r'''
+#include <cassert>
+#include <cmath>
+#include <string>
+#include <vector>
+#include <algorithm>
+struct vector {float a[3]={0,0,0};float& operator[](int n){return a[n];}bool operator==(const vector&b)const{return a[0]==b.a[0]&&a[1]==b.a[1]&&a[2]==b.a[2];}static float Distance(vector a,vector b){return std::sqrt(std::pow(a[0]-b[0],2)+std::pow(a[1]-b[1],2)+std::pow(a[2]-b[2],2));}};
+vector Vector(float x,float y,float z){return {{x,y,z}};}
+template<class T>struct Array:std::vector<T>{int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Clear(){this->clear();}bool Contains(T a){return std::find(this->begin(),this->end(),a)!=this->end();}void Insert(T a){this->push_back(a);}};
+struct Entity;using IEntity=Entity*;struct Prefab {std::string name="intel";std::string GetPrefabName(){return name;}};
+struct InventoryStorageManagerComponent {Array<IEntity> folders;static InventoryStorageManagerComponent*Cast(void*p){return (InventoryStorageManagerComponent*)p;}};
+struct InventoryItemComponent {void*slot=nullptr;void*GetParentSlot(){return slot;}static InventoryItemComponent*Cast(void*p){return (InventoryItemComponent*)p;}};
+struct SCR_PressureTriggerComponent {bool active=true;bool IsActivated(){return active;}static SCR_PressureTriggerComponent*Cast(void*p){return (SCR_PressureTriggerComponent*)p;}};
+struct Entity {bool alive=true,player=false,objective=false;int faction=1,reads=0;IEntity owner=nullptr,parent=nullptr;vector position;Prefab prefab;InventoryStorageManagerComponent*inv=nullptr;InventoryItemComponent item;SCR_PressureTriggerComponent trigger;
+ Prefab*GetPrefabData(){reads++;return &prefab;}IEntity GetParent(){reads++;return parent;}vector GetOrigin(){reads++;return position;}
+ void*FindComponent(std::string t){reads++;if(t=="ERR_DocumentComponent")return objective?this:nullptr;if(t=="InventoryStorageManagerComponent")return inv;if(t=="InventoryItemComponent")return &item;if(t=="SCR_PressureTriggerComponent")return &trigger;return nullptr;}};
+namespace Replication {bool server=true;int bumps=0;bool IsServer(){return server;}void BumpMe(){bumps++;}}
+namespace ERR_Actors {bool CanFight(IEntity e){return e&&e->alive;}bool Alive(IEntity e){return e&&e->alive;}bool Player(IEntity e){return e&&e->player;}}
+namespace SCR_FactionManager {int SGetFaction(IEntity e){return e?e->faction:0;}}
+namespace ERR_Resources {std::string IntelFolder(){return "intel";}}
+namespace ERR_EnemyLoadoutCatalog {std::string MINE="mine";}
+namespace ERR_DiscoveryService {void Folders(InventoryStorageManagerComponent*i,Array<IEntity>&f){f=i->folders;}}
+namespace ERR_InfantryAmmoTransfer {bool StoredUnder(IEntity f,IEntity a){return f&&a&&f->owner==a;}}
+namespace ERR_ForceRules {bool FiniteVector(vector a){return std::isfinite(a[0])&&std::isfinite(a[1])&&std::isfinite(a[2]);}}
+namespace ERR_DiscoveryMapRules {int Coordinate(float x,int){return std::floor(x/500.f)*500+250;}}
+struct DiscoveryService {Array<IEntity> spent;bool IsSpent(IEntity f){return spent.Contains(f);}};
+struct PlayersService {IEntity current=nullptr;bool CurrentActor(IEntity e){return e&&e==current;}};
+struct Queue {int removed=0;void Remove(int){removed++;}};
+struct Game {bool controller=true;Queue queue;bool GetPlayerController(){return controller;}Queue*GetCallqueue(){return &queue;}}game;Game*currentGame=&game;Game*GetGame(){return currentGame;}
+struct Invoker {int removed=0;void Remove(int){removed++;}};
+namespace ERR_LocationKind {int OUTPOST=3;}namespace SCR_EMapMarkerType {int PLACED_CUSTOM=1;}
+struct ERR_DiscoveryMarker {vector position;std::string label;int deleted=0;void SetType(int){}void SetMarkerConfigID(int){}void SetDiscoveryPosition(vector p,int){position=p;}void SetLocationIcon(int,std::string,int){}void SetCustomText(std::string s){label=s;}void OnDelete(){deleted++;}};
+struct SCR_MapMarkerManagerComponent {static inline SCR_MapMarkerManagerComponent*current=nullptr;bool config=true;Array<ERR_DiscoveryMarker*> inserted,removed;static SCR_MapMarkerManagerComponent*GetInstance(){return current;}bool GetMarkerConfig(){return config;}void InsertStaticMarker(ERR_DiscoveryMarker*m,bool){inserted.Insert(m);}void ERR_RemoveDiscoveryMarker(ERR_DiscoveryMarker*m){removed.Insert(m);m->OnDelete();}};
+struct ERR_MineIntel;
+struct ERR_GameMode {static inline ERR_GameMode*current=nullptr;bool active=true;int enemy=1,player=2;DiscoveryService discovery;PlayersService players;Invoker stop;
+ ERR_MineIntel*m_ERRMineIntel=nullptr;Array<vector>m_ERRMineAreas;Array<ERR_DiscoveryMarker*>m_ERRMineMarkers;bool m_ERRMineIntelStopped=false;SCR_MapMarkerManagerComponent*m_ERRMineMarkerOwner=nullptr;
+ static ERR_GameMode*Get(){return current;}bool Active(){return active;}int EnemyFaction(){return enemy;}int PlayerFaction(){return player;}DiscoveryService*Discovery(){return &discovery;}PlayersService*Players(){return &players;}Invoker*OnStop(){return &stop;}
+ void Destroy();bool ERR_RevealMineArea(vector);void ERR_ClearMineMarkers();void ERR_UpdateMineMarkers();void ERR_StopMineIntel();};
+struct ERR_MineIntelRecord {IEntity Mine=nullptr;vector Area;Array<IEntity> Folders;bool Revealed=false;};
+struct ERR_MineIntel {ERR_GameMode*m_Mode;Array<ERR_MineIntelRecord*>m_Records;int m_Bindings=0;bool m_Stopped=false;ERR_MineIntel(ERR_GameMode*m):m_Mode(m){}
+'''+cpp(service)+r'''};
+'''+re.sub(r'\b(bool|void) (ERR_\w+)\(',r'\1 ERR_GameMode::\2(',cpp(mode))+cpp(destructor).replace('void ~ERR_GameMode()', 'void ERR_GameMode::Destroy()')+r'''
+struct Fixture {ERR_GameMode mode;ERR_MineIntel intel{&mode};Entity engineer,player,folder,mine;InventoryStorageManagerComponent ei,pi;Array<IEntity> candidates;
+ Fixture(){ERR_GameMode::current=&mode;Replication::server=true;currentGame=&game;game.controller=true;SCR_MapMarkerManagerComponent::current=nullptr;mode.m_ERRMineIntel=&intel;mode.players.current=&player;player.player=true;player.faction=2;engineer.inv=&ei;player.inv=&pi;folder.owner=&engineer;ei.folders.Insert(&folder);mine.prefab.name="mine";mine.position=Vector(1030,0,2340);}
+ void Capture(){intel.Candidates(&engineer,candidates);assert(candidates.Count()==1);}
+ void Seal(){Capture();assert(intel.Seal(&engineer,&mine,mine.position,candidates));assert(mode.m_ERRMineAreas.empty());}
+ void Transfer(){ei.folders.Clear();pi.folders.Insert(&folder);folder.owner=&player;}
+};
+int main(){
+ Fixture base;base.Seal();assert(!base.intel.Seal(&base.engineer,&base.mine,base.mine.position,base.candidates));base.Transfer();int reads=base.mine.reads;int actorReads=base.engineer.reads;base.mine.alive=false;base.mine.position=Vector(9000,0,9000);base.intel.Recover(&base.player,&base.folder);assert(base.mode.m_ERRMineAreas.Count()==1&&base.mode.m_ERRMineAreas[0]==Vector(1250,0,2250));assert(base.mine.reads==reads&&base.engineer.reads==actorReads);base.intel.Recover(&base.player,&base.folder);assert(base.mode.m_ERRMineAreas.Count()==1);
+ // Original site content is never modified or looked up by the evidence service.
+ // An objective, foreign/spent folder or a newly issued folder cannot be sealed.
+ for(int fault=0;fault<6;fault++){Fixture f;f.Capture();Entity newFolder;newFolder.owner=&f.engineer;
+ switch(fault){case 0:f.folder.objective=true;break;case 1:f.folder.owner=&f.player;break;case 2:f.mode.discovery.spent.Insert(&f.folder);break;case 3:f.ei.folders.Clear();f.ei.folders.Insert(&newFolder);break;case 4:f.engineer.faction=2;break;case 5:f.engineer.player=true;break;}
+ assert(!f.intel.Seal(&f.engineer,&f.mine,f.mine.position,f.candidates)&&f.intel.m_Records.empty()&&f.mode.m_ERRMineAreas.empty());}
+ // Unarmed, moved, destroyed, attached and unrelated mines cannot create records.
+ for(int fault=0;fault<5;fault++){Fixture f;f.Capture();vector position=f.mine.position;switch(fault){case 0:f.mine.trigger.active=false;break;case 1:f.mine.position=Vector(9999,0,0);break;case 2:f.mine.alive=false;break;case 3:f.mine.item.slot=&f.ei;break;case 4:f.mine.prefab.name="other";break;}assert(!f.intel.Seal(&f.engineer,&f.mine,position,f.candidates));}
+ for(int fault=0;fault<8;fault++){Fixture f;f.Seal();f.Transfer();ERR_GameMode newer;Entity other;switch(fault){case 0:f.mode.players.current=&other;break;case 1:f.player.alive=false;break;case 2:f.player.faction=1;break;case 3:f.folder.owner=&other;break;case 4:f.pi.folders.Clear();break;case 5:f.mode.discovery.spent.Insert(&f.folder);break;case 6:ERR_GameMode::current=&newer;break;case 7:f.intel.Stop();break;}f.intel.Recover(&f.player,&f.folder);assert(f.mode.m_ERRMineAreas.empty());}
+ Fixture caps;caps.Capture();caps.intel.m_Bindings=128;assert(!caps.intel.Seal(&caps.engineer,&caps.mine,caps.mine.position,caps.candidates));caps.intel.m_Bindings=0;caps.intel.m_Records.resize(32,nullptr);assert(!caps.intel.Seal(&caps.engineer,&caps.mine,caps.mine.position,caps.candidates));
+ Fixture publish;for(int i=0;i<32;i++)assert(publish.mode.ERR_RevealMineArea(Vector(i*500,0,0)));assert(publish.mode.ERR_RevealMineArea(Vector(10,0,20)));assert(!publish.mode.ERR_RevealMineArea(Vector(32000,0,0)));assert(!publish.mode.ERR_RevealMineArea(Vector(NAN,0,0)));
+ // Failed publication must remain recoverable instead of consuming warning.
+ Fixture retry;retry.Seal();retry.Transfer();for(int i=0;i<32;i++)retry.mode.m_ERRMineAreas.Insert(Vector(i*500+250,0,250));retry.intel.Recover(&retry.player,&retry.folder);assert(!retry.intel.m_Records[0]->Revealed);retry.mode.m_ERRMineAreas.Clear();retry.intel.Recover(&retry.player,&retry.folder);assert(retry.intel.m_Records[0]->Revealed);
+ // Marker polling waits through preparation/JIP and missing native dependencies.
+ Fixture markers;markers.mode.m_ERRMineAreas.Insert(Vector(1250,0,2250));markers.mode.active=false;markers.mode.ERR_UpdateMineMarkers();assert(!markers.mode.m_ERRMineIntelStopped);markers.mode.active=true;markers.mode.ERR_UpdateMineMarkers();assert(markers.mode.m_ERRMineMarkers.empty());SCR_MapMarkerManagerComponent first,second;SCR_MapMarkerManagerComponent::current=&first;first.config=false;markers.mode.ERR_UpdateMineMarkers();assert(first.inserted.empty());first.config=true;game.controller=false;markers.mode.ERR_UpdateMineMarkers();assert(first.inserted.empty());game.controller=true;markers.mode.ERR_UpdateMineMarkers();markers.mode.ERR_UpdateMineMarkers();assert(first.inserted.Count()==1&&first.inserted[0]->position==Vector(1250,0,2250));assert(first.inserted[0]->label=="Reported mine area (500 m); may still be active");
+ SCR_MapMarkerManagerComponent::current=&second;markers.mode.ERR_UpdateMineMarkers();assert(first.removed.Count()==1&&second.inserted.Count()==1);markers.mode.active=false;markers.mode.ERR_UpdateMineMarkers();assert(second.removed.Count()==1);markers.mode.active=true;markers.mode.ERR_UpdateMineMarkers();assert(second.inserted.Count()==2);markers.mode.ERR_StopMineIntel();markers.mode.ERR_StopMineIntel();assert(markers.intel.m_Stopped&&markers.mode.m_ERRMineMarkers.empty()&&markers.mode.m_ERRMineAreas.empty()&&second.removed.Count()==2);markers.mode.ERR_UpdateMineMarkers();assert(second.inserted.Count()==2);
+ // Shrink rebuild must retain manager ownership for replacement marker cleanup.
+ Fixture shrink;SCR_MapMarkerManagerComponent shrinking;SCR_MapMarkerManagerComponent::current=&shrinking;shrink.mode.m_ERRMineAreas.Insert(Vector(250,0,250));shrink.mode.m_ERRMineAreas.Insert(Vector(750,0,250));shrink.mode.ERR_UpdateMineMarkers();assert(shrinking.inserted.Count()==2);shrink.mode.m_ERRMineAreas.resize(1);shrink.mode.ERR_UpdateMineMarkers();assert(shrinking.removed.Count()==2&&shrinking.inserted.Count()==3&&shrink.mode.m_ERRMineMarkerOwner==&shrinking);shrink.mode.ERR_StopMineIntel();assert(shrinking.removed.Count()==3);
+ Fixture destroyed;SCR_MapMarkerManagerComponent deletion;SCR_MapMarkerManagerComponent::current=&deletion;destroyed.mode.m_ERRMineAreas.Insert(Vector(250,0,250));destroyed.mode.ERR_UpdateMineMarkers();int removedCallbacks=game.queue.removed;destroyed.mode.Destroy();assert(destroyed.intel.m_Stopped&&destroyed.mode.m_ERRMineMarkers.empty()&&deletion.removed.Count()==1&&game.queue.removed==removedCallbacks+1);
+ Fixture bindings;Array<Entity> moreFolders;moreFolders.resize(16);bindings.ei.folders.Clear();for(auto&f:moreFolders){f.owner=&bindings.engineer;bindings.ei.folders.Insert(&f);}bindings.intel.Candidates(&bindings.engineer,bindings.candidates);assert(bindings.candidates.Count()==16);Array<Entity> mines;mines.resize(9);for(int i=0;i<9;i++){mines[i].prefab.name="mine";mines[i].position=Vector(30,0,40);bool sealed=bindings.intel.Seal(&bindings.engineer,&mines[i],mines[i].position,bindings.candidates);assert(sealed==(i<8));}assert(bindings.intel.m_Bindings==128&&bindings.intel.m_Records.Count()==8);
+ Fixture replica;Replication::server=false;assert(!replica.mode.ERR_RevealMineArea(Vector(1000,0,2000)));replica.intel.Candidates(&replica.engineer,replica.candidates);assert(replica.candidates.empty());
+}
+''')
+print('PASS: actual mine evidence sealing/recovery, historical coarse publication, caps, canonical ownership, marker join retry/owner-change/stop; native arming and replicated vector-array transport untested')
@@ -0,0 +1,19 @@
check: /tmp/err-policy-pt5u3pjk/check.cpp:290: void Fixture::Begin(): Assertion `attempted.Count()==1&&utility.additions==1&&mode.mineIntel.candidates==1&&mode.mineIntel.capturedActor==&actor&&mode.mineIntel.seals==0' failed.
Traceback (most recent call last):
File "/tmp/erri-mine-intel-integration/tests/test_engineer_mine.py", line 31, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<143 lines>...
}
^
''')
^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-pt5u3pjk/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,19 @@
check: /tmp/err-policy-28975rae/check.cpp:74: int main(): Assertion `f.mode.mine.calls==1&&f.mode.mine.lastPlayer==&f.player&&f.mode.mine.recovered[0]==&f.folder' failed.
Traceback (most recent call last):
File "/tmp/erri-mine-intel-integration/tests/test_mine_intel_discovery_integration.py", line 20, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<53 lines>...
}
^
''')
^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-28975rae/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,196 @@
--- a/tests/test_engineer_mine.py
+++ b/tests/test_engineer_mine.py
@@ -18,7 +18,7 @@
for field in ['StatusSampler','InfantryCombat','m_UtilityComponent']:
s=s.replace(field+'.',field+'->')
s=s.replace('InfantryCombat->Held','InfantryCombat.Held')
- s=s.replace('GetPrefabData().','GetPrefabData()->').replace('EnemyFaction().','EnemyFaction()->').replace('Forces().','Forces()->')
+ s=s.replace('GetPrefabData().','GetPrefabData()->').replace('EnemyFaction().','EnemyFaction()->').replace('Forces().','Forces()->').replace('MineIntel().','MineIntel()->')
s=s.replace('GetGame().','GetGame()->').replace('GetWorld().','GetWorld()->')
s=re.sub(r'FindComponent\((\w+)\)',r'FindComponent("\1")',s)
s=s.replace('CheckFriendly, queryFlags: EQueryEntitiesFlags.ALL','[this](IEntity entity){return CheckFriendly(entity);}, 1')
@@ -39,7 +39,7 @@
struct vector {float x=0,y=0,z=0;float LengthSq(){return x*x+y*y+z*z;}
static float Distance(vector a,vector b){return std::sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}
static float DistanceXZ(vector a,vector b){a.y=b.y=0;return Distance(a,b);}};
-template<class T>struct Array:std::vector<T>{int Count(){return this->size();}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}void Insert(T t){this->push_back(t);}};
+template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;using std::vector<T>::operator=;int Count(){return this->size();}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}void Insert(T t){this->push_back(t);}};
struct Entity;using IEntity=Entity*;struct SCR_AIGroup;struct SCR_ChimeraAIAgent;struct SCR_InventoryStorageManagerComponent;struct ERR_EngineerMineRemoval;
struct Faction {bool enemy=false;bool IsFactionEnemy(Faction* f){return f&&f->enemy;}};
struct Physics {vector velocity;vector GetVelocity(){return velocity;}};
@@ -68,7 +68,11 @@
struct ERR_HQReport{};struct ERR_ForceRecord {SCR_AIGroup* Group=nullptr;bool Physical=true,Eliminated=false;string SourceId="original";int InitialStrength=1;};
struct Ledger {ERR_ForceRecord* record=nullptr;ERR_ForceRecord* FindGroup(SCR_AIGroup*){return record;}};
struct ERR_HQUnit {SCR_AIGroup* Group=nullptr;ERR_HQTask* Task=nullptr;ERR_HQReport* Assignment=nullptr;ERR_HQTask* PendingTask=nullptr;ERR_HQReport* PendingOrder=nullptr;Sampler* StatusSampler=nullptr;struct{bool Held=false;}InfantryCombat;bool ReservedForSupport=false;int LogisticsReservation=0;string ForceSourceId="original";};
-struct ERR_GameMode {static inline ERR_GameMode* current=nullptr;bool active=true;Faction* faction=nullptr;Ledger* ledger=nullptr;static ERR_GameMode* Get(){return current;}bool Active(){return active;}Faction* EnemyFaction(){return faction;}Ledger* Forces(){return ledger;}};
+struct MineIntel {int candidates=0,seals=0;IEntity capturedActor=nullptr,sealedMine=nullptr;vector position;Array<IEntity> available,captured,sealed;
+ void Candidates(IEntity actor,Array<IEntity>&out){candidates++;capturedActor=actor;out=available;captured=out;}
+ void Seal(IEntity actor,IEntity mine,vector p,Array<IEntity>&folders){assert(actor==capturedActor&&mine&&mine->trigger&&mine->trigger->active);seals++;sealedMine=mine;position=p;sealed=folders;assert(folders==captured);}
+};
+struct ERR_GameMode {struct MineIntel mineIntel;bool haveMineIntel=true;struct MineIntel* MineIntel(){return haveMineIntel?&mineIntel:nullptr;}static inline ERR_GameMode* current=nullptr;bool active=true;Faction* faction=nullptr;Ledger* ledger=nullptr;static ERR_GameMode* Get(){return current;}bool Active(){return active;}Faction* EnemyFaction(){return faction;}Ledger* Forces(){return ledger;}};
namespace ERR_ForceRules {bool Finite(float f){return std::isfinite(f);}bool FiniteVector(vector v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}}
namespace Replication {bool server=true;bool IsServer(){return server;}}
namespace ERR_HunterCombat {bool engaged=false;bool Active(SCR_AIGroup*){return engaged;}}
@@ -88,19 +92,26 @@
'''+cpp(callback)+r'''};
bool SCR_InventoryStorageManagerComponent::TryRemoveItemFromInventory(IEntity,void*,ERR_EngineerMineRemoval* cb){calls++;callback=cb;if(inlineResult>0)cb->OnComplete();if(inlineResult<0)cb->OnFailed();return accepted;}
struct ERR_EngineerMine {
- ERR_GameMode* m_Mode=nullptr;ERR_HQUnit* m_Unit=nullptr;SCR_AIGroup* m_Group=nullptr;ERR_HQTask* m_Task=nullptr;ERR_HQReport* m_Assignment=nullptr;ERR_ForceRecord* m_Record=nullptr;string m_SourceId;int m_Strength=0;IEntity m_Actor=nullptr;int m_Slot=0;IEntity m_Mine=nullptr;SCR_PressureTriggerComponent* m_Trigger=nullptr;SCR_InventoryStorageManagerComponent* m_Inventory=nullptr;SCR_AIUtilityComponent* m_Utility=nullptr;SCR_AIBehaviorBase* m_Action=nullptr;ERR_EngineerMineRemoval* m_Removal=nullptr;Array<IEntity>* m_Attempted=nullptr;vector m_Position,m_Rally;float m_Started=-1,m_LastTick=-1,m_PreparedAt=-1,m_NextClearance=0;int m_State=0,m_Checked=0;bool m_FriendlyNear=false,m_Begun=false,m_Stopped=false;
+ ERR_GameMode* m_Mode=nullptr;ERR_HQUnit* m_Unit=nullptr;SCR_AIGroup* m_Group=nullptr;ERR_HQTask* m_Task=nullptr;ERR_HQReport* m_Assignment=nullptr;ERR_ForceRecord* m_Record=nullptr;string m_SourceId;int m_Strength=0;IEntity m_Actor=nullptr;int m_Slot=0;IEntity m_Mine=nullptr;SCR_PressureTriggerComponent* m_Trigger=nullptr;SCR_InventoryStorageManagerComponent* m_Inventory=nullptr;SCR_AIUtilityComponent* m_Utility=nullptr;SCR_AIBehaviorBase* m_Action=nullptr;ERR_EngineerMineRemoval* m_Removal=nullptr;Array<IEntity>* m_Attempted=nullptr;Array<IEntity> m_IntelFolders;vector m_Position,m_Rally;float m_Started=-1,m_LastTick=-1,m_PreparedAt=-1,m_NextClearance=0;int m_State=0,m_Checked=0;bool m_FriendlyNear=false,m_Begun=false,m_Stopped=false;
'''+cpp(methods)+r'''};
struct Fixture {Faction faction,hostile{true};SCR_AIGroup group;SCR_AIUtilityComponent utility;SCR_ChimeraAIAgent agent;SCR_InventoryStorageManagerComponent inventory;Entity actor,mine;Prefab prefab;Physics physics;InventoryItemComponent item;SCR_PressureTriggerComponent trigger;Sampler roster;ERR_HQTask task;ERR_HQReport report;ERR_ForceRecord record;Ledger ledger;ERR_GameMode mode;ERR_HQUnit unit;Array<IEntity> attempted;ERR_EngineerMine controller{&attempted};
Fixture(){ERR_GameMode::current=&mode;Replication::server=true;ERR_HunterCombat::engaged=false;currentGame=&game;game.world.query.clear();game.world.queries=0;
group.faction=&faction;actor.group=&group;actor.faction=&faction;actor.agent=&agent;actor.inventory=&inventory;agent.m_UtilityComponent=&utility;
mine.prefab=&prefab;mine.physics=&physics;mine.item=&item;mine.trigger=&trigger;mine.stored=true;mine.storageOwner=&actor;item.slot=&inventory;inventory.items.Insert(&mine);roster.members.Insert(&actor);
record.Group=&group;ledger.record=&record;mode.faction=&faction;mode.ledger=&ledger;unit.Group=&group;unit.Task=&task;unit.Assignment=&report;unit.StatusSampler=&roster;}
- void Begin(){assert(controller.Begin(&mode,&unit,&task,{30,0,0},1000));assert(attempted.Count()==1&&utility.additions==1);}
+ void Begin(){assert(controller.Begin(&mode,&unit,&task,{30,0,0},1000));assert(attempted.Count()==1&&utility.additions==1&&mode.mineIntel.candidates==1&&mode.mineIntel.capturedActor==&actor&&mode.mineIntel.seals==0);}
void Prepare(){Begin();actor.position={30,0,0};controller.Tick(2000);assert(controller.m_State==1&&utility.additions==2);controller.Tick(12000);assert(inventory.calls==1);assert(controller.m_State==2||controller.Finished());}
void Drop(){mine.position=actor.position;mine.stored=false;mine.storageOwner=nullptr;item.slot=nullptr;inventory.items.clear();}
void Withdraw(){Prepare();Drop();inventory.callback->OnComplete();controller.Tick(12001);assert(controller.m_State==3&&mine.moves==1&&utility.additions==3);}
};
int main(){
+ // Candidate list is captured once at accepted Begin; only successful native
+ // activation seals that same original list, even if carried folders change.
+ Fixture evidence;Entity originalFolder,lateFolder;evidence.mode.mineIntel.available.Insert(&originalFolder);evidence.Withdraw();
+ evidence.mode.mineIntel.available={&lateFolder};evidence.actor.position={0,0,0};evidence.controller.Tick(13000);
+ assert(evidence.mode.mineIntel.candidates==1&&evidence.mode.mineIntel.seals==1&&evidence.mode.mineIntel.sealed==Array<IEntity>{&originalFolder});
+ assert(evidence.mode.mineIntel.sealedMine==&evidence.mine&&evidence.mode.mineIntel.position.x==30);evidence.controller.Stop();evidence.controller.Tick(14000);assert(evidence.mode.mineIntel.seals==1);
+ Fixture noService;noService.mode.haveMineIntel=false;assert(noService.controller.Begin(&noService.mode,&noService.unit,&noService.task,{30,0,0},1000));assert(!noService.mode.mineIntel.candidates);
// Immutable total deadline, rollback/NaN clock refusal and continuous dwell.
assert(ERR_EngineerMineRules::Within(1000,1000,180999));assert(!ERR_EngineerMineRules::Within(1000,1000,181000));
assert(!ERR_EngineerMineRules::Within(1000,2000,1999));assert(!ERR_EngineerMineRules::Within(1000,2000,NAN));
@@ -111,7 +122,7 @@
dwell.actor.position={30,0,0};dwell.controller.Tick(12001);dwell.controller.Tick(22000);assert(!dwell.inventory.calls);dwell.controller.Tick(22001);assert(dwell.inventory.calls==1&&dwell.controller.m_Started==1000);
// Accepted unknown removal cannot retry, place or arm; original deadline wins.
Fixture unknown;unknown.Prepare();unknown.Drop();unknown.controller.Tick(12001);unknown.controller.Tick(180999);assert(unknown.inventory.calls==1&&!unknown.mine.moves&&!unknown.trigger.calls);
- auto held=unknown.inventory.callback;unknown.controller.Tick(181000);assert(unknown.controller.Finished());held->OnComplete();unknown.controller.Tick(181001);assert(!unknown.mine.moves&&!unknown.trigger.calls&&unknown.attempted.Count()==1);
+ auto held=unknown.inventory.callback;unknown.controller.Tick(181000);assert(unknown.controller.Finished());held->OnComplete();unknown.controller.Tick(181001);assert(!unknown.mine.moves&&!unknown.trigger.calls&&unknown.attempted.Count()==1&&unknown.mode.mineIntel.seals==0);
// Synchronous completion on a false native return is evidence, not a second call.
Fixture inlineOk;inlineOk.inventory.accepted=false;inlineOk.inventory.inlineResult=1;inlineOk.Prepare();inlineOk.Drop();inlineOk.controller.Tick(12001);assert(inlineOk.controller.m_State==3&&inlineOk.inventory.calls==1);
Fixture refused;refused.inventory.accepted=false;refused.Prepare();assert(refused.controller.Finished()&&refused.inventory.calls==1);refused.inventory.callback->OnComplete();refused.Drop();refused.controller.Tick(13000);assert(!refused.trigger.calls&&!refused.mine.moves);
@@ -126,7 +137,7 @@
// Native ownership still attached to the original actor may settle normally.
Fixture settling;settling.Prepare();settling.inventory.callback->OnComplete();settling.controller.Tick(12001);assert(!settling.controller.Finished()&&!settling.mine.moves);settling.Drop();settling.controller.Tick(12002);assert(settling.controller.m_State==3&&settling.mine.moves==1);
// Cancellation retains callback and item tombstone and only completes own action.
- Fixture stopped;stopped.Prepare();SCR_AIBehaviorBase unrelated;stopped.utility.actions.Insert(&unrelated);auto owned=stopped.controller.m_Action;stopped.controller.Stop();stopped.controller.Stop();stopped.Drop();stopped.inventory.callback->OnComplete();stopped.controller.Tick(13000);assert(owned->completed==1&&!unrelated.completed&&!stopped.mine.moves&&!stopped.trigger.calls&&stopped.attempted.Contains(&stopped.mine));
+ Fixture stopped;stopped.Prepare();SCR_AIBehaviorBase unrelated;stopped.utility.actions.Insert(&unrelated);auto owned=stopped.controller.m_Action;stopped.controller.Stop();stopped.controller.Stop();stopped.Drop();stopped.inventory.callback->OnComplete();stopped.controller.Tick(13000);assert(owned->completed==1&&!unrelated.completed&&!stopped.mine.moves&&!stopped.trigger.calls&&stopped.attempted.Contains(&stopped.mine)&&stopped.mode.mineIntel.seals==0);
// Original identity changes abort before irreversible work, including replacement
// task/report/ledger, recycled formation slot, capture and changed inventory.
for(int fault=0;fault<13;fault++){Fixture f;f.Begin();ERR_HQTask replacementTask;ERR_HQReport replacementReport;ERR_ForceRecord replacementRecord;SCR_InventoryStorageManagerComponent replacementInventory;SCR_AIUtilityComponent replacementUtility;
@@ -136,7 +147,7 @@
for(int fault=0;fault<3;fault++){Fixture f;f.Withdraw();if(fault==0)f.mine.parent=&f.actor;if(fault==1)f.mine.position={40,0,0};if(fault==2)f.trigger.active=true;f.actor.position={0,0,0};f.controller.Tick(13000);assert(f.controller.Finished()&&!f.trigger.calls);}
Fixture arm;arm.Withdraw();arm.actor.position={10.001f,0,0};arm.controller.Tick(13000);assert(!arm.trigger.calls);arm.actor.position={10,0,0};
Entity friendly;FactionAffiliationComponent affiliation;affiliation.faction=&arm.faction;friendly.affiliation=&affiliation;game.world.query.Insert(&friendly);arm.controller.Tick(14000);assert(!arm.trigger.calls);game.world.query.clear();arm.controller.Tick(14500);assert(!arm.trigger.calls);arm.controller.Tick(15000);assert(arm.trigger.calls==1&&arm.trigger.user==&arm.actor&&arm.controller.Finished());arm.controller.Tick(16000);assert(arm.trigger.calls==1);
- Fixture rejected;rejected.Withdraw();rejected.trigger.allow=false;rejected.actor.position={0,0,0};rejected.controller.Tick(13000);assert(rejected.trigger.calls==1&&!rejected.trigger.active&&rejected.controller.Finished());rejected.controller.Tick(14000);assert(rejected.trigger.calls==1);
+ Fixture rejected;rejected.Withdraw();rejected.trigger.allow=false;rejected.actor.position={0,0,0};rejected.controller.Tick(13000);assert(rejected.trigger.calls==1&&!rejected.trigger.active&&rejected.controller.Finished());rejected.controller.Tick(14000);assert(rejected.trigger.calls==1&&rejected.mode.mineIntel.seals==0);
Fixture moving;moving.Withdraw();moving.actor.position={0,0,0};moving.physics.velocity={1,0,0};moving.controller.Tick(13000);assert(!moving.trigger.calls);moving.physics.velocity={0,0,0};moving.controller.Tick(14000);assert(moving.trigger.calls==1);
Fixture bounded;bounded.Withdraw();bounded.actor.position={0,0,0};Entity prop;prop.character=false;for(int i=0;i<257;i++)game.world.query.Insert(&prop);bounded.controller.Tick(13000);assert(!bounded.trigger.calls&&bounded.controller.m_FriendlyNear);
// Exact original item stays quarantined across controllers; never adopted twice.
@@ -150,7 +161,7 @@
// Every irreversible stage repeats original task/actor custody checks.
for(int fault=0;fault<7;fault++){Fixture f;f.Withdraw();f.actor.position={0,0,0};ERR_HQTask newer;ERR_HQReport newerReport;ERR_GameMode newerMode;SCR_PressureTriggerComponent foreignTrigger;
switch(fault){case 0:f.unit.Task=&newer;break;case 1:f.unit.Assignment=&newerReport;break;case 2:f.actor.alive=false;break;case 3:f.actor.player=true;break;case 4:ERR_GameMode::current=&newerMode;break;case 5:f.mine.trigger=&foreignTrigger;break;case 6:f.task.ExpiresAt=13000;break;}
- f.controller.Tick(13000);assert(f.controller.Finished()&&!f.trigger.calls&&!foreignTrigger.calls);}
+ f.controller.Tick(13000);assert(f.controller.Finished()&&!f.trigger.calls&&!foreignTrigger.calls&&f.mode.mineIntel.seals==0);}
// Unknown or unconscious friendlies still block; hostile bodies and dead bodies
// do not fabricate a friendly. Static scenery isn't a soldier or vehicle.
Fixture friendPolicy;friendPolicy.Begin();Entity unknownPerson,unconscious,dead,enemy,scenery;DamageManagerComponent destroyed;destroyed.destroyed=true;dead.damage=&destroyed;FactionAffiliationComponent enemyAff;enemyAff.faction=&friendPolicy.hostile;enemy.affiliation=&enemyAff;scenery.character=false;
@@ -158,7 +169,7 @@
friendPolicy.controller.m_FriendlyNear=false;unconscious.alive=false;assert(!friendPolicy.controller.CheckFriendly(&unconscious)&&friendPolicy.controller.m_FriendlyNear);
friendPolicy.controller.m_FriendlyNear=false;assert(friendPolicy.controller.CheckFriendly(&dead)&&!friendPolicy.controller.m_FriendlyNear);assert(friendPolicy.controller.CheckFriendly(&enemy));assert(friendPolicy.controller.CheckFriendly(&scenery));
// Already-armed/default-live/unknown stock is not adopted or newly quarantined.
- for(int fault=0;fault<5;fault++){Fixture f;if(fault==0)f.trigger.active=true;if(fault==1)f.trigger.byDefault=true;if(fault==2)f.mine.alive=false;if(fault==3)f.prefab.name="unrelated";if(fault==4)f.mine.storageOwner=nullptr;assert(!f.controller.Begin(&f.mode,&f.unit,&f.task,{30,0,0},1000));assert(f.attempted.empty()&&!f.utility.additions&&!f.inventory.calls);}
+ for(int fault=0;fault<5;fault++){Fixture f;if(fault==0)f.trigger.active=true;if(fault==1)f.trigger.byDefault=true;if(fault==2)f.mine.alive=false;if(fault==3)f.prefab.name="unrelated";if(fault==4)f.mine.storageOwner=nullptr;assert(!f.controller.Begin(&f.mode,&f.unit,&f.task,{30,0,0},1000));assert(f.attempted.empty()&&!f.utility.additions&&!f.inventory.calls&&f.mode.mineIntel.candidates==0&&f.mode.mineIntel.seals==0);}
Fixture clock;clock.Begin();clock.controller.Tick(2000);clock.controller.Tick(1999);assert(clock.controller.Finished());
Fixture server;server.Begin();Replication::server=false;server.controller.Tick(2000);assert(server.controller.Finished()&&!server.inventory.calls);Replication::server=true;
--- /dev/null
+++ b/tests/test_mine_intel_discovery_integration.py
@@ -0,0 +1,86 @@
+"""Execute the complete production Recover body with controlled inventory and services.
+This verifies integration ordering and retained site-clue semantics, not native custody.
+"""
+import os,re
+from pathlib import Path
+from policy_harness import ROOT,body,run
+P=Path(os.environ.get('ERR_DISCOVERY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c'))
+s=body(P,'protected void Recover(')
+s=s.replace('protected ','').replace('null','nullptr').replace('foreach (','for (').replace('array<','Array<')
+for typ in ('InventoryStorageManagerComponent','ERR_DocumentComponent','ERR_LocationComponent'):
+ s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s)
+s=s.replace('Array<ERR_LocationComponent>','Array<ERR_LocationComponent*>').replace('bool mineRecovered;', 'bool mineRecovered=false;')
+for ns in ('Replication','ERR_Actors','SCR_FactionManager','InventoryStorageManagerComponent','ERR_DocumentComponent','ERR_LocationKind','Math'):
+ s=s.replace(ns+'.',ns+'::')
+for obj in ('m_Mode','player','folder','location','document','chosen'):
+ s=re.sub(r'\b'+obj+r'\.',obj+'->',s)
+for method in ('Players','Evidence','Settings','MineIntel','GetGame','GetPlayerManager'):
+ s=s.replace(method+'().',method+'()->')
+s=re.sub(r'FindComponent\((\w+)\)',r'FindComponent("\1")',s)
+run(r'''
+#include <cassert>
+#include <string>
+#include <vector>
+#include <algorithm>
+struct string:std::string{using std::string::string;using std::string::operator=;bool IsEmpty(){return empty();}};
+template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;using std::vector<T>::operator=;int Count(){return this->size();}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}void Insert(T t){this->push_back(t);}bool IsEmpty(){return this->empty();}T GetRandomElement(){return this->front();}};
+struct Entity;using IEntity=Entity*;
+struct Faction{};
+struct ERR_DocumentComponent{string target;string TargetId(){return target;}static ERR_DocumentComponent* Cast(void*p){return (ERR_DocumentComponent*)p;}};
+struct InventoryStorageManagerComponent{Array<IEntity> folders;static InventoryStorageManagerComponent* Cast(void*p){return (InventoryStorageManagerComponent*)p;}};
+struct Entity{bool alive=true,canonical=true;Faction*faction=nullptr;InventoryStorageManagerComponent*inventory=nullptr;ERR_DocumentComponent*document=nullptr;void*FindComponent(std::string type){if(type=="InventoryStorageManagerComponent")return inventory;if(type=="ERR_DocumentComponent")return document;return nullptr;}};
+namespace Replication{bool server=true;bool IsServer(){return server;}}
+namespace ERR_Actors{bool Alive(IEntity e){return e&&e->alive;}}
+namespace SCR_FactionManager{Faction*SGetFaction(IEntity e){return e?e->faction:nullptr;}}
+namespace ERR_LocationKind{enum{PRISON,RADIO,EXTRACTION,DEPOT};}
+namespace Math{int RandomInt(int,int){return 99;}}
+struct ERR_LocationComponent{string id;int kind=ERR_LocationKind::RADIO,knowledge=0,calls=0;bool allow=true;int Kind(){return kind;}int Knowledge(){return knowledge;}string Id(){return id;}bool Discover(int,int){calls++;if(!allow)return false;knowledge++;return true;}};
+struct Roster{IEntity CurrentActor(IEntity e){return e&&e->canonical?e:nullptr;}};
+struct Evidence{IEntity sealed=nullptr;string target;string Target(IEntity e){return e==sealed?target:"";}};
+struct Settings{int Runtime(string){return 15;}};
+struct MineIntel{bool newlyRecovered=false;int calls=0;Array<IEntity> recovered;Array<IEntity>*spent=nullptr;IEntity lastPlayer=nullptr;bool Recover(IEntity player,IEntity folder){assert(spent&&!spent->Contains(folder));calls++;lastPlayer=player;recovered.Insert(folder);return newlyRecovered;}};
+struct Mode{Roster roster;struct Evidence evidence;struct Settings settings;struct MineIntel mine;Faction*faction=nullptr;bool haveMine=true;Array<ERR_LocationComponent*>locations;int exhausted=0;
+ Roster*Players(){return &roster;}Faction*PlayerFaction(){return faction;}struct Evidence*Evidence(){return &evidence;}struct Settings*Settings(){return &settings;}struct MineIntel*MineIntel(){return haveMine?&mine:nullptr;}void Locations(Array<ERR_LocationComponent*>&out){out=locations;}void ERR_IntelExhausted(bool){exhausted++;}};
+struct PlayerManager{int GetPlayerIdFromControlledEntity(IEntity){return 1;}};struct Game{PlayerManager manager;PlayerManager*GetPlayerManager(){return &manager;}}game;Game*GetGame(){return &game;}
+template<class...T>void PrintFormat(T...){}
+struct Discovery{Mode*m_Mode=nullptr;Array<IEntity>m_Spent;void Folders(InventoryStorageManagerComponent*i,Array<IEntity>&out){out=i->folders;}bool MarkSpent(IEntity e){if(!m_Spent.Contains(e))m_Spent.Insert(e);return true;}
+'''+s+r'''
+};
+struct Fixture{Faction friendly,foreign;Mode mode;Discovery discovery;Entity player,second,folder;InventoryStorageManagerComponent firstInv,secondInv;ERR_DocumentComponent objective;ERR_LocationComponent radio,other;
+ Fixture(){Replication::server=true;mode.faction=&friendly;discovery.m_Mode=&mode;mode.mine.spent=&discovery.m_Spent;player.faction=&friendly;second.faction=&friendly;player.inventory=&firstInv;second.inventory=&secondInv;firstInv.folders.Insert(&folder);radio.id="radio";other.id="other";mode.locations={&other,&radio};}}
+;
+int main(){
+ // Authored target wins over incidental locations, and each exact document
+ // advances ordinary discovery once across transfer between two valid players.
+ Fixture f;f.objective.target="radio";f.folder.document=&f.objective;
+ f.discovery.Recover(&f.player);assert(f.radio.knowledge==1&&f.other.knowledge==0&&f.discovery.m_Spent.Contains(&f.folder));
+ assert(f.mode.mine.calls==1&&f.mode.mine.lastPlayer==&f.player&&f.mode.mine.recovered[0]==&f.folder);
+ f.firstInv.folders.clear();f.secondInv.folders.Insert(&f.folder);f.discovery.Recover(&f.second);assert(f.radio.calls==1&&f.other.calls==0&&f.mode.mine.calls==1);
+ // Existing sealed generic-folder target survives the supplemental hook.
+ Fixture sealed;sealed.mode.evidence.sealed=&sealed.folder;sealed.mode.evidence.target="radio";sealed.discovery.Recover(&sealed.player);assert(sealed.radio.knowledge==1&&sealed.other.knowledge==0);
+ // Unknown authored target stays unspent; a supplement cannot consume it first.
+ Fixture missing;missing.objective.target="absent";missing.folder.document=&missing.objective;missing.discovery.Recover(&missing.player);assert(missing.discovery.m_Spent.IsEmpty()&&missing.radio.calls==0&&missing.other.calls==0);
+ // Failed site discovery also retains the original retry semantics.
+ Fixture denied;denied.objective.target="radio";denied.folder.document=&denied.objective;denied.radio.allow=false;denied.discovery.Recover(&denied.player);assert(denied.discovery.m_Spent.IsEmpty()&&denied.radio.calls==1);
+ // Generic exhausted clue retains the existing spent/exhaustion behavior.
+ Fixture exhausted;exhausted.radio.knowledge=2;exhausted.other.knowledge=2;exhausted.discovery.Recover(&exhausted.player);assert(exhausted.discovery.m_Spent.Contains(&exhausted.folder)&&exhausted.mode.exhausted==1);
+ // A newly published mine warning is useful even after site clues are exhausted.
+ // Spend the original generic folder once without the contradictory exhaustion notice.
+ Fixture mineOnly;mineOnly.mode.mine.newlyRecovered=true;mineOnly.radio.knowledge=2;mineOnly.other.knowledge=2;
+ mineOnly.discovery.Recover(&mineOnly.player);assert(mineOnly.mode.mine.calls==1&&mineOnly.discovery.m_Spent.Contains(&mineOnly.folder)&&mineOnly.mode.exhausted==0);
+ mineOnly.discovery.Recover(&mineOnly.player);assert(mineOnly.mode.mine.calls==1&&mineOnly.mode.exhausted==0);
+ // New warning supplements, never replaces, an available site clue.
+ Fixture both;both.mode.mine.newlyRecovered=true;both.discovery.Recover(&both.player);assert(both.other.knowledge==1&&both.discovery.m_Spent.Contains(&both.folder)&&both.mode.exhausted==0);
+ // No mine service still produces the ordinary exhausted-folder notice.
+ Fixture noWarning;noWarning.mode.haveMine=false;noWarning.radio.knowledge=2;noWarning.other.knowledge=2;noWarning.discovery.Recover(&noWarning.player);assert(noWarning.discovery.m_Spent.Contains(&noWarning.folder)&&noWarning.mode.exhausted==1);
+ // Missing optional service cannot stop ordinary discovery.
+ Fixture absent;absent.mode.haveMine=false;absent.discovery.Recover(&absent.player);assert(absent.other.knowledge==1&&absent.discovery.m_Spent.Contains(&absent.folder));
+ // A distinct folder transferred before recovery is recovered by its real holder.
+ Fixture transferred;transferred.firstInv.folders.clear();transferred.secondInv.folders.Insert(&transferred.folder);transferred.discovery.Recover(&transferred.player);assert(transferred.mode.mine.calls==0);transferred.discovery.Recover(&transferred.second);assert(transferred.mode.mine.calls==1&&transferred.mode.mine.lastPlayer==&transferred.second);
+ // Full ledger and pre-spent documents never call the extra service.
+ Fixture full;full.discovery.m_Spent.resize(4096,nullptr);full.discovery.Recover(&full.player);assert(full.mode.mine.calls==0&&full.other.calls==0);
+ // Rejected actor never reaches either inventory or supplemental recovery.
+ for(int fault=0;fault<4;fault++){Fixture rejected;if(fault==0)rejected.player.canonical=false;if(fault==1)rejected.player.alive=false;if(fault==2)rejected.player.faction=&rejected.foreign;if(fault==3)Replication::server=false;rejected.discovery.Recover(&rejected.player);assert(rejected.mode.mine.calls==0&&rejected.discovery.m_Spent.IsEmpty()&&rejected.radio.calls==0);}
+}
+''')
+print('PASS: actual full document recovery retains authored/sealed targets, one shared spent ledger, retry/exhaustion semantics and canonical multi-player ownership alongside supplemental mine intel')
@@ -0,0 +1,19 @@
check: /tmp/err-policy-reqodto3/check.cpp:89: int main(): Assertion `mineOnly.mode.mine.calls==1&&mineOnly.discovery.m_Spent.Contains(&mineOnly.folder)&&mineOnly.mode.exhausted==0' failed.
Traceback (most recent call last):
File "/tmp/erri-mine-intel-integration/tests/test_mine_intel_discovery_integration.py", line 20, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<62 lines>...
}
^
''')
^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-reqodto3/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,6 @@
{
"addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "822a526af8814264ee45da21b675466abfece86aa573744ee78692bdd1f1bc66",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "e0098577626e719283cf4b40936e7ec038076c4bab9269fbad0b5ad3292e01e3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
"tests/test_mine_intel.py": "109d5c8532c3725ec3b42f7b0d769dfdf4eda5912a5d2409556c30f203cc6672"
}
@@ -0,0 +1,55 @@
{
"README.md": "c2c106797809f3c103e340f834d327aa2fb3295776cc5a2aec7f3f1511a97dd8",
"addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
"addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "d39dc876487b445efc5c3fadc19e1e06c6900c5cd57c93a01f35c32aa27d6039",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "251d55779509cb76f66938221b4dc8face53e187a82c9f2c651e6b1d13216c27",
"addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
"addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "7422f79bfa5ecf9b13c37b7ad0cf0b23469ed7059e85462ff96b7704084d29d9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "e353ece5e1f3a6731875d8080c00fa9511446c309ff2a1454911e53c01f536f9",
"addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "e73b3654ea115568ab24456d43dfe0c6419d3ccfeaf53e5b7752d31f2950b58d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "7d5ff3389ee806ac213db5be3a68288b3399142ccc29806df0d65b34a0b2fc3c",
"addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
"addons/core/UI/layouts/ERR/AdminMenu.layout": "997e4f33660de5bb54c2939898cacc8857736a73db2c6919888ae0e762050e5c",
"docs/environment.md": "2a58f8a969348e42e09e45b906a3d61fb65d887ae2814547605a01987747ab6c",
"docs/field-sites.md": "9c3928a04b4b242dcf806d7b20ecf2f4cc636aff9a31ed90d9fd75cfaf776aa0",
"docs/prison-opening.md": "be60fee1542185bfae38cba9bacf1f181acf2a032af33d5eb853468a036cc54a",
"docs/recovery.md": "026b513982530b8d65a6a1459e8707cd4abaf56450abc00f8449cf01fc660d0d",
"docs/spectator-guidance.md": "700840fb639152c61785238ebc383fade6cf34f5d888496204569c60ad6d091d",
"docs/vanilla-resources.json": "d80edf67d429b578051cad1630d3c44fae70714d14a277e40294242f9b439783",
"tests/test_admin_menu.py": "e7adf7c3ad76274e29135b56223facdd0f9e01911d7a690787949d695073bfba",
"tests/test_command_maintenance.py": "be2c942aa11a5f874448e94f06925f2f1de2210a14881fb7e486842119cb673c",
"tests/test_escape_result_wording.py": "7b3613cccd4f24d3ef4665dfc1854cfc958a69018a59f9b8090617f0185a82a8",
"tests/test_field_sites.py": "fddb0e44e72fdfe32bb94347a14da64efbd2208e4f252754e80c620fbecda56c",
"tests/test_headless_game_runner.py": "0d84160076ec9961e7315ccd50d6ce45ff971328c298649505fbba6305c22f31",
"tests/test_journal_readability.py": "47764126522e7d7a90100cd9beff741bf49e4d8390111f977919d3e323a5c7df",
"tests/test_native_end_lifecycle.py": "8b187723c9039e68e3e590c812c91dcffe1e5917d4e450ed798dc177888fda7a",
"tests/test_player_medical.py": "e4b3140a3afc0161db53f261e5480e51f1ca09f85657e25b0efb7dbba3336e3f",
"tests/test_settings_migration.py": "5fdfc8815f49f900a1aeda73ec3954cfd767019e702c48c77411dbb7dc016c2f",
"tests/test_spectator_recovery.py": "8bb59c51df003e24532ad9476af4c8ff3b7f4276dca25e8162b91eb77c7b67c2",
"tools/check.py": "ac4e38114e1796829afa58ef8ac00e1fa6433b129e29955a6d69162fd78bf0a0",
"tools/headless_game.py": "e7cab472ee51497343174cb460022b3e4591f148d4acbc6e6f881fc68c0fda1b",
"tools/headless_workbench.py": "37651b5601add5689143767ab1592f6753f2145177b1d8055babca1789eb6265",
"tools/import_settings.py": "c44490a568893b0076c73423cae09a174ce9c808d83b959987e06af072d38567"
}
@@ -0,0 +1,8 @@
{
"newtests": [
"test_mine_intel.py",
"test_mine_intel_discovery_integration.py"
],
"addition": "'test_mine_intel.py', 'test_mine_intel_discovery_integration.py', ",
"regression_programs": 262
}
@@ -0,0 +1,563 @@
PASS: missing, child-only, malformed, zero and duplicate prefab root IDs rejected
PASS: delayed scene/inventory arrival, deferred preload, identity checks, stale replies, timeout and observer cleanup
PASS: actual inventory manifest, delayed/missing/wrong-owner item links, finite cap, consumed-stock refresh and preload ordering
PASS: spawn scene remains held through final acknowledgement and nearby use; leaving, reassignment, disconnect and teardown release it
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
PASS: actual mine evidence sealing/recovery, historical coarse publication, caps, canonical ownership, marker join retry/owner-change/stop; native arming and replicated vector-array transport untested
PASS: actual full document recovery retains authored/sealed targets, one shared spent ledger, retry/exhaustion semantics and canonical multi-player ownership alongside supplemental mine intel
PASS: actual infantry search suspension, quiet grace, finite resume, expiry/replacement and defensive/ownership boundaries
PASS: infantry combat gate precedes radio delivery and preserves non-task transports
PASS: actual HQ contact transition wakes only fit squad members, cancels only task orders and logs changes once
PASS: actual finite medicine grants, authored stock deduction, full-backpack refusal/pouch fallback, no loot replenishment, unresolved-operation quarantine and ownership/stop guards
PASS: only recent native detected/identified threats suspend hunter travel; stale/disarmed/destroyed contacts cannot strand patrols
PASS: actual hunter combat transition cancels only its travel once, holds through renewed contact and resumes after quiet; unregistered startup preserved
PASS: captured sighting retention, immutable details, expiry, replay rejection, bounded sound uncertainty/cooldown, radio loss, priority and overdue-status fairness
PASS: arrow press/release, held keys, opposing keys, disabled/menu input and firearm-only retention
PASS: town trigger and hard 700m exclusion for all observers, empty/invalid positions and final-check crossings
PASS: exact finite site squads, invalid roster/count rejection, committed-site spacing and safe fallback boundary
PASS: mortar couriers use the mobile site team and refuse permanent-only garrisons
PASS: omitted preferred mortar depot selects a surviving owned camp/mobile team; no camp, foreign cache and permanent-only sites are unavailable; historical priority retained
PASS: real-session mortar deadline, failed-support convoy admission and hunter survivor/recovery gates
PASS: native-route retry preserves delivered target, limits attempts and suspends during combat
PASS: stale/deleted AI utility cannot receive Complete; mortar HQ preflight withholds unsafe orders; mounted convoy cover never creates infantry Defend
PASS: flight crew affiliation and group precede native boarding; preparation remains bounded even while passengers wait
PASS: factionless/deleted map targets do not abort perception; faction lookup tolerates teardown; deleting helicopter releases without capture/engine access
PASS: shoot adapter waits for a physical round; bounded same-shell retries, interrupted/never-started loads, committed no-retry, order/owner changes and normal native delegation
PASS: missing/invalid faction crew defers before any native spawn or allowance insertion; all registered RHS factions have explicit soldier and medic profiles
PASS: vehicle radio issued once; pending, refusal and looting cannot duplicate or fabricate a physical radio link
PASS: actual vehicle-radio link requires the original seated crew, physical manpack and live uncaptured mission vehicle; looting, dismount, release and teardown remove it
PASS: actual hunter release preserves survivors/HQ, releases driving ownership once, delegates capture/teardown, and excludes prison/patrol/mortar from generic objective defence
PASS: real opening road geometry enforces wide azimuths; fresh delivered contact preempts patrol cooldown, respects radio failures and does not starve in-flight interception
PASS: actual scoped 10% tighter REGULAR aim error and alert perception; preserves equipment multiplier and restores vanilla behavior when unbound
PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay
PASS: bounded same-group empty-spawn retries, no casualty refill, queue retirement, delivery-gated intel, prepared-team reuse, throttled diagnostics and LOD release
PASS: production airborne memory confidence, persistence, ground coverage, confirmed losses, artillery veto, cooldown and invalid-input rules
PASS: production cover retains the carried HQ target until its deadline; airport reload waits until the drop pass and cover have finished
PASS: air logistics reservation preserves delivered search until radio handoff, excludes guards/combat/in-flight orders, and quarantines unresolved native loads/moves
PASS: actual ammunition cargo selector handles empty rifle/machinegun/sniper magazines, preserves loaded variants, excludes auxiliary launchers and tolerates missing native metadata
PASS: original 15-minute launch/loss cadence, active/captured timer disarm, saved delay reset, stop, 300m orbit and bounded close-contact standoff at 30/60/120 Hz
PASS: actual aircraft-removal notification guards owner/server/active/stop and schedules one full delay without replay extension
PASS: hill prominence/elevation, actual road edges/heights/bends and server-only finite scout admission, pending stock, timeout and no replacements/refills
PASS: mortar duty scope excludes players, other crews, stopped/client/inactive states; only destruction releases an active assignment, while the gunner may approach the gun
PASS: random mode restrictions, full numeric ranges, independent calendar dates and strict daylight boundaries
PASS: actual killais eligibility includes the 1000m boundary, excludes players/retained bodies/dead/non-character entities and checks full 3D distance
PASS: actual generation scheduler bounds each tick, enforces deadline/candidate ceiling, validates fallback, commits only accepted positions, skips only dispensable sites, preserves required objectives/intel, and resets the next search budget
PASS: terrain placement samples world bounds, retains streaming candidates, bounds waits/work, rejects foreign fallbacks, preserves objectives/intel and validates completion
PASS: actual navigation readiness supports static meshes, yields only for loadable streaming tiles and refuses unreachable positions
PASS: universal connector, embedded/standalone exports, multiple terrains, stable IDs, native nav configs, missing-nav visibility, path validation and overwrite protection
PASS: airfield detection accepts physical runways/towers and bounded authored markers, rejects unrelated props, water and out-of-world markers, and samples terrain height
PASS: actual faction resolution reserves explicit roles, samples without replacement, substitutes disabled selections, and rejects duplicate/unknown/missing choices and insufficient pools
PASS: Random all submits persistent random roles immediately; manual mixed choices, stale/unauthorized UI guards and debounce preserved
PASS: actual content policy gates parent packs, individual factions, faction identity and finite group rotation with vanilla fallback
PASS: actual delivered road eligibility, ahead projection without chords, reservations, stock road query bounds, terrain/water/obstruction refusal and clean outputs
PASS: actual delivered-task lineage, expiry, old-order retention, native commit, release, road precision expiry and duplicate delivery
PASS: actual original-roster local handoff,100m3D bound,busy carrier/budget exclusion,origin interruption including deletedsource,normal radio delivery and per-source replay history
PASS: actual visual intake retains source/time/position/id, rejects replay, prefers usable own route, excludes simultaneous callers and conservatively resets negative-sweep dwell
PASS: actual fixture local/radio gating, immutable source/time/position, interrupted-report exclusion and exact-owner cleanup
PASS: local-handoff runner refuses wrong project/round count/insufficient deadline before runtime work
PASS: actual fixture allocator terminal/unsubmitted guard, original-group lookup and both candidate gates
PASS: actual report-derived waypoint insertion/order and tighter positive radii; no formation navigation claim
PASS: actual Place/Stop waits native pose update, bounds four attempts, preserves original position, restores pending/settled placement and respects ownership/accepted-move quarantine
PASS: actual fixture current/original recipient ownership, unresolved transfer cleanup, exact-token release and idempotent Stop
PASS: actual fixture phased-cargo readiness, bounded callbacks, captured-stock mixed-caliber selection/continuation, reservation cleanup and component magazine counts
PASS: actual inventory-fixture setup uses ordinary prison unlock before constructing its convoy-waiting probe; failed unlock cannot run fixture
PASS: actual authored storage anchors, native trace flags, own-hierarchy exclusion, external wall/vehicle obstruction, range, unknown geometry and bounded context refusal
PASS: actual convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup
PASS: actual finite convoy supply pool; immutable slots, shared demand state, sparse/capped discovery and permanent shutdown
PASS: actual HQ rotates finite donors, skips unavailable/contacted trucks, uses delivered reports and dispatches at most one trip per planning cadence
PASS: actual original turret identity, native/canonical guards, scoped maximum-skill profile, reset, dismount/reboard, requested-skill preservation and restoration
PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines
PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths
PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged
PASS: actual read migrates old valid settings, preserves explicit disabled state, rejects invalid data; next-round feedback and fixed menu remain honest
PASS: actual automatic convoy timing/authority/admission/one-attempt/manual-task/stop policy; native deployment unproved
PASS: late authoritative failure reason refreshes open result; detach, mode change and success subscriptions preserved
infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed
PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership
PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries
PASS: actual shared finite identity reservation; competing consumers, submission permanence, stale cleanup and96-item bound
PASS: actual carried-mounted swap, shared committed claim, physical slot reach, exact two-way proof, uncertainty and terminal cleanup
PASS: actual mounted pickup, exact finite ownership, pre-submission commit, physical custody, bounded callback and quarantine lifecycle; no native coverage claim
PASS: actual mounted courier admission, radio, individual orders, two-stage transfer, reboarding, token cleanup and quarantine lifecycle
PASS: actual scoped crew permit and native board completion/failure preserves foreign seats without teleport fallback
PASS: actual shared mounted stock/history ownership, atomic exact HQ pair claim, and bounded stopped-owner proof polling
PASS: actual carried/mounted early ammunition policy and status-first shared uplink; complete threshold, phases, cooldown, failures and requested check-ins
PASS: actual group radio startup preservation, finite native grants, callback quarantine, frozen selection/actor ownership and bounded observation
PASS: actual maintenance native-stock check rejects missing/duplicate/wrong-identity/unowned/depleted/malformed stock and is read-only; native runtime not executed
..................
----------------------------------------------------------------------
Ran 18 tests in 0.294s
OK
PASS: actual radio node rejects current incapacitation, death, ownership and faction changes despite cached inventory; one-second capability refresh remains explicit
PASS: Southern finite maintenance stock preserves weapons/clues and optional transport, historical Western fixture stays separate; native capacity/consumption untested
PASS: optional transport deferred behind required readiness, bounded once-only spawn/omission, isolated cleanup, occupied-candidate retention and required-default preservation
PASS: actual diagnostic fallback runs only on failed missing-context call, derives unique native pilot door, preserves stock eligibility and restores prior index on success/failure; diagnostics mutate no game state.
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.
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.
PASS: actual preparation Configure guards/idempotence/breach preservation, security eligibility/final current-body server mutation and all scoped action guards; all five seat/four door resource overrides. Native hold, prefab merge, replication and boarding remain unverified.
PASS: production vehicle alarm single trigger/replica completion/no replay, fixed deadline/readiness wait, failed audio, dedicated server, moving exact handle, destruction/native end/deletion/clock and mission teardown. Native sound and multiplayer delivery require engine qualification.
PASS: production alarm emitter/receiver original time/location, explicit native queue only, 32-entry cap, 50m local witness eligibility, bound perception, native-super preservation; actual engine broadcast/hearing remains unverified.
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
PASS: actual once-only native dry query, exact before/after slots, native refusal, shutdown; shared bounded discovery and distinct opt-in verdict
PASS: actual completion selector and pre-cleanup variant capture preserve separate radio and eligibility verdicts
PASS: actual cargo diagnostic stages separate absent/foreign magazines, used/empty/invalid rounds, well mismatch and exact truck storage/attachment without mutation
PASS: actual native courier witness rejects missing radio/custody/swap/reboard evidence; CLI opt-in bounded; native success remains unqualified
PASS: actual courier constructor/Tick waits for preparation, returns before physical checks, preserves fixed deadline and sticky stop/failure; Enfusion startup awaits native verification
PASS: actual arranged native alarm fixture deadline, single emit, natural-route observation, original timestamp/area/detail assertions, natural observer proximity/activation wait, failure cleanup and independent canonical-body restoration; native delivery itself remains unqualified.
PASS: actual convoy cover observation/snapshot/uplink/HOLD/RESUME/cleanup transitions; native boundaries mocked, non-convoy runner opt-in refused
Enemy optics actual-service ownership, preservation, callback, deadline and bounded-inspection policies passed
PASS: actual delivered cover freshness/lineage/replay and canonical executor; owned waypoint-only hold, one resume at preserved route index, invalid ownership/crew/ledger refusal and fail-closed native recreation
PASS: actual Stinger show/set/help state precise actor-roll effects; read-only help, bounded values, malformed syntax and failed-save preservation; no rerolls/gameplay edits and no native persistence claim
PASS: new/retasked search and radio delivery ammo gates; active tasks and delivered release preserved
HQ convoy delivered-report planning and downlink regressions passed
PASS: actual own-inventory ammo inspection deduplicates loaded/carried/shared wells, separates chambers/launchers, freezes scalar snapshots and treats unsupported/capped/foreign inventory as unknown
PASS: actual mounted hierarchy sampling, ownership exclusion, deduplication, completeness/caps, quarter threshold and detached validation; no runtime policy or ammunition mutation
PASS: actual HQ original convoy-root admission rejects wrong force/server/group and never supplies replacement lookup
PASS: production mounted structural seat scan ignores >128 carried/cargo descendants, shares exact native mount/magazine ownership, preserves attachment seats and exact occupants, rejects unknown/cyclic/oversize structures; native binding still requires qualification.
PASS: native body fixture uses existing immutable actors, real production LOS/queued uplink, pre-delivery isolation, actual status overlap, bounded cleanup and no fabricated reports/spawns
PASS: actual native fixture lookup selects exact BODY kind/identity/message from bounded evaluations, never sighting-only Get
PASS: actual ammo snapshot comparison checks every scalar/category flag; native probe requires real roster rescan, loaded-round lower bound and separate immutable pending/Watch objects
PASS: actual delivered slot-union bodies preserve overlap/disjoint evidence, replay idempotence, status subset integrity, full-wipe closure and formation-local bounds
test_review_added_allowed_media_invalidates_snapshot (__main__.ReviewTests.test_review_added_allowed_media_invalidates_snapshot) ... ok
test_review_added_source_directory_rejected (__main__.ReviewTests.test_review_added_source_directory_rejected) ... ok
test_review_loose_root_resource_and_symlink_rejected (__main__.ReviewTests.test_review_loose_root_resource_and_symlink_rejected) ... ok
test_review_metadata_media_and_sidecars_remain_allowed_and_bound (__main__.ReviewTests.test_review_metadata_media_and_sidecars_remain_allowed_and_bound) ... ok
test_review_missing_link_rejected (__main__.ReviewTests.test_review_missing_link_rejected) ... ok
test_review_package_guard_sees_new_scripts (__main__.ReviewTests.test_review_package_guard_sees_new_scripts) ... ok
test_review_retargeted_private_link_rejected (__main__.ReviewTests.test_review_retargeted_private_link_rejected) ... ok
----------------------------------------------------------------------
Ran 7 tests in 0.076s
OK
PASS: actual report methods reproduce old starvation; status-first scheduler delivers check-ins and requires 30s without combat or actual visible contacts before negative reports
PASS: actual actor group lookup retains controlled character membership when seated/inherited vehicle agents differ; missing control or parent refuses
.................
----------------------------------------------------------------------
Ran 17 tests in 3.701s
OK
PASS: actual convoy motion thresholds, native-only proof boundaries, physical cargo/crew ownership and pre-launch runner restrictions
PASS: actual filled rotated-footprint TraceBox and nine terrain/water samples; broad tree/cable bounds alone accepted, actual collision/nonfinite trace refused, nonzero sweep and ENTS/OCEAN flags, bounded diagnostic query and reset
PASS: actual road interpolation/projection/orientation, six35m starts,200m forward tail, preserved bends, short/far/degenerate/nonfinite/overdense/hairpin refusal and deterministic candidate ties
PASS: actual authenticated convoy dispatch, active/ready admission gates, canonical receipt, safe unconsumed preflight retry, pool refusal, retained partial failure and consumed no-retry
PASS: actual native readiness exact membership, one-time per-vehicle ledger admission/reservation, partial readiness retry without duplicate records and one-pass56-item cargo allocation without replenishment
PASS: actual per-vehicle readiness reasons, native agent/activity counts, intended-seat diagnostics, five-second throttle and read-only observation
PASS: actual convoy dispatch validates before receipt consumption, consumes once before native mutation, retains all12 partial-failure paths, accepts the selected non-USSR enemy, and allocates exact19 bodies without capacity shrinking
PASS: own memberless prefab disables automatic spawn before initialization; actual admission rejects populated, immediate or authored-slot templates before finite crew creation
PASS: actual native seated-group arrival outside35m, native waypoint removal, idempotent advance, and convoy waypoint idempotence/arrival/deadline, missing/dead/captured/reparented crew refusal, failed native waypoint release, original vehicle/member preservation and no replacement
PASS: actual convoy receipt identity/one-use, shared60-body and128-formation caps, outstanding/native-ledger accounting, exact19-body composition, source reuse, mode/client guards and no consumed receipt refunds
PASS: actual supply route cycling/arrival/stops, finite startup bounds, contact freshness, dismount hold, quiet interval, interrupted boarding, timeout and lost-truck release
PASS: moving-convoy perception boundaries and scoped individual/group abandonment priorities
PASS: actual supply startup reasons expose unchanged body budget/requirement, journal only failure changes, preserve retry cadence/caps and report the true final refusal
PASS: actual StartOne plus actual pool preserve unconsumed receipt retry, reject consumed replay, skip impossible new-budget surveys, retain equality, retry caps and journal dedup; no FPS claim
PASS: actual admission seeds use exact installed loaded prefab, reject replacement/foreign/projectile paths and preserve bounded immutable identity
PASS: actual primary-before-mounted one-shot batch, shared96/128 caps, physical snapshot headroom, original ownership, callback refusal and admission pinning
PASS: actual bounded HQ query validates only existing original binding without admission or replacement lookup
PASS: production convoy spacing, physical arrival, stable follower targets, supply ownership, leader promotion and bounded stuck recovery
PASS: convoy combat keeps native manoeuvres for unchanged contacts and refreshes when contact moves
PASS: native convoy proof excludes pre-departure movement and ends via explicit fixture reset, not prohibited player death
PASS: boarding retries only after approach/seat progress stops, capped at three, with delayed native reissue and completed-team preservation
PASS: slow only owned vehicles near fit dismounted infantry; ignore passengers, casualties and released teams/vehicles
PASS: restore missing native driving registration only for healthy owned seated crews; preserve existing association and refuse invalid/released vehicles
PASS: actual body observer enforces owned physical roster, local death-only candidates, native trace gating, budget/cadence/caps, immutable body-only snapshots, radio retries and confirmed suppression
PASS: own initial roster, explicit retained corpse evidence, unconscious/missing/ref transfer guards, fixed strength, no replacement adoption, detached samples, surviving radio sender, immutable convoy root/ledger, mounted capture release and lost-root unknown
PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence, detached/validated mounted payload replacement and 256-record cap
PASS: actual failed-retask deadline rollback plus assignment cancellation/release preserves radio ownership, native waypoint lifecycle and failed-order retry boundaries
PASS: actual force ledger, finite casualties/identity/cap, routes/arrival/elevation/overshoot, server and physical guards, staggered 256-record simulated hour without world queries
PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 256-group bound
PASS: actual percentage selection, native/preferred launcher preservation, failure/removal fallback, pending-operation quarantine, capture, finite two-mine grants and no replenishment
PASS: actual engineer mine preparation/deadline, original custody/identity, once-only callback removal, cancellation quarantine, withdrawal/clearance, native refusal and owned-action cleanup; native execution untested
PASS: actual road mine-site annulus/bend geometry, deterministic bounded candidates, server/query limits, and native ground/water/obstruction rejection; no runtime placement claim
PASS: actual HQ mine admission, one site query per tick, maximum two active/32 retained jobs, delivered-only original post, once-per-unit refusal latch, 256-item ceiling and maintenance/teardown ownership
PASS: actual objective heading/threat/approach rules, persistent doctrine weight, fresh-contact coverage invalidation, stale-sweep rejection and atomic radio retask ownership
PASS: actual bounded delivered-negative coverage, replay/freshness/expiry/invalid guards, oldest eviction, small-circle and nearest-unswept selection, reserved-cell exclusion and cleanup
PASS: actual HQ active/pending reservations, interruption, committed replacement, bounded coverage and unchanged force counts
PASS: actual bounded pursuit roles/objectives/scores, stale search degradation, physical/busy/home guards, finite lifetime and two-bearing escape gap; no hidden player reads or spawning
PASS: actual HQ memory rules/service preserve delivered snapshots, chronology, replay bounds, decay, motion limits, identity and negative-search revisions
.......
----------------------------------------------------------------------
Ran 7 tests in 0.030s
OK
PASS: actual session Tick + journal router delivers each grant completion and new HQ line once, without repeats on empty/unavailable feeds or unauthorized ticks
.....
----------------------------------------------------------------------
Ran 5 tests in 0.434s
OK
PASS: actual current-controller/admin/mode authorization, per-round anti-replay, token-rotation refusal, command/snapshot throttles and client scope; owner-only replies and player-tool cleanup wiring
PASS: mission provider registration is idempotent, optional dispatch is ordered, status aggregates, journals preserve cursors, aliases stay with their addons and topic help is bounded
PASS: actual menu command routing covers all fourteen settings, rejects unsupported keys, gates companions, and matches unique authored widgets
PASS: explicit weapon retention buttons use the same ready/authorized server command path
PASS: actual summaries preserve queued/delivered meaning, clear counts and IDs; raw records, legacy display, cursor gaps and RPC limits remain intact
PASS: actual admin body authorization, god restoration, vanilla item deposit, callback completion/failure, timeout quarantine and stop/revocation paths
PASS: same-body revoke/regrant preserves pending insertions and timeout quarantine; new-body binding isolates late callbacks and never inherits god mode
PASS: actual Intel commands distinguish status/start/failure, preserve authorization gate and reject malformed requests; spent ledger is idempotent, server-only and bounded
PASS: actual reroll snapshot, authority, cancellation, ownership, accepted operations, quarantine, bounded work and stop methods; no native runtime claim
PASS: production Intel feedback coalescing, rough secrecy, rate limit, bounded dedupe, local/remote delivery and round cleanup; native UI/RPC not exercised
PASS: actual per-squad bounded report selector rotates visible targets, survives ordering/turnover, records only queued attempts, and preserves radio intake ordering
PASS: actual action denial/clearing, server request failure, single submitted-result feedback, current rescuer identity and terminal/stop suppression; native UI/RPC pending
PASS: actual physical denial precedence and transport-seat occupancy/reservation/access/lock checks
PASS: actual initial admission exhaustion and ServerTick grace; new/pending/empty/controller/life guards, normal death preserved
......................
----------------------------------------------------------------------
Ran 22 tests in 0.293s
OK
......................
----------------------------------------------------------------------
Ran 22 tests in 29.054s
OK
..................
----------------------------------------------------------------------
Ran 18 tests in 3.285s
OK
.........
----------------------------------------------------------------------
Ran 9 tests in 2.610s
OK
...............
----------------------------------------------------------------------
Ran 15 tests in 1.231s
OK
PASS: actual field result/braking observer and Chat dispatch rules; one finite fixed candidate, deferred callback failure and guarded cleanup; no native measurement
PASS: actual opt-in terrain audit records one fixed1681-point grid, preserves original survey refusal/success and exact no-allocation scope; malformed heights stop without retry; no native data acquired
....
----------------------------------------------------------------------
Ran 4 tests in 0.679s
OK
PASS: actual field PI/ramp/vector caps, antiwindup, braking hypothesis, immutable admission limits and segment bounds; no native physics tested
PASS: actual100m whole-field survey sampling/4096cap, rotated coverage, all-node terrain and native trace refusal; original certificate lineage retained; no native qualification
PASS: actual QualifyField preserves original identity/footprint/time, orders complete surveys before issuance, and refuses failed stages/moved body/expired or changed world; native boundaries faked
PASS: WORKBENCH first-refusal diagnostics preserve ordinary predicates, query order/count/budget and opt-in scope; no native logging run
PASS: actual field startup delegation, immutable lease/target, braking/settling/cancel transitions, early abort, callback scope, physical terminal policy and shared landing demand; native boundaries faked
PASS: actual inherited airborne pre-CLIMB cancellation enables verified native autohover once, refuses failed enable and never writes after capture
PASS: actual Core maintenance/default/tick/stop methods; empty/populated authority, terminal reentry, no tactical resume or new scheduler; native boundaries substituted
PASS: actual finite registration, unique claims/tokens, retention/cancel/stop, readiness gating, capture/expiry retirement and bounded cross-kind order history and typed field/route construction; native boundaries faked
PASS: actual WORKBENCH route observer returns exact retained route subtype and refuses absent/field controllers
.....
----------------------------------------------------------------------
Ran 5 tests in 0.707s
OK
......................
----------------------------------------------------------------------
Ran 22 tests in 0.193s
OK
................
----------------------------------------------------------------------
Ran 16 tests in 11.338s
OK
......
----------------------------------------------------------------------
Ran 6 tests in 0.019s
OK
PASS: actual production bridge lookup, lease/world/mode/seat/capture guards, no allocation, native super ordering and read-only fixture hooks
...............
----------------------------------------------------------------------
Ran 15 tests in 0.062s
OK
.............
----------------------------------------------------------------------
Ran 13 tests in 5.490s
OK
PASS: actual route gain/caps/braking, callback selection, old landing/cancellation control and matching read-only telemetry
..............................
----------------------------------------------------------------------
Ran 30 tests in 0.458s
OK
..............
----------------------------------------------------------------------
Ran 14 tests in 0.227s
OK
.........
----------------------------------------------------------------------
Ran 9 tests in 0.118s
OK
PASS: actual gate observer binds native registered action/context and current life, reads accumulated progress, refuses stale bindings and never revives outside original bounds
PASS: actual read-only look observer methods enforce explicit scope, pinned native camera/body/identity, normalized pose, terminal cancellation and original sample/time bounds
...........
----------------------------------------------------------------------
Ran 11 tests in 0.078s
OK
.......................
----------------------------------------------------------------------
Ran 23 tests in 0.039s
OK
PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending
........
----------------------------------------------------------------------
Ran 8 tests in 0.013s
OK
PASS: actual inventory adapter scope, grid placement, sole compatible host, refresh reuse, rollback, foreign hierarchy refusal and exactly-once native delegation; native compatibility pending
.................................................................................
----------------------------------------------------------------------
Ran 81 tests in 0.588s
OK
......
----------------------------------------------------------------------
Ran 6 tests in 0.083s
OK
.................
----------------------------------------------------------------------
Ran 17 tests in 0.005s
OK
...........
----------------------------------------------------------------------
Ran 11 tests in 0.091s
OK
.........
----------------------------------------------------------------------
Ran 9 tests in 0.357s
OK
PASS: actual observer nonce, admission pins, baseline/menu sequencing, snapshots, bounded clocks/samples, cleanup and one-attempt latch; native untested
PASS: actual corridor caps/height/hold and whole-rectangle survey bounds, terrain refusal, native trace refusal and exact certificate lineage; native route unqualified
PASS: actual route entry, fixed corridor/target, hover hold, cancellation landing freeze, shared lease/capture/deadline gate and unchanged native startup/tick sequence
PASS: finite opt-in route fixture, original native input order, meaningful physical-arrival evidence and guarded cleanup; no native launch
PASS: actual Chat route step result dispatch and scoped completion/cleanup wiring; six real early-parser refusal paths leave no prefix/profile output
PASS: actual retained-service fixture entry, immutable controller/token/deadline/count bindings, observer getter and cleanup ownership ordering; native route validation pending
PASS: actual measured cancellation gate, one-shot retained service Stop, no premature drain, immutable lease, fresh real controller readback and separate physical cancellation result policy
PASS: actual rough-intel objective selection, exact precedence, source grid dimensions and unchanged other-phase dispatch; native UI pending
.................................
----------------------------------------------------------------------
Ran 33 tests in 0.165s
OK
...............
----------------------------------------------------------------------
Ran 15 tests in 0.039s
OK
PASS: actual preparation status scope, persistent updates, spinner restoration, placeholder replacement/deletion/destruction, native observation persistence/timeout; rendering remains native-pending
PASS: actual guide/observer monitors retry native refusal, cache successful delivery, deduplicate and preserve living/preparing/spectator boundaries; native UI not exercised
PASS: actual native-end shutdown, existing terminal snapshots, reentrancy, unchanged native end data and stale preparation guards
....
----------------------------------------------------------------------
Ran 4 tests in 1.605s
OK
PASS: actual three-state result wording and UI refresh; stale winner IDs never manufacture escape
...........
----------------------------------------------------------------------
Ran 11 tests in 0.132s
OK
PASS: actual immutable target, bounded autohover demand, drift refusal, five-second hold and unchanged qualification/deadline
PASS: actual admission attempt budget bounds blocked/missing prerequisites; preparation, spent life and async pending remain protected
PASS: delayed admission retry retains controller ownership across same-account recycled connection IDs
PASS: actual scene deadline overrides delayed native preload only for rejection; late completion cannot assign, ordinary verified admission preserved
PASS: actual action permission matrix unchanged; useful phase/intel/consciousness denials, stale reason cleared, native door denial preserved; no native UI claim
.....
----------------------------------------------------------------------
Ran 5 tests in 0.284s
OK
PASS: actual aircraft cancellation/stage rules, ground-only completion, expiry/capture faults, input ownership and no physical shortcuts
PASS: actual exact-instance single-use qualification, native-clock staleness/movement refusal, footprint bounds and ownership-safe ground/fault cleanup
PASS: actual optional screenshot helper flag/identity/world/life revalidation, one queued attempt, delayed capture and mission/world cleanup; no native image/presentation claim
PASS: actual yard diagnostic exact registered prison ownership, eight native-bound corner projections, no root-sibling escape, bounded duplicate/deep/wide hierarchy traversal; native projection/mask still unmeasured
PASS: actual CurrentActor, SpawnPosition and observer-selection methods reject pending/unregistered/replaced/recycled/foreign/dead bodies; canonical selection/cycling, unconscious following and prison/geometry fallback preserved; native boundaries adapted
PASS: actual native-map fixture ownership, cleanup and callback evidence fail closed; native execution remains separate
PASS: actual shared-map callbacks bind exact map/config/root, preserve replacement UI/camera, defer focus, and remove only owned delayed work
PASS: actual Intel/HQ methods and one-shot qualified readiness handoff deliver late actors once; duplicate readiness, accepted spawn, pickup/drop, death and original negative rolls do not mint assignments
PASS: Workbench-only read accessor rejects unknown/nonserver identities; Chat observes all distinct ready crew before existing shell-depletion mutation
PASS: actual native-event latch survives deselection, requires exact activity/order, detaches before cleanup, preserves failure/timeout and never infers completion from physical shot count
.........
----------------------------------------------------------------------
Ran 9 tests in 0.121s
OK
PASS: actual refresh-fixture gates pin immutable observations/actual downlinks/original activity, reject unaccepted or relabelled commits, stop queueing early and require all queued contacts claimed before replay
..........................
----------------------------------------------------------------------
Ran 26 tests in 0.232s
OK
PASS: actual refresh scheduler/delivery/cancellation/projectile methods reject interrupted or replayed reports, retain committed ownership, preserve immutable snapshots/aim geometry and isolate stopped or replaced orders; native radio/crew behavior remains separate
.....................
----------------------------------------------------------------------
Ran 21 tests in 0.037s
OK
...........
----------------------------------------------------------------------
Ran 11 tests in 0.039s
OK
PASS: actual full-salvo gates require eight fresh committed physical launches, natural closure and exact finite inventory; reject partial/extra/replayed events
PASS: actual reason/availability guidance and refresh matrix; no-target copy omits cycling, hint retry retained, existing command/admin paths unchanged; native UI pending
PASS: actual client camera policy closes immediately on healing or mission end; late unconscious metadata cannot keep the view active
PASS: actual input dispatch, one press per edge, menu-held suppression; actual revival camera handoff with editor close/retry, missing camera, replacement body and stopped round
PASS: first-person pose survives missing samples without drift, follows body motion/rotation, resumes fresh pose and cannot leak between targets
................usage: test_native_package.py [-h] [--project {core}] --session SESSION
--compat COMPAT [--steam STEAM]
[--timeout TIMEOUT]
[--external-addons EXTERNAL_ADDONS]
[--silent-workbench | --exit-after-init]
[--continue-on-failure]
test_native_package.py: error: argument --exit-after-init: not allowed with argument --silent-workbench
................................
----------------------------------------------------------------------
Ran 48 tests in 12.316s
OK
.......
----------------------------------------------------------------------
Ran 7 tests in 0.254s
OK
..............
----------------------------------------------------------------------
Ran 14 tests in 2.200s
OK
....
----------------------------------------------------------------------
Ran 4 tests in 0.329s
OK
....
----------------------------------------------------------------------
Ran 4 tests in 0.057s
OK
PASS: actual finite-courier age, token, exact ownership/callback and delivered-status admission reject stale, replayed, captured, canceled and ambiguous work
PASS: actual native-gun ownership gate rejects player/foreign/replaced/dead occupant, faction change, missing seat and missing registry
PASS: four-battery courier selection preserves pending trip/report/transfer identity, skips unavailable crews, and selects the next depleted battery without new stock
PASS: 64 bounded distinct storage candidates; native gates, five-store barrier and finite-stock ownership retained; native placement pending
PASS: 128 coarse+80 local refinement+169 airport grid candidates retain all native clearance gates; real terrain untested
PASS: actual prison registration/crossing policies reject missing/duplicate/destroyed initial gate, incomplete ownership/scan, outside-only body, jumps and stale samples; physical exit independent of later gate damage
PASS: actual prison door execution blocks direct AI/UI bypass while locked and delegates unchanged native action once after unlock and permission approval
..................
----------------------------------------------------------------------
Ran 18 tests in 1.774s
OK
.....
----------------------------------------------------------------------
Ran 5 tests in 1.102s
OK
PASS: native local-admission snapshot rejects changed life/key/body/participant/pending state; authentication is not simulated
PASS: actual mortar report ledger prevents duplicate response after cancellation, expiry and interleaved reports; native scheduler separate
.........
----------------------------------------------------------------------
Ran 9 tests in 0.016s
OK
....
----------------------------------------------------------------------
Ran 4 tests in 0.133s
OK
PASS: actual aim renewal requires fresh same-report solve and original-command equivalence; native firing untested
........
----------------------------------------------------------------------
Ran 8 tests in 0.012s
OK
PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation
PASS: rapid mortar cycle counts eight physical rounds once and waits for native completion without a ninth aim or shell
PASS: actual probe binds native events to fresh immutable commits, permits delayed emission, rejects unrelated expiry closure and premature stop
PASS: actual noSplash Load body requires both explicit diagnostic and noSplash, preserves vanilla otherwise, and handles repeated Load/reload
PASS: actual fixture method permits one native resilience operation and restores either prior protection state, including failure paths
PASS: actual safe-exit boundary policy, native action/door selection, stop/cache cleanup, separate old mechanism and opt-in runner contracts
PASS: actual one-shot deadline/stability policies and preparation ownership, fuel, cleanup integration contracts
PASS: pending-only cancellation retires copied instance intent, preserves physical/control actors, and stops once
PASS: actual short-cast hit, upward support normal, no self support and no dynamic support
PASS: actual committed-ticket structure preserves reservation after death, rejects missing bodies/seats and ends at observation expiry
PASS: actual pending callback expires an empty-server reservation once, preserves its full lease, and cancels on completion/Stop
PASS: rescue lease expiry/reordering, fresh five-second settling, independent rescue ranges and grounded upright aircraft motion boundaries
PASS: requested guard population requires complete physical conscious membership before deadline
......................................
----------------------------------------------------------------------
Ran 38 tests in 0.017s
OK
..........
----------------------------------------------------------------------
Ran 10 tests in 0.002s
OK
.....
----------------------------------------------------------------------
Ran 5 tests in 0.915s
OK
PASS: authored radio/optional-site bounds and physical horizontal/vertical boundaries
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
PASS: all phase transitions, terminal states, defence boundaries, stale/future observations, intel discovery
PASS: Core document-discovery alias, companion-only alias exclusion, strict integer parsing and setting boundaries
PASS: player admission phase/life/identity/controller matrix, preload displacement limits, pending reservation overlap and owner exclusion
PASS: actual gate and pre-inventory document guards reject noncanonical/faction/life/disconnect/server mismatches; canonical reconnect and unconscious carried intel preserved
PASS: WB-only native fault injection restores both body mutations before checks/returns and requires eligible held-document negative/positive proof; runtime pending
PASS: actual discovery coordinates disclose stable 500m cell center until identified, then exact point, including negative/boundary coordinates
PASS: actual local admission context/selection/latch, same-round late identity, replacement/mode failure, fresh round and untouched network path
PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance
PASS: physical body occupancy rejects overlap, permits diagonal neighboring slots, and excludes own body and unrelated broad-phase bounds
PASS: recovery state excludes dead bodies, preserves reservations, requires controlled rescuers and distinguishes empty/all-dead teams
PASS: authority-scoped slow recovery, bleeding pauses resilience, medicine unaffected, player-only lethal damage cap without healing
PASS: bleeding severity survives low health, retains armour, causes no knockout and restores the actual damage/blood-loss cap
PASS: viable passive recovery survives native delay; bleeding, disabled/full effects and low-blood resilience do not block defeat
PASS: every minute round-trips, malformed clocks rejected, defaults limited to added keys, progression bounds and day duration aligned
PASS: native settings policy matches calendar boundaries 1900-2050, date/profile parsing is strict, authored defaults preserve old worlds
PASS: view-distance bounds, default, save failures, command parsing, temporary ownership, server/platform limits and lifecycle wiring
.....
----------------------------------------------------------------------
Ran 5 tests in 0.645s
OK
.
----------------------------------------------------------------------
Ran 1 test in 0.369s
OK
PASS: radio authorization/discovery/phase matrix, exact distance limits, defender handover, interruption, empty samples, clock regression and duration boundary
PASS: actual radio feedback policy, initial wait, interruption persistence, resumption and terminal/new-round reset
...............
----------------------------------------------------------------------
Ran 15 tests in 2.028s
OK
..............................................
----------------------------------------------------------------------
Ran 46 tests in 0.972s
OK
PASS: legacy values preserved, unsupported fields reported, invalid data rejected, existing files protected, runtime bounds aligned
PASS: failed initial settings promotion leaves defaults writable after restart; prior/fallback saves survive copy, readback and mismatch faults
PASS: real-carrier shortest-hop paths, 500m boundary, three-hop cap, no-manpack failure, three-second originating-call interruption, unchanged downlink hop timing, completed-hop survival, interrupted final uplink, radio loss, capture, motion, timeout, reset and network bounds
PASS: migrated aircraft availability policy (controller migration still pending)
PASS: migrated salvo offsets are deterministic, spread and bounded (native firing and complete salvo qualification are separate)
PASS: 34 prefabs have unique saved root entity IDs
PASS: 299 original script entries tracked across 18 unfinished responsibilities
PASS: 1 isolated addons, acyclic dependencies, 55 unique resources, exact vanilla/authorized external references
All repository checks passed. Native compilation and multiplayer tests are separate requirements.
@@ -0,0 +1,37 @@
{
"feature": "Historical mine warnings from exact original recovered engineer documents",
"scope": "Existing carried generic folders only; sealed at confirmed native arming, no spawned intel, no objective-folder replacement, no live coordinates or unknown-mine disclosure.",
"source_sha256": {
"addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "822a526af8814264ee45da21b675466abfece86aa573744ee78692bdd1f1bc66",
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "e0098577626e719283cf4b40936e7ec038076c4bab9269fbad0b5ad3292e01e3",
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
"tests/test_mine_intel.py": "109d5c8532c3725ec3b42f7b0d769dfdf4eda5912a5d2409556c30f203cc6672",
"tests/test_mine_intel_discovery_integration.py": "bac2c8ec269d6e51a46fc17893de4114a5613f37899a1e044a9132d97d44cc5a",
"tests/test_engineer_mine.py": "3ffd360652ba66d4bb96247496e9b34175cc35c4e5d665f6524cb1cbd563bb73",
"tools/check.py": "25dcb5662d952bf549c1a554a4c3c5263c06478068aa491f1d5a73b104a88185"
},
"regression_programs": 262,
"native_route_assertions": 63,
"native_script_failures": 0,
"native_resource_errors": 13,
"native_cleanup_and_inputs_verified": true,
"review_fixes": [
"New mine-only warning suppresses contradictory exhausted-intel text while preserving normal spending/site clues.",
"Shrinking replicated marker list rebinds its manager before replacement insertion, so later cleanup removes native markers."
],
"bounds": {
"records": 32,
"folder_bindings": 128,
"candidate_folders_per_engineer": 16,
"coarse_cell_metres": 500
},
"independent_base_loop_reviews": "Player lifecycle and objective/document audits found no demonstrated additional defect; focused regressions passed, without multiplayer qualification.",
"prior_unstaged_files_preserved": 53,
"original_reference_files_preserved": 533,
"previous_handoff_unchanged": true,
"limitations": [
"Normal route compiles/integrates the feature but does not execute mine placement, arming, document sealing/recovery or mine-warning rendering.",
"Actual-method tests use native boundary doubles; remote/JIP transport and map presentation remain untested.",
"Physical mine lifecycle, mounted rearming, human escape, twelve-player multiplayer, comparative FPS and clean packaging remain unfinished."
]
}