Files
EscapistsReintroduced/docs/evidence/roadblocks-body-recovery-2026-10-03/native-fix-probe.c.txt
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

144 lines
6.7 KiB
Plaintext

modded class ERR_BodyRecovery
{
bool ERR_TestBorrow(vector position, SCR_AIGroup expected, float now)
{
int waves = m_Waves;
ERR_BodyRecoveryJob job = new ERR_BodyRecoveryJob(); job.Id = 999; job.Position = position;
bool result = SpawnTeam(job, now);
return result && job.Team == expected && job.Prepared && job.State == 1 && m_Waves == waves;
}
}
modded class ERR_EngineerMine
{
protected bool m_ERRCleared;
protected bool ERR_MoveTestFriend(IEntity entity)
{
ChimeraCharacter character=ChimeraCharacter.Cast(entity);
if(!character || entity==m_Actor || ERR_Actors.Player(entity))return true;
vector transform[4];character.GetWorldTransform(transform);transform[3]=ERR_Actors.Ground(m_Rally+Vector(0,0,100));character.Teleport(transform);
return true;
}
void ERR_ClearTestFriends()
{
if(m_State!=3 || m_ERRCleared)return;
m_ERRCleared=true;
GetGame().GetWorld().QueryEntitiesBySphere(m_Position,25,ERR_MoveTestFriend,queryFlags:EQueryEntitiesFlags.ALL);
}
bool ERR_TestArmed() { return m_Trigger && m_Trigger.IsActivated(); }
string ERR_TestProgress() { return string.Format("stage=%1 stopped=%2 owned=%3 quiet=%4 actor=%5 mine=%6 site=%7",m_State,m_Stopped,Owned(),Quiet(),m_Actor.GetOrigin(),m_Mine.GetOrigin(),m_Position)+string.Format(" placed=%1 friendNear=%2",Placed(),m_FriendlyNear); }
}
modded class ERR_HQ
{
bool ERR_TestRecovery(float now)
{
IndexRadios();
foreach (ERR_HQUnit unit : m_Units)
{
if (!unit.Eligible(m_Mode) || !unit.StatusSampler.Bound() || !unit.Radio || unit.Assignment || unit.PendingOrder || unit.Downlink || Fighting(unit)) continue;
if (!m_Network.Route(unit.Radio, true)) continue;
ERR_HQStatusReport status = new ERR_HQStatusReport(); status.SourceId = unit.ForceSourceId;status.MessageId=m_Journal.Message();status.Position=unit.Group.GetOrigin();status.Strength=unit.StatusSampler.InitialStrength();status.Count=m_Mode.ForceLiving(unit.Group);status.Fit=status.Count;status.ObservedAt=now;
if (!m_Watch.Ingest(status,now)) continue;
bool guard=unit.HomeGuard;unit.HomeGuard=false;
bool result=m_Recovery.ERR_TestBorrow(status.Position,unit.Group,now);
unit.ReservedForSupport=false;unit.HomeGuard=guard;
return result;
}
return false;
}
ERR_EngineerMine ERR_TestMine(float now)
{
m_Equipment.Tick(now); m_Journal.Flush();
foreach (ERR_HQUnit original : m_Units)
{
if (original.ForceSourceId.Contains("prison")) continue;
if (!original.Eligible(m_Mode) || !original.StatusSampler.Bound() || Fighting(original)) continue;
vector rally=original.Group.GetOrigin();
bool carried;
array<AIAgent> agents={};original.Group.GetAgents(agents);
foreach (AIAgent agent:agents)
{
IEntity actor=agent.GetControlledEntity(); if(!actor) continue;
SCR_InventoryStorageManagerComponent inventory=SCR_InventoryStorageManagerComponent.Cast(actor.FindComponent(SCR_InventoryStorageManagerComponent));
if(!inventory) continue;
array<IEntity> items={};ERR_Inventory.Items(inventory,items);
foreach(IEntity item:items) if(item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName()==ERR_EnemyLoadoutCatalog.MINE) carried=true;
}
if(!carried) continue;
vector site;
if(!ERR_EngineerMineSite.Select(rally,site))
{
bool clear;
for(int direction=0;direction<8;direction++)
{
float angle=direction*Math.PI2/8;
site=ERR_Actors.Ground(rally+Vector(Math.Cos(angle)*35,0,Math.Sin(angle)*35));
if(!ERR_HQRoadIntercept.Standable(site))continue;
bool nearFriend;
foreach(AIAgent neighbour:agents) if(neighbour.GetControlledEntity() && vector.DistanceXZ(neighbour.GetControlledEntity().GetOrigin(),site)<25)nearFriend=true;
if(nearFriend)continue;
clear=true;break;
}
if(!clear)continue;
}
if (!m_ERRFixtureRoadGroups.Contains(original.Group))
{
AIWaypoint post = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(),rally));
if(!post)continue;
post.SetCompletionRadius(70); original.Group.AddWaypointAt(post,0);
m_ERRFixtureRoadGroups.Insert(original.Group);
original.Group.SetPermanentLOD(0);
foreach(AIAgent heldBefore:agents){heldBefore.SetPermanentLOD(0);heldBefore.ActivateAI();}
continue;
}
ERR_HQUnit unit=new ERR_HQUnit();unit.Group=original.Group;unit.Utility=original.Utility;unit.StatusSampler=original.StatusSampler;unit.ForceSourceId=original.ForceSourceId;
unit.Task=new ERR_HQTask();unit.Task.RoadIntercept=true;unit.Task.Role=ERR_HQPursuitRole.INTERCEPT;unit.Task.Destination=rally;unit.Task.QueuedAt=now;unit.Task.ExpiresAt=now+180000;
unit.Assignment=new ERR_HQReport();unit.Assignment.MessageId=777;unit.Assignment.ObservedAt=now;unit.Assignment.Position=rally;
array<IEntity> attempted={};ERR_EngineerMine mine=new ERR_EngineerMine(attempted);
if(!mine.Begin(m_Mode,unit,unit.Task,site,now)) continue;
// Keep this arranged unit alive; production owns the actual movement/item.
m_ERRFixtureUnit=unit; m_ERRFixtureAttempts=attempted;
original.ReservedForSupport=true;
original.Group.SetPermanentLOD(0);
foreach(AIAgent held:agents) {held.SetPermanentLOD(0);held.ActivateAI();}
return mine;
}
return null;
}
protected ref array<SCR_AIGroup> m_ERRFixtureRoadGroups = {};
protected ref ERR_HQUnit m_ERRFixtureUnit;
protected ref array<IEntity> m_ERRFixtureAttempts;
}
modded class ArmaReforgerScripted
{
protected float m_ERRFixStart=-1,m_ERRFixNext;
protected bool m_ERRFixBorrowed,m_ERRFixDone;
protected ref ERR_EngineerMine m_ERRFixMine;
override void OnUpdate(BaseWorld world,float timeslice)
{
super.OnUpdate(world,timeslice);
ERR_GameMode mode=ERR_GameMode.Get();
if(m_ERRFixDone || !world || !Replication.IsServer() || !mode || !mode.Active())return;
float now=world.GetWorldTime();
if(m_ERRFixStart<0) m_ERRFixStart=now;
if(!m_ERRFixBorrowed && now-m_ERRFixStart>10000)
{
m_ERRFixBorrowed=ERR_HQ.Get().ERR_TestRecovery(now);
if(m_ERRFixBorrowed)Print("ERR FIX PASS: existing native idle infantry selected for body search without new spawn");
}
if(!m_ERRFixMine && m_ERRFixBorrowed)m_ERRFixMine=ERR_HQ.Get().ERR_TestMine(now);
if(m_ERRFixMine)
{
m_ERRFixMine.ERR_ClearTestFriends();
m_ERRFixMine.Tick(now); ERR_HQ.Get().Journal().Flush();
if(now>=m_ERRFixNext){m_ERRFixNext=now+10000;Print("ERR FIX MINE: "+m_ERRFixMine.ERR_TestProgress());}
if(m_ERRFixMine.Finished())
{
if(m_ERRFixMine.ERR_TestArmed())Print("ERR FIX PASS: native soldier walked, removed carried mine, withdrew and armed it");
else Print("ERR FIX FAIL: physical mine job stopped before arming",LogLevel.ERROR);
m_ERRFixDone=true;Print("ERR FIX COMPLETE");
}
}
if(now-m_ERRFixStart>210000){Print("ERR FIX FAIL: fixture deadline",LogLevel.ERROR);m_ERRFixDone=true;Print("ERR FIX COMPLETE");}
}
}