Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
144 lines
6.7 KiB
Plaintext
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");}
|
|
}
|
|
}
|