Integrate startup optics and supply vehicle lock picking

This commit is contained in:
2026-09-20 05:34:30 +02:00
parent 9205e2129a
commit 963cab50c0
104 changed files with 16171 additions and 25 deletions
+26 -10
View File
@@ -13,9 +13,9 @@ code=code.replace('static const ResourceName','static constexpr const char*').re
code=code.replace('string result','std::string result').replace('array<IEntity>','std::vector<IEntity*>')
code=code.replace('BaseWeaponManagerComponent.Cast(Actor.FindComponent(BaseWeaponManagerComponent))','Actor->weapons')
code=code.replace('InventoryStorageManagerComponent.Cast(Actor.FindComponent(InventoryStorageManagerComponent))','Actor->inventory')
for cls in ('ERR_GameMode','SCR_AIGroup','SCR_AIGroupUtilityComponent','IEntity','SCR_AICombatComponent','ERR_EnemyEquipmentCallback','BaseWeaponManagerComponent','InventoryStorageManagerComponent'):
for cls in ('ERR_GameMode','SCR_AIGroup','SCR_AIGroupUtilityComponent','IEntity','SCR_AICombatComponent','ERR_EnemyEquipmentCallback','ERR_EnemyOptics','BaseWeaponManagerComponent','InventoryStorageManagerComponent'):
code=re.sub(r'\b'+cls+r' ([a-zA-Z_]\w*)',cls+r'* \1',code)
for obj in ('mode','group','utility','Actor','Group','Combat','Operation','item','weapons','inventory'):
for obj in ('mode','group','utility','Actor','Group','Combat','Optics','Operation','item','weapons','inventory'):
code=code.replace(obj+'.',obj+'->')
for cls in ('Replication','SCR_Global','ERR_GameMode','ERR_Actors','ERR_EnemyEquipmentRules','EAISkill','ERR_HQ','Math','EStoragePurpose'):
code=code.replace(cls+'.',cls+'::')
@@ -67,13 +67,14 @@ struct NativeCombat {
IEntity* GetOwner(){return owner;}EAISkill GetAISkill(){return skill;}
virtual void SetAISkill(EAISkill value){skill=value;}virtual void ResetAISkill(){skill=EAISkill::ROOKIE;}
};
struct ERR_EnemyOptics{int stops=0;void Stop(){stops++;}};
''' + code + r'''
std::vector<std::unique_ptr<ERR_EnemyEquipmentCallback>> operations;
ERR_EnemyEquipmentCallback* NewOperation(){operations.emplace_back(new ERR_EnemyEquipmentCallback());return operations.back().get();}
struct Soldier {
SCR_AIGroup group;BaseWeaponManagerComponent weapons;InventoryStorageManagerComponent inventory;IEntity actor;SCR_AICombatComponent combat;
SCR_AIGroup group;BaseWeaponManagerComponent weapons;InventoryStorageManagerComponent inventory;IEntity actor;SCR_AICombatComponent combat;ERR_EnemyOptics optics;
Soldier(){actor.group=&group;actor.weapons=&weapons;actor.inventory=&inventory;combat.owner=&actor;}
ERR_EnemyEquipmentEntry Entry(){ERR_EnemyEquipmentEntry e;e.Actor=&actor;e.Group=&group;e.Combat=&combat;return e;}
ERR_EnemyEquipmentEntry Entry(){ERR_EnemyEquipmentEntry e;e.Actor=&actor;e.Group=&group;e.Combat=&combat;e.Optics=&optics;return e;}
};
int main(){
ERR_GameMode mode;ERR_GameMode::current=&mode;
@@ -123,7 +124,7 @@ int main(){
skill.combat.SetAISkill(EAISkill::ROOKIE);assert(skill.combat.GetAISkill()==EAISkill::ROOKIE);
Soldier moved;SCR_AIGroup replacement;moved.combat.ERR_BindEnemySkill(&mode,&moved.group);moved.actor.group=&replacement;
moved.combat.SetAISkill(EAISkill::ROOKIE);assert(moved.combat.GetAISkill()==EAISkill::ROOKIE);
Soldier stopped;auto terminal=stopped.Entry();terminal.Check(&mode);terminal.Stop(&mode);stopped.inventory.callback->OnComplete();
Soldier stopped;auto terminal=stopped.Entry();terminal.Check(&mode);terminal.Stop(&mode);assert(stopped.optics.stops==1);stopped.inventory.callback->OnComplete();
for(int n=0;n<10;n++){terminal.Check(&mode);}assert(stopped.inventory.requests==1&&terminal.Complete);
}
''')
@@ -136,7 +137,7 @@ for cls in ('ERR_GameMode','SCR_AIGroup','ERR_EnemyEquipmentGroup','ERR_EnemyEqu
coordinator=re.sub(r'\b'+cls+r' ([a-zA-Z_]\w*)',cls+r'* \1',coordinator)
for obj in ('m_Mode','existing','state','group','agent','entry','actor'):
coordinator=coordinator.replace(obj+'.',obj+'->')
coordinator=coordinator.replace('Group.GetAgents','Group->GetAgents').replace('Combat.ERR_','Combat->ERR_')
coordinator=coordinator.replace('Group.GetAgents','Group->GetAgents').replace('Combat.ERR_','Combat->ERR_').replace('Optics.Check','Optics->Check')
for cls in ('Replication','ERR_GameMode','ERR_EnemyEquipmentRules'):coordinator=coordinator.replace(cls+'.',cls+'::')
coordinator=coordinator.replace('void ERR_EnemyEquipment(', 'ERR_EnemyEquipment(')
coordinator=coordinator.replace('GetGame().GetWorld().GetWorldTime()','worldTime').replace('foreach (','for (').replace('null','nullptr')
@@ -155,9 +156,15 @@ struct IEntity{SCR_AICombatComponent* combat=nullptr;bool eligible=true;};
struct AIAgent{IEntity* actor=nullptr;IEntity* GetControlledEntity(){return actor;}};
struct SCR_AIGroup{Array<AIAgent*> agents;void GetAgents(Array<AIAgent*>& out){out=agents;}};
namespace ERR_EnemyEquipmentRules{bool Eligible(ERR_GameMode*,SCR_AIGroup*,IEntity* actor){return actor&&actor->eligible;}}
struct ERR_EnemyOptics{
IEntity* actor;SCR_AIGroup* group;int checks=0,stops=0;
ERR_EnemyOptics(IEntity* a,SCR_AIGroup* g):actor(a),group(g){}
void Check(ERR_GameMode*){checks++;}void Stop(){stops++;}
};
struct ERR_EnemyEquipmentEntry{
ERR_EnemyOptics* Optics=nullptr;bool Complete=false;
IEntity* Actor=nullptr;SCR_AIGroup* Group=nullptr;SCR_AICombatComponent* Combat=nullptr;bool Released=false;int SkillChecks=0,checks=0,stops=0;
void Check(ERR_GameMode*){checks++;}void Stop(ERR_GameMode*){stops++;Released=true;Combat=nullptr;}
void Check(ERR_GameMode*){checks++;Complete=true;}void Stop(ERR_GameMode*){stops++;Released=true;if(Optics)Optics->Stop();Combat=nullptr;}
};
''' + coordinator + r'''
int main(){
@@ -165,8 +172,11 @@ int main(){
SCR_AIGroup group;IEntity soldier;SCR_AICombatComponent combat;soldier.combat=&combat;AIAgent agent;agent.actor=&soldier;group.agents.Insert(&agent);
service.RegisterGroup(&group);service.RegisterGroup(&group);assert(service.m_Groups.Count()==1);
service.Tick(0);assert(service.m_Entries.Count()==0);service.Tick(3000);assert(service.m_Entries.Count()==1&&combat.binds==1);
service.Tick(3001);assert(service.m_Entries[0]->checks==1);service.Tick(6000);assert(service.m_Entries[0]->checks==2&&combat.binds==1);
service.UnregisterGroup(&group);service.Tick(9000);assert(service.m_Entries[0]->Released&&service.m_Entries[0]->checks==2);
auto entry=service.m_Entries[0];assert(entry->Optics&&entry->Optics->actor==&soldier&&entry->Optics->group==&group);
assert(entry->Complete&&entry->Optics->checks==1); // Stinger is already complete; optics has its own startup completion.
service.Tick(3001);assert(entry->checks==1&&entry->Optics->checks==1);
service.Tick(6000);assert(entry->checks==2&&entry->Optics->checks==2&&combat.binds==1);
service.UnregisterGroup(&group);service.Tick(9000);assert(service.m_Entries[0]->Released&&service.m_Entries[0]->checks==2&&entry->Optics->checks==2&&entry->Optics->stops==1);
service.RegisterGroup(&group);service.Tick(12000);assert(service.m_Entries.Count()==1&&combat.binds==1);
service.Stop();service.RegisterGroup(&group);service.Tick(50000);assert(service.m_Groups.Count()==0&&service.m_Stopped);
ERR_EnemyEquipment delayed(&mode);SCR_AIGroup late;delayed.RegisterGroup(&late);delayed.Tick(3000);late.agents.Insert(&agent);delayed.Tick(6000);assert(delayed.m_Entries.Count()==1);
@@ -174,7 +184,13 @@ int main(){
ERR_EnemyEquipment bounded(&mode);for(int i=0;i<140;i++){bounded.RegisterGroup(new SCR_AIGroup());}assert(bounded.m_Groups.Count()==128);
ERR_EnemyEquipment incomplete(&mode);SCR_AIGroup unresolved;IEntity body;AIAgent bodyAgent;bodyAgent.actor=&body;unresolved.agents.Insert(&bodyAgent);incomplete.RegisterGroup(&unresolved);
for(int i=1;i<=12;i++){incomplete.Tick(i*3000);}assert(incomplete.m_Entries.Count()==1&&incomplete.m_Entries[0]->SkillChecks==5);
incomplete.Stop();
auto incompleteOptics=incomplete.m_Entries[0]->Optics;int checksBeforeStop=incompleteOptics->checks;
incomplete.Stop();incomplete.Tick(60000);assert(incompleteOptics->stops==1&&incompleteOptics->checks==checksBeforeStop);
ERR_EnemyEquipment capture(&mode);SCR_AIGroup capturedGroup;IEntity capturedBody;AIAgent capturedAgent;capturedAgent.actor=&capturedBody;
capturedGroup.agents.Insert(&capturedAgent);capture.RegisterGroup(&capturedGroup);capture.Tick(3000);
auto capturedOptics=capture.m_Entries[0]->Optics;capturedBody.eligible=false;capture.Tick(6000);
assert(capturedOptics->checks==1&&capturedOptics->stops==1&&capture.m_Entries[0]->Released);
capturedBody.eligible=true;capture.Tick(9000);assert(capturedOptics->checks==1);
}
''')
print('PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 128-group bound')