Integrate radio-delivered convoy cover and conservative squad ammunition reports

This commit is contained in:
2026-09-20 04:23:11 +02:00
parent 9b6596eb3e
commit 9205e2129a
88 changed files with 13934 additions and 28 deletions
+13 -2
View File
@@ -10,11 +10,12 @@ def cpp(s):
for old,new in [('protected ',''),('null','nullptr'),('Replication.','Replication::'),
('ERR_Actors.','ERR_Actors::'),('ERR_HQPursuitRules.','ERR_HQPursuitRules::'),
('SCR_FactionManager.','SCR_FactionManager::'),('ERR_HQRadio.','ERR_HQRadio::'),('Math.','Math::'),
('sourceId.IsEmpty()','sourceId.empty()'),('sourceId.Length()','sourceId.size()')]:s=s.replace(old,new)
('ERR_HQAmmoSampler.','ERR_HQAmmoSampler::'),('sourceId.IsEmpty()','sourceId.empty()'),('sourceId.Length()','sourceId.size()')]:s=s.replace(old,new)
for typ in ('IEntity','AIAgent','SCR_AIGroup','Faction','ERR_HQStatusReport','DamageManagerComponent'):
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
for var in ('actor','agent','group','report','m_Group','damage'):s=s.replace(var+'.',var+'->')
s=s.replace('foreach (AIAgent* agent : m_Agents)','for (AIAgent* agent : m_Agents)')
s=s.replace('report->AmmoState.', 'report->AmmoState->')
return s
methods='\n'.join(cpp(body(P,s)) for s in ('bool Bound()', 'protected bool Eligible(', 'bool Bind(',
'string InitialSourceId(', 'int InitialStrength(', 'bool OwnsRoster(', 'IEntity InitialMember(',
@@ -56,7 +57,10 @@ struct ERR_Actors{
};
struct SCR_FactionManager{static Faction* SGetFaction(IEntity* a){return a?a->faction:nullptr;}};
struct ERR_HQRadio{static int Capability(IEntity* a){return ERR_Actors::CanFight(a)&&a->radio?1:0;}};
struct ERR_HQStatusReport{
struct ERR_HQAmmoSnapshot{bool Complete=false,LauncherComplete=false;int Members=0;};
struct ERR_HQAmmoSampler{inline static Array<IEntity*> sampled;
static void Inspect(IEntity* actor,SCR_AIGroup* group,ERR_HQAmmoSnapshot* state){assert(actor&&actor->group==group);sampled.Insert(actor);state->Members++;}};
struct ERR_HQStatusReport{ERR_HQAmmoSnapshot* AmmoState=nullptr;
string SourceId;int MessageId=0;vector Position;int Strength=0,Count=0,Fit=0,ConfirmedLosses=0;
float ObservedAt=-1;Array<int> DeathSlots;
};
@@ -90,6 +94,10 @@ int main(){
assert(!sample.CanAttribute(1,&members[2]));std::reverse(group.agents.begin(),group.agents.end());
auto first=sample.Sample(1000,1,&members[0]);assert(first&&first->Count==4&&first->Fit==4&&first->Strength==4);
assert(first->Position.x==100&&first->SourceId=="site");
assert(first->AmmoState&&first->AmmoState->Complete&&first->AmmoState->Members==4);
assert(ERR_HQAmmoSampler::sampled.Count()==4);
for(auto* actor:ERR_HQAmmoSampler::sampled)assert(actor>=&members[0]&&actor<=&members[3]);
ERR_HQAmmoSampler::sampled.Clear();
group.position.x=200;assert(first->Position.x==100); // detached snapshot
members[1].unconscious=true;auto injured=sample.Sample(2000,2,&members[0]);
assert(injured&&injured->Count==4&&injured->Fit==3&&injured->ConfirmedLosses==0);
@@ -109,6 +117,7 @@ int main(){
sample.m_Members[2]=nullptr;members[3].hasDamage=false;
auto absent=sample.Sample(4000,4,&members[0]);
assert(absent&&absent->Count==1&&absent->ConfirmedLosses==1);
assert(!absent->AmmoState->Complete&&absent->AmmoState->Members==1); // missing original identity/component => unknown
members[3].hasDamage=true;members[3].player=true;assert(sample.ObserveDeaths());
assert(!sample.CanAttribute(3,&members[3]));
members[3].player=false;members[3].damage.dead=true;assert(sample.ObserveDeaths()&&sample.m_Deaths==1);
@@ -116,7 +125,9 @@ int main(){
// Never adopt an externally attached replacement as one of the authored original members.
IEntity replacement;replacement.group=&group;replacement.faction=&enemy;AIAgent replacementAgent;replacementAgent.actor=&replacement;
group.agents.Insert(&replacementAgent);assert(!sample.Sample(5000,5,&replacement));
ERR_HQAmmoSampler::sampled.Clear();
auto original=sample.Sample(5000,5,&members[0]);assert(original&&original->Strength==4&&original->Count==1);
assert(ERR_HQAmmoSampler::sampled.Count()==1&&ERR_HQAmmoSampler::sampled[0]==&members[0]); // no replacement/dead/released inventory sampling
members[0].radio=false;assert(!sample.Sample(6000,6,&members[0]));members[0].radio=true;
members[0].unconscious=true;assert(!sample.Sample(6000,6,&members[0]));members[0].unconscious=false;
group.players=1;assert(!sample.ObserveDeaths()&&!sample.Sample(6000,6,&members[0]));group.players=0;