Preserve native chat during terrain takeover with fallback for missing chat
This commit is contained in:
@@ -11,6 +11,11 @@ enum ERR_TerrainTakeoverStage
|
||||
|
||||
class ERR_TerrainTakeoverRules
|
||||
{
|
||||
static ResourceName Bootstrap(bool hasNativeChat)
|
||||
{
|
||||
if (hasNativeChat) return "{9D182739ABEF405C}Prefabs/ERR/TerrainTakeover.et";
|
||||
return "{DA8E364BC095712F}Prefabs/ERR/TerrainTakeoverWithChat.et";
|
||||
}
|
||||
static bool TimedOut(float elapsed) { return elapsed >= 10; }
|
||||
static bool MayDrain(float elapsed, bool sameMode) { return elapsed >= 0.5 && sameMode; }
|
||||
static bool MayCreate(float elapsed, bool empty) { return empty && !TimedOut(elapsed); }
|
||||
@@ -68,6 +73,7 @@ modded class ArmaReforgerScripted
|
||||
protected ERR_TerrainTakeoverStage m_ERRTerrainStage;
|
||||
protected float m_ERRTerrainElapsed;
|
||||
protected RadioManagerEntity m_ERRTerrainRadio;
|
||||
protected BaseChatEntity m_ERRTerrainChat;
|
||||
protected EntityID m_ERRTerrainOldLoadoutId;
|
||||
protected BaseWorld m_ERRTerrainWorld;
|
||||
protected SCR_BaseGameMode m_ERRTerrainOriginal;
|
||||
@@ -110,6 +116,7 @@ modded class ArmaReforgerScripted
|
||||
m_ERRTerrainStage = ERR_TerrainTakeoverStage.INACTIVE;
|
||||
m_ERRTerrainElapsed = 0;
|
||||
m_ERRTerrainRadio = null;
|
||||
m_ERRTerrainChat = null;
|
||||
m_ERRTerrainOldLoadoutId = EntityID.INVALID;
|
||||
m_ERRTerrainWorld = null;
|
||||
m_ERRTerrainOriginal = null;
|
||||
@@ -130,7 +137,7 @@ modded class ArmaReforgerScripted
|
||||
ERR_FailTerrainTakeover("Select a plain scenario with SCR_BaseGameMode and a Soldiers navmesh; original scenario retained.");
|
||||
return false;
|
||||
}
|
||||
Resource prefab = Resource.Load("{9D182739ABEF405C}Prefabs/ERR/TerrainTakeover.et");
|
||||
Resource prefab = Resource.Load(ERR_TerrainTakeoverRules.Bootstrap(GetChat() != null));
|
||||
if (!prefab || !prefab.IsValid())
|
||||
{
|
||||
ERR_FailTerrainTakeover("Escape bootstrap prefab is missing; original scenario retained.");
|
||||
@@ -210,8 +217,13 @@ modded class ArmaReforgerScripted
|
||||
{
|
||||
SCR_EditorManagerCore editorCore = SCR_EditorManagerCore.Cast(SCR_EditorManagerCore.GetInstance(SCR_EditorManagerCore));
|
||||
if (editorCore) editorCore.ERR_SetTerrainModeEvents(m_ERRTerrainOriginal, false);
|
||||
array<IEntity> managers = {m_ERRTerrainOriginal, GetLoadoutManager(), GetFactionManager(), GetPerceptionManager(), GetChat()};
|
||||
array<IEntity> managers = {m_ERRTerrainOriginal, GetLoadoutManager(), GetFactionManager(), GetPerceptionManager()};
|
||||
ERR_TerrainTakeoverReplication.CollectDelegates(SCR_DelegateFactionManagerComponent.GetInstance(), managers);
|
||||
// Native chat unregister can clear a newer registration after replication
|
||||
// delivers the replacement. Keep the terrain's chat on both peers instead.
|
||||
m_ERRTerrainChat = GetChat();
|
||||
if (m_ERRTerrainChat && !ERR_TerrainTakeoverReplication.RetainManager(m_ERRTerrainChat, managers))
|
||||
{ ERR_FailTerrainTakeover("Could not retain the native chat service; original scenario retained."); return; }
|
||||
ChimeraWorld chimera = ChimeraWorld.CastFrom(GetWorld());
|
||||
if (chimera) m_ERRTerrainRadio = chimera.GetRadioManager();
|
||||
// Native radio teardown clears the world pointer even after a replacement
|
||||
@@ -230,7 +242,7 @@ modded class ArmaReforgerScripted
|
||||
ancestor = ancestor.GetParent();
|
||||
}
|
||||
}
|
||||
Print("Reintroduced [terrain takeover]: stopping original scenario; preserving radio manager");
|
||||
Print("Reintroduced [terrain takeover]: stopping original scenario; preserving radio and chat managers");
|
||||
m_ERRTerrainOriginal.OnGameEnd();
|
||||
if (m_DataCollectorComponent && m_DataCollectorComponent.GetOwner() == m_ERRTerrainOriginal) m_DataCollectorComponent = null;
|
||||
SCR_EntityCatalogManagerComponent.ERR_ReleaseTerrainCatalog(m_ERRTerrainOriginal);
|
||||
@@ -258,7 +270,7 @@ modded class ArmaReforgerScripted
|
||||
protected bool ERR_TerrainRegistrationsEmpty()
|
||||
{
|
||||
ChimeraWorld chimera = ChimeraWorld.CastFrom(GetWorld());
|
||||
return !GetGameMode() && !GetLoadoutManager() && !GetFactionManager() && !GetPerceptionManager() && !GetChat() && (!chimera || chimera.GetRadioManager() == m_ERRTerrainRadio) && !SCR_EntityCatalogManagerComponent.GetInstance() && !m_DataCollectorComponent;
|
||||
return !GetGameMode() && !GetLoadoutManager() && !GetFactionManager() && !GetPerceptionManager() && GetChat() == m_ERRTerrainChat && (!chimera || chimera.GetRadioManager() == m_ERRTerrainRadio) && !SCR_EntityCatalogManagerComponent.GetInstance() && !m_DataCollectorComponent;
|
||||
}
|
||||
protected void ERR_CreateTerrainMode()
|
||||
{
|
||||
@@ -277,9 +289,9 @@ modded class ArmaReforgerScripted
|
||||
if (!marker) { ERR_FailTerrainTakeover("Could not create configured airport marker; restart the scenario."); return; }
|
||||
marker.SetName("ERR_Airfield_" + m_ERRTerrainMarkerSlots[i].ToString());
|
||||
}
|
||||
ERR_GameMode mode = ERR_GameMode.Cast(SpawnEntityPrefab(Resource.Load("{9D182739ABEF405C}Prefabs/ERR/TerrainTakeover.et"), GetWorld()));
|
||||
ERR_GameMode mode = ERR_GameMode.Cast(SpawnEntityPrefab(Resource.Load(ERR_TerrainTakeoverRules.Bootstrap(m_ERRTerrainChat != null)), GetWorld()));
|
||||
if (!mode || GetGameMode() != mode) { ERR_FailTerrainTakeover("Escape game mode could not register; restart the scenario."); return; }
|
||||
if (!ERR_TerrainTakeoverReplication.Link(mode)) { ERR_FailTerrainTakeover("Escape replication hierarchy could not register; restart the scenario."); return; }
|
||||
if (!ERR_TerrainTakeoverReplication.Link(mode, !m_ERRTerrainChat)) { ERR_FailTerrainTakeover("Escape replication hierarchy could not register; restart the scenario."); return; }
|
||||
SCR_EditorManagerCore editorCore = SCR_EditorManagerCore.Cast(SCR_EditorManagerCore.GetInstance(SCR_EditorManagerCore));
|
||||
if (editorCore) editorCore.ERR_SetTerrainModeEvents(mode, true);
|
||||
m_ERRTerrainStage = ERR_TerrainTakeoverStage.RUNNING;
|
||||
|
||||
@@ -57,7 +57,6 @@ modded class ArmaReforgerScripted
|
||||
m_ERRClientOldManagers.Insert(GetLoadoutManager());
|
||||
m_ERRClientOldManagers.Insert(GetFactionManager());
|
||||
m_ERRClientOldManagers.Insert(GetPerceptionManager());
|
||||
m_ERRClientOldManagers.Insert(GetChat());
|
||||
}
|
||||
override void UnregisterLoadoutManager(SCR_LoadoutManager instance)
|
||||
{
|
||||
@@ -89,6 +88,13 @@ modded class ArmaReforgerScripted
|
||||
void ERR_BeginClientTerrainTakeover(ERR_TerrainTakeoverMode incoming)
|
||||
{
|
||||
if (m_ERRClientOldManagers.IsEmpty()) return;
|
||||
// Match authority retention before deleting any original parent. No second
|
||||
// chat entity is created when the terrain already supplies one.
|
||||
if (GetChat() && !ERR_TerrainTakeoverReplication.RetainManager(GetChat(), m_ERRClientOldManagers))
|
||||
{
|
||||
Print("Reintroduced [terrain client]: could not retain native chat; original managers retained", LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
m_ERRClientTerrainTakeover = true;
|
||||
SCR_BaseGameMode mode = SCR_BaseGameMode.Cast(m_ERRClientOldManagers[0]);
|
||||
PrintFormat("Reintroduced [terrain client]: drain retained mode=%1 incoming=%2", mode, incoming);
|
||||
|
||||
@@ -256,6 +256,25 @@ class ERR_TerrainTakeoverReplication
|
||||
if (delegate && delegate.GetOwner() && !entities.Contains(delegate.GetOwner())) entities.Insert(delegate.GetOwner());
|
||||
}
|
||||
}
|
||||
// Shared world services must survive removal of an old game-mode hierarchy.
|
||||
static bool RetainManager(IEntity entity, array<IEntity> removed)
|
||||
{
|
||||
if (!entity || !removed || removed.Contains(entity)) return false;
|
||||
IEntity ancestor = entity.GetParent();
|
||||
while (ancestor)
|
||||
{
|
||||
if (removed.Contains(ancestor))
|
||||
{
|
||||
entity.GetParent().RemoveChild(entity, true);
|
||||
if (entity.GetParent()) return false;
|
||||
RplComponent rpl = SCR_EntityHelper.GetEntityRplComponent(entity);
|
||||
if (rpl && rpl.GetNode()) rpl.GetNode().SetParent(null);
|
||||
return true;
|
||||
}
|
||||
ancestor = ancestor.GetParent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected static bool Parent(IEntity entity, IEntity parent)
|
||||
{
|
||||
RplComponent childRpl = SCR_EntityHelper.GetEntityRplComponent(entity);
|
||||
@@ -267,11 +286,14 @@ class ERR_TerrainTakeoverReplication
|
||||
if (childNode.GetParent() != parentNode) childNode.SetParent(parentNode);
|
||||
return childNode.GetParent() == parentNode;
|
||||
}
|
||||
static bool Link(ERR_GameMode mode)
|
||||
static bool Link(ERR_GameMode mode, bool ownsChat)
|
||||
{
|
||||
IEntity factions = GetGame().GetFactionManager();
|
||||
if (!factions || !Parent(factions, mode)) return false;
|
||||
if (!Parent(GetGame().GetLoadoutManager(), mode) || !Parent(GetGame().GetChat(), mode)) return false;
|
||||
if (!Parent(GetGame().GetLoadoutManager(), mode)) return false;
|
||||
// Retained native chat stays world-owned. Only a newly supplied fallback
|
||||
// belongs to this replacement mode's replication node.
|
||||
if (ownsChat && !Parent(GetGame().GetChat(), mode)) return false;
|
||||
SCR_DelegateFactionManagerComponent manager = SCR_DelegateFactionManagerComponent.GetInstance();
|
||||
if (!manager) return false;
|
||||
map<Faction, SCR_EditableFactionComponent> delegates = new map<Faction, SCR_EditableFactionComponent>();
|
||||
|
||||
Reference in New Issue
Block a user