Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c
|
||||
@@ -1,6 +1,39 @@
|
||||
// Decisions consumed by the finite original-item controller below.
|
||||
class ERR_EngineerMineRules
|
||||
{
|
||||
+ // Straight XZ corridors are conservative local checks, not native route proofs.
|
||||
+ static bool CorridorClear(vector start, vector end, array<vector> priorSites)
|
||||
+ {
|
||||
+ if (!ERR_ForceRules.FiniteVector(start) || !ERR_ForceRules.FiniteVector(end)) return false;
|
||||
+ if (!priorSites) return true;
|
||||
+ if (priorSites.Count() > 32) return false;
|
||||
+ float dx = end[0] - start[0], dz = end[2] - start[2];
|
||||
+ float squared = dx * dx + dz * dz;
|
||||
+ if (!ERR_ForceRules.Finite(squared)) return false;
|
||||
+ foreach (vector site : priorSites)
|
||||
+ {
|
||||
+ if (!ERR_ForceRules.FiniteVector(site)) return false;
|
||||
+ float along = 0;
|
||||
+ if (squared > 0)
|
||||
+ {
|
||||
+ float projection = (site[0] - start[0]) * dx + (site[2] - start[2]) * dz;
|
||||
+ if (!ERR_ForceRules.Finite(projection)) return false;
|
||||
+ along = projection / squared;
|
||||
+ if (!ERR_ForceRules.Finite(along)) return false;
|
||||
+ along = Math.Clamp(along, 0, 1);
|
||||
+ }
|
||||
+ float x = start[0] + along * dx - site[0], z = start[2] + along * dz - site[2];
|
||||
+ float clearance = x * x + z * z;
|
||||
+ if (!ERR_ForceRules.Finite(clearance) || clearance <= 400) return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ static bool WithinWorkArea(vector post, vector actor)
|
||||
+ {
|
||||
+ if (!ERR_ForceRules.FiniteVector(post) || !ERR_ForceRules.FiniteVector(actor)) return false;
|
||||
+ float distance = vector.DistanceXZ(post, actor);
|
||||
+ return ERR_ForceRules.Finite(distance) && distance <= 60;
|
||||
+ }
|
||||
static bool Within(float started, float previous, float now)
|
||||
{
|
||||
return ERR_ForceRules.Finite(started) && ERR_ForceRules.Finite(previous) && ERR_ForceRules.Finite(now)
|
||||
@@ -56,6 +89,7 @@
|
||||
protected ref ERR_EngineerMineRemoval m_Removal;
|
||||
protected ref array<IEntity> m_Attempted;
|
||||
protected ref array<IEntity> m_IntelFolders = {};
|
||||
+ protected ref array<vector> m_PriorSites = {};
|
||||
protected vector m_Position;
|
||||
protected vector m_Rally;
|
||||
protected float m_Started = -1;
|
||||
@@ -70,6 +104,14 @@
|
||||
|
||||
void ERR_EngineerMine(array<IEntity> attempted) { m_Attempted = attempted; }
|
||||
bool Finished() { return m_Stopped || m_State == 4; }
|
||||
+ bool BlocksNextPost(ERR_ForceRecord record)
|
||||
+ {
|
||||
+ if (!record || record != m_Record) return false;
|
||||
+ if (m_Begun && !Finished()) return true;
|
||||
+ // A late terminal callback or exact deletion settles only the old job.
|
||||
+ // Destroyed but surviving items and uncertain native refusals remain pinned.
|
||||
+ return m_Removal && !m_Removal.Result && m_Mine;
|
||||
+ }
|
||||
protected bool Refuse() { Stop(); return false; }
|
||||
protected bool Quiet()
|
||||
{
|
||||
@@ -90,6 +132,11 @@
|
||||
if (m_Record.SourceId != m_SourceId || m_Unit.ForceSourceId != m_SourceId || m_Record.InitialStrength != m_Strength) return false;
|
||||
if (!m_Unit.StatusSampler.OwnsRoster(m_Group) || m_Unit.StatusSampler.InitialStrength() != m_Strength) return false;
|
||||
if (!m_Actor || !ERR_Actors.CanFight(m_Actor) || ERR_Actors.Player(m_Actor) || CompartmentAccessComponent.GetVehicleIn(m_Actor)) return false;
|
||||
+ vector actorPosition = m_Actor.GetOrigin();
|
||||
+ if (!ERR_EngineerMineRules.WithinWorkArea(m_Rally, actorPosition) || !ERR_EngineerMineRules.WithinWorkArea(m_Rally, m_Position)) return false;
|
||||
+ if (!ERR_EngineerMineRules.CorridorClear(actorPosition, actorPosition, m_PriorSites)
|
||||
+ || !ERR_EngineerMineRules.CorridorClear(m_Position, m_Position, m_PriorSites)
|
||||
+ || !ERR_EngineerMineRules.CorridorClear(m_Rally, m_Rally, m_PriorSites)) return false;
|
||||
if (!m_Unit.StatusSampler.CanAttribute(m_Slot, m_Actor, false) || ERR_Actors.Group(m_Actor) != m_Group) return false;
|
||||
if (SCR_FactionManager.SGetFaction(m_Actor) != m_Mode.EnemyFaction()) return false;
|
||||
SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(m_Actor));
|
||||
@@ -190,7 +237,7 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
- bool Begin(ERR_GameMode mode, ERR_HQUnit unit, ERR_HQTask task, vector minePosition, float now)
|
||||
+ bool Begin(ERR_GameMode mode, ERR_HQUnit unit, ERR_HQTask task, vector minePosition, float now, array<vector> priorSites = null)
|
||||
{
|
||||
if (m_Begun || m_Stopped) return false;
|
||||
m_Begun = true;
|
||||
@@ -203,7 +250,18 @@
|
||||
m_Position = minePosition; m_Rally = task.Destination;
|
||||
float distance = vector.DistanceXZ(m_Position, m_Rally);
|
||||
if (!ERR_ForceRules.FiniteVector(m_Rally) || distance < 25 || distance > 60 || now >= task.ExpiresAt) return Refuse();
|
||||
+ if (priorSites)
|
||||
+ {
|
||||
+ if (priorSites.Count() > 32) return Refuse();
|
||||
+ foreach (vector prior : priorSites)
|
||||
+ {
|
||||
+ if (!ERR_ForceRules.FiniteVector(prior)) return Refuse();
|
||||
+ m_PriorSites.Insert(prior);
|
||||
+ }
|
||||
+ }
|
||||
if (!SelectActor() || !Owned() || !Quiet()) return Refuse();
|
||||
+ if (!ERR_EngineerMineRules.CorridorClear(m_Actor.GetOrigin(), m_Position, m_PriorSites)
|
||||
+ || !ERR_EngineerMineRules.CorridorClear(m_Position, m_Rally, m_PriorSites)) return Refuse();
|
||||
// The shared exact-item tombstone survives pickup, transfer and late callbacks.
|
||||
m_Attempted.Insert(m_Mine);
|
||||
if (!Carried()) return Refuse();
|
||||
Reference in New Issue
Block a user