// Vanilla caches are tied to the original game mode. Release its exact // components before takeover. Some vanilla destructors unconditionally clear // their static cache later; resolve those getters from the current takeover // owner so delayed destruction cannot invalidate the replacement. modded class SCR_ArsenalManagerComponent { static void ERR_ReleaseTerrainSingleton(SCR_ArsenalManagerComponent expected) { if (s_Instance == expected) s_Instance = null; } } modded class SCR_GroupsManagerComponent { static void ERR_ReleaseTerrainSingleton(SCR_GroupsManagerComponent expected) { if (s_Instance == expected) s_Instance = null; } } modded class SCR_SupportStationManagerComponent { static void ERR_ReleaseTerrainSingleton(SCR_SupportStationManagerComponent expected) { if (s_Instance == expected) s_Instance = null; } } modded class SCR_TaskFinishHistoryManagerComponent { static void ERR_ReleaseTerrainSingleton(SCR_TaskFinishHistoryManagerComponent expected) { if (s_Instance == expected) s_Instance = null; } override static SCR_TaskFinishHistoryManagerComponent GetInstance() { ERR_TerrainTakeoverMode mode; if (GetGame()) mode = ERR_TerrainTakeoverMode.Cast(GetGame().GetGameMode()); if (mode) return SCR_TaskFinishHistoryManagerComponent.Cast(mode.FindComponent(SCR_TaskFinishHistoryManagerComponent)); return super.GetInstance(); } } modded class SCR_TaskManagerUIComponent { static void ERR_ReleaseTerrainSingleton(SCR_TaskManagerUIComponent expected) { if (s_Instance == expected) s_Instance = null; } override static SCR_TaskManagerUIComponent GetInstance() { ERR_TerrainTakeoverMode mode; if (GetGame()) mode = ERR_TerrainTakeoverMode.Cast(GetGame().GetGameMode()); if (mode) return SCR_TaskManagerUIComponent.Cast(mode.FindComponent(SCR_TaskManagerUIComponent)); return super.GetInstance(); } } modded class SCR_TextsTaskManagerComponent { static void ERR_ReleaseTerrainSingleton(SCR_TextsTaskManagerComponent expected) { if (s_Instance == expected) s_Instance = null; } override static SCR_TextsTaskManagerComponent GetInstance() { ERR_TerrainTakeoverMode mode; if (GetGame()) mode = ERR_TerrainTakeoverMode.Cast(GetGame().GetGameMode()); if (mode) return SCR_TextsTaskManagerComponent.Cast(mode.FindComponent(SCR_TextsTaskManagerComponent)); return super.GetInstance(); } } modded class SCR_MapMarkerManagerComponent { override static SCR_MapMarkerManagerComponent GetInstance() { ERR_TerrainTakeoverMode mode; if (GetGame()) mode = ERR_TerrainTakeoverMode.Cast(GetGame().GetGameMode()); if (mode) return SCR_MapMarkerManagerComponent.Cast(mode.FindComponent(SCR_MapMarkerManagerComponent)); return super.GetInstance(); } } modded class SCR_RespawnSystemComponent { override static SCR_RespawnSystemComponent GetInstance() { ERR_TerrainTakeoverMode mode; if (GetGame()) mode = ERR_TerrainTakeoverMode.Cast(GetGame().GetGameMode()); if (mode) return SCR_RespawnSystemComponent.Cast(mode.FindComponent(SCR_RespawnSystemComponent)); return super.GetInstance(); } } // Standalone global nodes otherwise have no delivery-order relationship. During // a connected restart a faction delegate can arrive before its new mode and // faction manager. Express that dependency to replication before publishing the // newly spawned hierarchy, rather than relying on an arbitrary frame delay. class ERR_TerrainTakeoverReplication { static void CollectDelegates(SCR_DelegateFactionManagerComponent manager, array entities) { if (!manager) return; map delegates = new map(); manager.GetFactionDelegates(delegates); for (int i = 0; i < delegates.Count(); i++) { SCR_EditableFactionComponent delegate = delegates.GetElement(i); if (delegate && delegate.GetOwner() && !entities.Contains(delegate.GetOwner())) entities.Insert(delegate.GetOwner()); } } protected static bool Parent(IEntity entity, IEntity parent) { RplComponent childRpl = SCR_EntityHelper.GetEntityRplComponent(entity); RplComponent parentRpl = SCR_EntityHelper.GetEntityRplComponent(parent); if (!childRpl || !parentRpl) return false; RplNode childNode = childRpl.GetNode(); RplNode parentNode = parentRpl.GetNode(); if (!childNode || !parentNode || childNode == parentNode) return false; if (childNode.GetParent() != parentNode) childNode.SetParent(parentNode); return childNode.GetParent() == parentNode; } static bool Link(ERR_GameMode mode) { IEntity factions = GetGame().GetFactionManager(); if (!factions || !Parent(factions, mode)) return false; if (!Parent(GetGame().GetLoadoutManager(), mode) || !Parent(GetGame().GetChat(), mode)) return false; SCR_DelegateFactionManagerComponent manager = SCR_DelegateFactionManagerComponent.GetInstance(); if (!manager) return false; map delegates = new map(); manager.GetFactionDelegates(delegates); for (int i = 0; i < delegates.Count(); i++) { SCR_EditableFactionComponent delegate = delegates.GetElement(i); if (!delegate || !Parent(delegate.GetOwner(), factions)) return false; } return !delegates.IsEmpty(); } }