Add mission customization, HQ support and aggression-driven AI

Integrate faction and random settings menus, generated objectives, scouts, convoys, air support, mortar stations and body-intel recovery. Add identified-body aggression, finite hunter UAZ deployment, dedicated objective defence and maximum AI skill with separate reduced aim accuracy. Include policy tests, native probes, evidence and documentation.
This commit is contained in:
2026-09-23 15:07:14 +02:00
parent 04bd19327b
commit 1b1a8b5173
242 changed files with 12153 additions and 875 deletions
+9 -1
View File
@@ -15,7 +15,7 @@ def adapt(s):
s=s.replace('FindComponent(DamageManagerComponent)', 'FindDamage()').replace('FindComponent(SCR_InventoryStorageManagerComponent)', 'FindInventory()')
s=s.replace('DamageManagerComponent.Cast(', 'Damage::Cast(').replace('SCR_InventoryStorageManagerComponent.Cast(', 'Inventory::Cast(')
s=s.replace('purpose: EStoragePurpose.PURPOSE_DEPOSIT, cb: m_Grants->Operation', '1, m_Grants->Operation')
s=s.replace('String item;', 'String item;')
s=s.replace('String item;', 'String item;').replace('string.Format(', 'String::Format(').replace('ERR_DebugAI.', 'DebugAI::').replace('ERR_DebugIntel.', 'DebugIntel::')
return s
binding=adapt(body(source,'void Bind('))
constructor=adapt(body(source,'void ERR_AdminPlayerTools(')).replace('void ERR_AdminPlayerTools(ERR_AdminGrantState grants = nullptr)', 'Tools(GrantState* grants = nullptr)')
@@ -30,6 +30,7 @@ run(r'''
#include <vector>
struct String:std::string {
using std::string::string;String()=default;String(const std::string& s):std::string(s){}
static String Format(String text,int n){text.replace(text.find("%1"),2,std::to_string(n));return text;}
String Trim(){auto a=find_first_not_of(" \t\n");return a==npos?String():String(substr(a,find_last_not_of(" \t\n")-a+1));}
void ToLower(){std::transform(begin(),end(),begin(),[](unsigned char c){return std::tolower(c);});}
bool StartsWith(const char* p){return rfind(p,0)==0;}bool IsEmpty(){return empty();}
@@ -51,6 +52,8 @@ struct Game{float now=0;Manager manager;Manager* GetPlayerManager(){return &mana
namespace Replication{bool server=true;bool IsServer(){return server;}}
namespace Global{bool admin=true;bool IsAdmin(int){return admin;}}
namespace Actors{bool Alive(Entity* a){return a&&a->alive;}}
namespace DebugAI {int calls=0;int KillNearby(Mode* m,Entity* e){assert(m&&e);calls++;return 3;}}
namespace DebugIntel {int calls=0;bool success=true;bool SpawnSix(Mode* m,Entity* e){assert(m&&e);calls++;return success;}}
struct GrantState{IEntity Actor=nullptr;ERR_AdminItemCallback* Operation=nullptr;String Item;float Deadline=0;bool TimedOut=false;
'''+binding+r'''
};
@@ -65,6 +68,11 @@ struct Fixture{
bool command(String args){replies.clear();return tools.Execute(&mode,&controller,args,replies);}void tick(){replies.clear();tools.Tick(replies);}
};
int main(){
{Fixture f;int before=DebugIntel::calls;f.command("cheat intel");assert(DebugIntel::calls==before+1&&f.replies[0].find("Spawned 6")!=String::npos&&f.actor.inventory.submissions==0);Global::admin=false;f.command("cheat intel");assert(DebugIntel::calls==before+1);}
{Fixture f;DebugIntel::success=false;f.command("cheat intel");assert(f.replies[0].find("Could not place")!=String::npos);DebugIntel::success=true;}
{Fixture f;int before=DebugAI::calls;f.command("killais");assert(DebugAI::calls==before+1&&f.replies[0].find("Killed 3")!=String::npos);Global::admin=false;f.command("killais");assert(DebugAI::calls==before+1);}
{Fixture f;assert(!f.command("mission time show")&&f.replies.empty());assert(f.command(" GOD SET ON ")&&!f.actor.damage.enabled);assert(f.tools.m_God);f.command("god");assert(f.actor.damage.changes==1);f.command("god show");assert(f.replies[0].find("on")!=String::npos);f.command("ungod");assert(f.actor.damage.enabled&&f.actor.damage.changes==2);f.tools.Stop();assert(f.actor.damage.changes==2);}
{Fixture f;f.actor.damage.enabled=false;f.command("god");f.command("god set off");assert(!f.actor.damage.enabled);}
{Fixture f;f.command("god");Global::admin=false;f.tick();assert(f.actor.damage.enabled&&f.tools.m_Stopped&&f.replies.empty());Global::admin=true;f.command("god");assert(f.actor.damage.enabled);}