Files
EscapistsReintroduced/docs/evidence/crash-start-2026-10-03/proposals/nearby-native/fix.patch
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

61 lines
3.7 KiB
Diff

--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashStartProbe.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashStartProbe.c
@@ -3,6 +3,28 @@
// actor relocation, damage or inventory creation in this probe.
class ERR_NativeCrashStartProbe
{
+ protected static SCR_AIGroup s_ClueGroup;
+ protected static ref array<SCR_ChimeraAIAgent> s_ClueAgents = {};
+ protected static ref array<IEntity> s_ClueBodies = {};
+ static bool NearbyEnemies(ERR_GameMode mode, IEntity player)
+ {
+ ERR_SiteRuntime clue = mode.Sites().Find("everon-supply-1");
+ if (!clue || clue.Group != s_ClueGroup || !s_ClueGroup || s_ClueAgents.IsEmpty() || s_ClueAgents.Count() != s_ClueBodies.Count()) return false;
+ array<AIAgent> current = {}; s_ClueGroup.GetAgents(current);
+ int nearby, active;
+ for (int index = 0; index < s_ClueAgents.Count(); index++)
+ {
+ SCR_ChimeraAIAgent agent = s_ClueAgents[index]; IEntity actor = s_ClueBodies[index];
+ if (!agent || !actor || agent.GetControlledEntity() != actor || !current.Contains(agent) || !ERR_Actors.CanFight(actor) || ERR_Actors.Player(actor)) continue;
+ if (vector.DistanceXZ(actor.GetOrigin(), player.GetOrigin()) > 100) continue;
+ nearby++;
+ bool awake = agent.IsAIActivated();
+ PrintFormat("ERR CRASH NEARBY AI: index=%1 active=%2 lod=%3 permanentLod=%4 prisonHeld=%5", index, awake, agent.GetLOD(), agent.GetPermanentLOD(), agent.ERR_PrisonHeldForTest());
+ if (awake && !agent.ERR_PrisonHeldForTest()) active++;
+ }
+ PrintFormat("ERR CRASH NEARBY AI TOTAL: retained=%1 nearby=%2 active=%3; ordinary native activation after scripted cache approach, no activation override", s_ClueAgents.Count(), nearby, active);
+ return active > 0;
+ }
protected static bool Check(bool condition, string message)
{
if (condition) { Print("ERR SMOKE PASS: crash start " + message); return true; }
@@ -24,6 +46,18 @@
static bool Run(ERR_GameMode mode, IEntity player)
{
if (!Check(mode && mode.StartMode() == 1 && mode.Phase() == ERR_Phase.RADIO_SEARCH, "frozen choice enters radio search directly")) return false;
+ s_ClueAgents.Clear(); s_ClueBodies.Clear(); s_ClueGroup = null;
+ ERR_SiteRuntime clue = mode.Sites().Find("everon-supply-1");
+ if (!Check(clue && clue.Group, "retains original clue defenders before approach")) return false;
+ s_ClueGroup = clue.Group;
+ array<AIAgent> guards = {}; s_ClueGroup.GetAgents(guards);
+ if (guards.IsEmpty() || guards.Count() > 16) return false;
+ foreach (AIAgent guard : guards)
+ {
+ SCR_ChimeraAIAgent original = SCR_ChimeraAIAgent.Cast(guard);
+ if (!original || !original.GetControlledEntity()) return false;
+ s_ClueAgents.Insert(original); s_ClueBodies.Insert(original.GetControlledEntity());
+ }
ERR_PlayerLife life = mode.Players().CurrentActor(player);
CompartmentAccessComponent access = CompartmentAccessComponent.Cast(player.FindComponent(CompartmentAccessComponent));
if (!Check(life && life.UsedLife && access && !access.IsInCompartment() && ERR_Actors.CanFight(player), "ordinary canonical one-life survivor starts conscious on foot")) return false;
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
@@ -985,6 +985,7 @@
}
else if (m_ERRSmokeStep == 3)
{
+ if (m_ERRTestCrashStart && !ERR_Check(ERR_NativeCrashStartProbe.NearbyEnemies(this, m_ERRSmokePlayer), "an original nearby clue defender has native AI active after crash-route approach")) return;
if (!ERR_CheckRouteExtras(now)) return;
if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2, "carried intel identifies radio through intel service")) return;
if (!ERR_Check(!TuneRadio(m_ERRSmokePlayer, m_ERRSmokeRadio), "radio rejects distant player")) return;