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
+9 -5
View File
@@ -19,7 +19,7 @@ run(r'''
#include <string>
#include <algorithm>
struct AIWaypoint{};
struct ERR_HQTask {bool ReleaseOnly=false,RoadIntercept=false;std::string SecuritySite;float ExpiresAt=100000;};
struct ERR_HQTask {int OperationId=0;bool Maneuver=false,ReleaseOnly=false,RoadIntercept=false;std::string SecuritySite;float ExpiresAt=100000;};
struct Group {std::vector<AIWaypoint*> queue;int adds=0,removes=0;
void RemoveWaypoint(AIWaypoint* w){removes++;queue.erase(std::remove(queue.begin(),queue.end(),w),queue.end());}
void AddWaypointAt(AIWaypoint* w,int slot){assert(slot==0);adds++;queue.insert(queue.begin(),w);}};
@@ -39,6 +39,8 @@ int main(){
assert(f.combat.Update(&f.unit,true,false,19000)==2&&!f.combat.Held&&!f.combat.Paused());
assert(f.group.adds==1&&f.group.queue.size()==2&&f.group.queue[0]==&f.search);
assert(f.combat.Update(&f.unit,true,false,20000)==0&&f.group.adds==1);}
// Explicit HQ flank movement survives contact; expiration returns to normal combat.
{Fixture f;f.task.Maneuver=true;assert(f.combat.Update(&f.unit,true,true,2000)==0&&!f.combat.Held&&f.group.removes==0);f.task.ExpiresAt=3000;assert(f.combat.Update(&f.unit,true,true,3000)==1&&f.combat.Paused());}
// Never resurrect expired, released, replaced, or newly defensive tasks.
for(int invalid=0;invalid<6;invalid++){Fixture f;ERR_HQTask replacement;AIWaypoint other;
f.combat.Update(&f.unit,true,true,0);
@@ -69,11 +71,12 @@ hq=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c'
tick=body(hq,'override void Tick(')
assert tick.index('UpdateInfantryCombat(unit, now)') < tick.index('unit.Downlink.Advance')
assert 'unit.InfantryCombat.Held || ERR_HunterCombat.Active(unit.Group)' in body(hq,'protected bool Fighting(')
assert 'if (unit.PendingTask) LostOrder(unit, now)' in body(hq,'protected void UpdateInfantryCombat(')
assert 'if (unit.PendingTask && !unit.PendingTask.Maneuver) LostOrder(unit, now)' in body(hq,'protected void UpdateInfantryCombat(')
print('PASS: infantry combat gate precedes radio delivery and preserves non-task transports')
update=body(hq,'protected void UpdateInfantryCombat(').replace('protected ', '')
update=update.replace('ERR_HQUnit unit','ERR_HQUnit* unit').replace('unit.', 'unit->')
update=update.replace('PendingTask.', 'PendingTask->')
update=update.replace('InfantryCombat.', 'InfantryCombat->').replace('Group.', 'Group->')
update=update.replace('array<AIAgent> reacting', 'std::vector<AIAgent*> reacting')
update=update.replace('foreach (AIAgent actor : reacting)', 'for (AIAgent* actor : reacting)').replace('actor.', 'actor->')
@@ -90,18 +93,19 @@ struct ERR_Actors{static bool CanFight(AIAgent* a){return a->fit;}};
struct ERR_HunterCombat{static bool Active(Group*){return true;}};
struct ERR_HQUnit;
struct State{int change=1;bool paused=true;int Update(ERR_HQUnit*,bool eligible,bool,float){return eligible?change:0;}bool Paused(){return paused;}};
struct ERR_HQUnit{int Id=7;string ForceSourceId="town";struct Group* Group;State* InfantryCombat;void* PendingTask=nullptr;bool eligible=true;bool Eligible(int){return eligible;}};
struct Task{bool Maneuver=false;};
struct ERR_HQUnit{int Id=7;string ForceSourceId="town";struct Group* Group;State* InfantryCombat;Task* PendingTask=nullptr;bool eligible=true;bool Eligible(int){return eligible;}};
struct Journal{int logs=0;void Write(string,string){logs++;}};
struct HQ{int m_Mode=1,cancelled=0;Journal m_Journal;void LostOrder(ERR_HQUnit* u,float){cancelled++;u->PendingTask=nullptr;}
'''+update+r'''
};
int main(){HQ h;Group g;State state;ERR_HQUnit u;u.Group=&g;u.InfantryCombat=&state;
AIAgent fit,casualty;casualty.fit=false;g.members={&fit,&casualty,nullptr};u.PendingTask=&fit;
AIAgent fit,casualty;casualty.fit=false;g.members={&fit,&casualty,nullptr};Task pending;u.PendingTask=&pending;
h.UpdateInfantryCombat(&u,1000);assert(g.activations==1&&fit.activations==1&&casualty.activations==0&&h.cancelled==1&&h.m_Journal.logs==1);
state.change=0;h.UpdateInfantryCombat(&u,2000);assert(g.activations==1&&h.cancelled==1);
state.change=1;u.PendingTask=nullptr;h.UpdateInfantryCombat(&u,3000);assert(h.cancelled==1&&fit.activations==2);
u.eligible=false;h.UpdateInfantryCombat(&u,4000);assert(g.activations==2&&h.m_Journal.logs==2);
u.eligible=true;state.change=2;h.UpdateInfantryCombat(&u,5000);assert(g.activations==2&&h.m_Journal.logs==3);
u.eligible=true;pending.Maneuver=true;u.PendingTask=&pending;h.UpdateInfantryCombat(&u,4500);assert(u.PendingTask==&pending&&h.cancelled==1);state.change=2;h.UpdateInfantryCombat(&u,5000);assert(g.activations==3&&h.m_Journal.logs==4);
}
''')
print('PASS: actual HQ contact transition wakes only fit squad members, cancels only task orders and logs changes once')