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
+73
View File
@@ -86,3 +86,76 @@ int main(){
}
''')
print('PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay')
# Exercise sealing as well as corpse inspection: a large camp population should
# cover unfinished sites, while already-issued and authored clues stay fixed.
selection='\n'.join(body(p,sig) for sig in ('protected string NextTarget(', 'void Capture('))
selection=selection.replace('protected ', '').replace('foreach (', 'for (').replace('array<', 'Array<')
selection=selection.replace('Array<ERR_LocationComponent>', 'Array<ERR_LocationComponent*>')
selection=selection.replace('InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent))', 'actor->inventory')
selection=selection.replace('ERR_DocumentComponent.Cast(folder.FindComponent(ERR_DocumentComponent))', 'folder->document')
for t in ('ERR_BodyEvidence','ERR_IssuedIntel','InventoryStorageManagerComponent','ERR_LocationComponent','ERR_DocumentComponent'):
selection=re.sub(r'\b'+t+r' (\w+)', t+r'* \1', selection)
for n in ('location','record','issued','item','document'):
selection=selection.replace(n+'.',n+'->')
for n in ('ERR_GameMode','ERR_Actors','ERR_DiscoveryService','ERR_LocationKind'):
selection=selection.replace(n+'.',n+'::')
selection=selection.replace('ERR_GameMode::Get().','ERR_GameMode::Get()->').replace('GetRandomElement().Id()', 'GetRandomElement()->Id()')
selection=selection.replace('bool known;', 'bool known=false;')
run(r'''
#include <cassert>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
struct string:std::string{using std::string::string;using std::string::operator=;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}};
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;void Clear(){this->clear();}int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}T GetRandomElement(){return this->front();}};
template<class K,class V>struct Map:std::map<K,V>{bool Find(K k,V& v){auto i=this->find(k);if(i==this->end())return false;v=i->second;return true;}void Set(K k,V v){(*this)[k]=v;}};
namespace ERR_LocationKind{enum{PRISON,EXTRACTION,RADIO,OUTPOST};}
struct ERR_LocationComponent{string id;int knowledge=0,kind=ERR_LocationKind::OUTPOST;string Id(){return id;}int Knowledge(){return knowledge;}int Kind(){return kind;}};
struct ERR_GameMode{Array<ERR_LocationComponent*> locations;static ERR_GameMode*Get(){static ERR_GameMode m;return &m;}void Locations(Array<ERR_LocationComponent*>&out){out=locations;}};
struct ERR_DocumentComponent{string target;string TargetId(){return target;}};
struct Entity;using IEntity=Entity*;
struct InventoryStorageManagerComponent{Array<IEntity>folders;};
struct Entity{bool alive=true,player=false;InventoryStorageManagerComponent*inventory=nullptr;ERR_DocumentComponent*document=nullptr;};
namespace ERR_Actors{bool Alive(IEntity e){return e&&e->alive;}bool Player(IEntity e){return e&&e->player;}}
struct ERR_IssuedIntel{IEntity Folder=nullptr;string SiteId;};
struct ERR_BodyEvidence{IEntity Actor=nullptr;bool Searched=false;Array<ERR_IssuedIntel*>Issued;};
namespace ERR_DiscoveryService{void Folders(InventoryStorageManagerComponent*inv,Array<IEntity>&out){out=inv->folders;}}
struct Evidence{Map<string,int>m_TargetAssignments;ERR_BodyEvidence*record=nullptr;ERR_BodyEvidence*Find(IEntity actor){return record&&record->Actor==actor?record:nullptr;}
'''+selection+r'''
};
int main(){
auto mode=ERR_GameMode::Get();Evidence service;ERR_LocationComponent sites[60];
for(int i=0;i<60;i++){sites[i].id="camp-"+std::to_string(i);mode->locations.Insert(&sites[i]);}
// Known sites and automatic prison/extraction disclosures are never new targets.
sites[0].knowledge=2;sites[1].kind=ERR_LocationKind::PRISON;sites[2].kind=ERR_LocationKind::EXTRACTION;
sites[3].knowledge=1;mode->locations.Insert(nullptr);
for(int i=0;i<570;i++)assert(!service.NextTarget().IsEmpty());
assert(service.m_TargetAssignments.size()==57);
for(int i=3;i<60;i++)assert(service.m_TargetAssignments[sites[i].id]==10);
// New generated camps catch up instead of leaving all intel on the early sites.
ERR_LocationComponent added;added.id="late-camp";mode->locations.Insert(&added);
for(int i=0;i<10;i++)assert(service.NextTarget()=="late-camp");
sites[3].knowledge=2;
for(int i=0;i<56;i++)assert(service.NextTarget()!=sites[3].id);
assert(service.m_TargetAssignments[sites[3].id]==10);
// The exact folder is sealed once. Repeated scans/discovery changes cannot retarget it.
Entity actor,folder;InventoryStorageManagerComponent inv;actor.inventory=&inv;inv.folders={&folder};
ERR_BodyEvidence record;record.Actor=&actor;service.record=&record;service.Capture(&actor);
assert(record.Issued.Count()==1);string target=record.Issued[0]->SiteId;
for(auto site:mode->locations)if(site)site->knowledge=2;
service.Capture(&actor);assert(record.Issued.Count()==1&&record.Issued[0]->SiteId==target);
assert(service.NextTarget().IsEmpty());
// Explicit mission clues survive even when no random unfinished target remains.
Entity objective;ERR_DocumentComponent doc;doc.target="radio";objective.document=&doc;
inv.folders.Insert(&objective);service.Capture(&actor);
assert(record.Issued.Count()==2&&record.Issued[1]->SiteId=="radio");
Entity extra;inv.folders.Insert(&extra);service.Capture(&actor);assert(record.Issued.Count()==2);
// Later availability can seal an unassigned folder, but not a spent/reported body's contents.
added.knowledge=0;record.Searched=true;service.Capture(&actor);assert(record.Issued.Count()==2);
record.Searched=false;actor.alive=false;service.Capture(&actor);assert(record.Issued.Count()==2);
actor.alive=true;service.Capture(&actor);assert(record.Issued.Count()==3&&record.Issued[2]->SiteId=="late-camp");
}
''')
print('PASS: 570 folders cover 57 unfinished sites evenly; known/automatic targets excluded, late camps included, and exact issued/authored documents preserved')