Show Escape mission text after terrain takeover; record Workshop 0.0.135
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-10-31 15:52:27 +01:00
parent 2c2158702d
commit 0e1e7790f9
10 changed files with 972 additions and 33 deletions
@@ -63,6 +63,18 @@ class ERR_TerrainDisplayName
}
}
// Keep the authored Escape header as the source of mission text.
class ERR_TerrainMissionText
{
static bool Load(out string description, out string details)
{
Resource resource = BaseContainerTools.LoadContainer("{C1E20667DCE324ED}Missions/ERR_Everon.conf");
if (!resource || !resource.IsValid()) return false;
BaseContainer header = resource.GetResource().ToBaseContainer();
return header && header.Get("m_sDescription", description) && header.Get("m_sDetails", details);
}
}
// Scenario selection still loads the terrain's header. Advertise the configured
// Escape mode through the native DS name callback, then update local metadata
// only when the authority actually starts Escape or its bootstrap reaches a client.
@@ -71,6 +83,9 @@ modded class ArmaReforgerScripted
protected ref SCR_MissionHeader m_ERRPresentedTerrainHeader;
protected string m_ERROriginalTerrainTitle;
protected string m_ERROriginalTerrainGameMode;
protected string m_ERROriginalTerrainDescription, m_ERROriginalTerrainDetails;
protected string m_ERRAppliedTerrainDescription, m_ERRAppliedTerrainDetails;
protected bool m_ERRTerrainTextApplied;
protected string m_ERRAppliedTerrainTitle;
protected string m_ERRTitleWorld;
protected string m_ERRTerrainLabel;
@@ -131,6 +146,14 @@ modded class ArmaReforgerScripted
m_ERRAppliedTerrainTitle = ERR_TerrainMissionTitle(header);
header.m_sName = m_ERRAppliedTerrainTitle;
header.m_sGameMode = "Escape";
m_ERROriginalTerrainDescription = header.m_sDescription;
m_ERROriginalTerrainDetails = header.m_sDetails;
m_ERRTerrainTextApplied = ERR_TerrainMissionText.Load(m_ERRAppliedTerrainDescription, m_ERRAppliedTerrainDetails);
if (m_ERRTerrainTextApplied)
{
header.m_sDescription = m_ERRAppliedTerrainDescription;
header.m_sDetails = m_ERRAppliedTerrainDetails;
}
PrintFormat("Reintroduced [terrain presentation]: mission=%1; source scenario=%2", header.m_sName, header.GetHeaderResourceName());
}
@@ -145,17 +168,30 @@ modded class ArmaReforgerScripted
PrintFormat("Reintroduced [terrain presentation]: refreshed mission=%1; loaded world=%2", title, GetWorldFile());
}
SCR_MissionHeader ERR_TerrainLoadingHeader(SCR_MissionHeader requested)
{
if (!requested) return null;
SCR_MissionHeader header = SCR_MissionHeader.Cast(GetMissionHeader());
// A loading screen may hold a copy. Only replace the confirmed scenario;
// another incoming map must never inherit the outgoing world's text.
if (!header || header != m_ERRPresentedTerrainHeader || m_ERRPresentedTerrainWorld != GetWorld()) return requested;
if (requested != header && (requested.GetHeaderResourceName().IsEmpty() || requested.GetHeaderResourceName() != header.GetHeaderResourceName())) return requested;
ERR_RefreshTerrainPresentation();
return header;
}
string ERR_TerrainLoadingTitle(SCR_MissionHeader requested)
{
if (!requested) return "";
SCR_MissionHeader header = SCR_MissionHeader.Cast(GetMissionHeader());
// The loading screen can hold a separate copy of the same scenario header.
// Never replace another incoming scenario's title with the outgoing world.
if (!header || header != m_ERRPresentedTerrainHeader || m_ERRPresentedTerrainWorld != GetWorld()) return requested.m_sName;
if (requested != header && (requested.GetHeaderResourceName().IsEmpty() || requested.GetHeaderResourceName() != header.GetHeaderResourceName())) return requested.m_sName;
ERR_RefreshTerrainPresentation();
SCR_MissionHeader header = ERR_TerrainLoadingHeader(requested);
if (!header) return "";
return header.m_sName;
}
string ERR_TerrainLoadingDescription(SCR_MissionHeader requested)
{
SCR_MissionHeader header = ERR_TerrainLoadingHeader(requested);
if (!header) return "";
if (!header.m_sDetails.IsEmpty()) return header.m_sDetails;
return header.m_sDescription;
}
override void OnUpdate(BaseWorld world, float timeslice)
{
@@ -173,6 +209,11 @@ modded class ArmaReforgerScripted
{
// A later change by another system belongs to that system.
if (m_ERRPresentedTerrainHeader.m_sName == m_ERRAppliedTerrainTitle) m_ERRPresentedTerrainHeader.m_sName = m_ERROriginalTerrainTitle;
if (m_ERRTerrainTextApplied)
{
if (m_ERRPresentedTerrainHeader.m_sDescription == m_ERRAppliedTerrainDescription) m_ERRPresentedTerrainHeader.m_sDescription = m_ERROriginalTerrainDescription;
if (m_ERRPresentedTerrainHeader.m_sDetails == m_ERRAppliedTerrainDetails) m_ERRPresentedTerrainHeader.m_sDetails = m_ERROriginalTerrainDetails;
}
if (m_ERRPresentedTerrainHeader.m_sGameMode == "Escape") m_ERRPresentedTerrainHeader.m_sGameMode = m_ERROriginalTerrainGameMode;
}
m_ERRPresentedTerrainHeader = null;
@@ -180,6 +221,9 @@ modded class ArmaReforgerScripted
m_ERROriginalTerrainTitle = "";
m_ERROriginalTerrainGameMode = "";
m_ERRAppliedTerrainTitle = "";
m_ERRTerrainTextApplied = false;
m_ERROriginalTerrainDescription = ""; m_ERROriginalTerrainDetails = "";
m_ERRAppliedTerrainDescription = ""; m_ERRAppliedTerrainDetails = "";
}
override protected void OnBeforeWorldCleanup()
@@ -191,27 +235,37 @@ modded class ArmaReforgerScripted
}
// Vanilla copies the header title once, before the replicated Escape bootstrap
// may arrive. Refresh only the title; do not recreate loading widgets/hints.
// may arrive. Refresh text in existing widgets; do not recreate widgets/hints.
modded class SCR_LoadingScreenComponent
{
protected ref SCR_MissionHeader m_ERRLoadingTerrainHeader;
protected string m_ERRLoadingTerrainTitle;
protected string m_ERRLoadingTerrainTitle, m_ERRLoadingTerrainDescription;
protected float m_ERRLoadingTerrainWait;
override void OnMissionDataRetrieved(SCR_MissionHeader header)
{
super.OnMissionDataRetrieved(header);
m_ERRLoadingTerrainHeader = header;
m_ERRLoadingTerrainTitle = ""; m_ERRLoadingTerrainWait = 0;
m_ERRLoadingTerrainTitle = ""; m_ERRLoadingTerrainDescription = ""; m_ERRLoadingTerrainWait = 0;
ERR_RefreshLoadingTerrainTitle();
}
protected void ERR_RefreshLoadingTerrainTitle()
{
if (!m_ERRLoadingTerrainHeader || !m_Widgets || !m_Widgets.m_wTitle || !GetGame()) return;
if (!m_ERRLoadingTerrainHeader || !m_Widgets || !GetGame()) return;
string title = GetGame().ERR_TerrainLoadingTitle(m_ERRLoadingTerrainHeader);
if (title == m_ERRLoadingTerrainTitle) return;
m_ERRLoadingTerrainTitle = title;
m_Widgets.m_wTitle.SetText(title);
if (m_Widgets.m_wTitle && title != m_ERRLoadingTerrainTitle)
{
m_ERRLoadingTerrainTitle = title;
m_Widgets.m_wTitle.SetText(title);
}
// Match vanilla details/description precedence, translation and length limit.
string description = WidgetManager.Translate(GetGame().ERR_TerrainLoadingDescription(m_ERRLoadingTerrainHeader));
if (description.Length() > MAX_DESCRIPTION_LENGTH) description = description.Substring(0, MAX_DESCRIPTION_LENGTH) + "...";
if (m_Widgets.m_wDescription && description != m_ERRLoadingTerrainDescription)
{
m_ERRLoadingTerrainDescription = description;
m_Widgets.m_wDescription.SetText(description);
}
}
override void Update(float timeSlice, float progress = 0, float minDurationRatio = 0)
{