Add configurable anonymous site markers and record Workshop 117
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
+5
-1
@@ -1,6 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
Latest published Workshop version: **0.0.115**
|
Latest published Workshop version: **0.0.117**
|
||||||
|
|
||||||
|
## 2026-10-20 — Optional site map hints
|
||||||
|
|
||||||
|
- Added an Intel menu option to show sites as question marks until intel identifies their types.
|
||||||
|
|
||||||
## 2026-10-20 — Safe intel cleanup
|
## 2026-10-20 — Safe intel cleanup
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
|||||||
m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
|
m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
|
||||||
m_Mode = ERR_GameMode.Cast(GetGame().GetGameMode());
|
m_Mode = ERR_GameMode.Cast(GetGame().GetGameMode());
|
||||||
if (!m_Controller) { Close(); return; }
|
if (!m_Controller) { Close(); return; }
|
||||||
array<string> names = {"PlaneOn", "PlaneOff", "Close", "PauseJournal", "JournalDetails", "LatestJournal", "KeepWeaponOn", "KeepWeaponOff", "SelfEpiOn", "SelfEpiOff", "IntelSummary", "RerollIntel", "RandomDay_startTimeMinutes", "Default_viewDistanceMetres", "RestartEmptyOn", "RestartEmptyOff", "RecommendedPlane", "RecommendedWeapons"};
|
array<string> names = {"SitesOn", "SitesOff", "PlaneOn", "PlaneOff", "Close", "PauseJournal", "JournalDetails", "LatestJournal", "KeepWeaponOn", "KeepWeaponOff", "SelfEpiOn", "SelfEpiOff", "IntelSummary", "RerollIntel", "RandomDay_startTimeMinutes", "Default_viewDistanceMetres", "RestartEmptyOn", "RestartEmptyOff", "RecommendedPlane", "RecommendedWeapons"};
|
||||||
foreach (string mainButton : ERR_AdminMenuPages.MainButtons()) names.Insert(mainButton);
|
foreach (string mainButton : ERR_AdminMenuPages.MainButtons()) names.Insert(mainButton);
|
||||||
foreach (string pageButton : Navigation()) names.Insert(pageButton);
|
foreach (string pageButton : Navigation()) names.Insert(pageButton);
|
||||||
for (int density = 1; density <= 4; density++) names.Insert("GuardEvery_" + density.ToString());
|
for (int density = 1; density <= 4; density++) names.Insert("GuardEvery_" + density.ToString());
|
||||||
@@ -154,9 +154,11 @@ class ERR_AdminMenu : ChimeraMenuBase
|
|||||||
}
|
}
|
||||||
protected int m_KeepWeaponState = -1;
|
protected int m_KeepWeaponState = -1;
|
||||||
protected int m_SelfEpiState = -1;
|
protected int m_SelfEpiState = -1;
|
||||||
|
protected int m_SitesState = -1;
|
||||||
protected int m_RestartEmptyState = -1;
|
protected int m_RestartEmptyState = -1;
|
||||||
protected void UpdateActions()
|
protected void UpdateActions()
|
||||||
{
|
{
|
||||||
|
ERR_SelectionStyle.Pair(GetRootWidget(), "SitesOn", "SitesOff", m_SitesState);
|
||||||
ERR_SelectionStyle.Pair(GetRootWidget(), "SelfEpiOn", "SelfEpiOff", m_SelfEpiState);
|
ERR_SelectionStyle.Pair(GetRootWidget(), "SelfEpiOn", "SelfEpiOff", m_SelfEpiState);
|
||||||
ERR_SelectionStyle.Pair(GetRootWidget(), "KeepWeaponOn", "KeepWeaponOff", m_KeepWeaponState);
|
ERR_SelectionStyle.Pair(GetRootWidget(), "KeepWeaponOn", "KeepWeaponOff", m_KeepWeaponState);
|
||||||
ERR_SelectionStyle.Pair(GetRootWidget(), "RestartEmptyOn", "RestartEmptyOff", m_RestartEmptyState);
|
ERR_SelectionStyle.Pair(GetRootWidget(), "RestartEmptyOn", "RestartEmptyOff", m_RestartEmptyState);
|
||||||
@@ -176,6 +178,8 @@ class ERR_AdminMenu : ChimeraMenuBase
|
|||||||
else if (name == "LatestJournal") button.SetEnabled(m_Ready && m_HQ);
|
else if (name == "LatestJournal") button.SetEnabled(m_Ready && m_HQ);
|
||||||
else if (name == "RestartEmptyOn") button.SetEnabled(m_Ready && m_RestartEmptyState == 0);
|
else if (name == "RestartEmptyOn") button.SetEnabled(m_Ready && m_RestartEmptyState == 0);
|
||||||
else if (name == "RestartEmptyOff") button.SetEnabled(m_Ready && m_RestartEmptyState == 1);
|
else if (name == "RestartEmptyOff") button.SetEnabled(m_Ready && m_RestartEmptyState == 1);
|
||||||
|
else if (name == "SitesOn") button.SetEnabled(m_Ready && m_SitesState == 0);
|
||||||
|
else if (name == "SitesOff") button.SetEnabled(m_Ready && m_SitesState == 1);
|
||||||
else if (name == "SelfEpiOn") button.SetEnabled(m_Ready && m_SelfEpiState == 0);
|
else if (name == "SelfEpiOn") button.SetEnabled(m_Ready && m_SelfEpiState == 0);
|
||||||
else if (name == "SelfEpiOff") button.SetEnabled(m_Ready && m_SelfEpiState == 1);
|
else if (name == "SelfEpiOff") button.SetEnabled(m_Ready && m_SelfEpiState == 1);
|
||||||
else if (name == "KeepWeaponOn") button.SetEnabled(m_Ready && m_KeepWeaponState == 0);
|
else if (name == "KeepWeaponOn") button.SetEnabled(m_Ready && m_KeepWeaponState == 0);
|
||||||
@@ -230,6 +234,11 @@ class ERR_AdminMenu : ChimeraMenuBase
|
|||||||
SetText("Saved_restartOnEmpty", "Saved: " + restartState);
|
SetText("Saved_restartOnEmpty", "Saved: " + restartState);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (key == "showAllSites")
|
||||||
|
{
|
||||||
|
m_SitesState = entry.Substring(divider + 1, entry.Length() - divider - 1).ToInt();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (key == "selfEpinephrine")
|
if (key == "selfEpinephrine")
|
||||||
{
|
{
|
||||||
m_SelfEpiState = entry.Substring(divider + 1, entry.Length() - divider - 1).ToInt();
|
m_SelfEpiState = entry.Substring(divider + 1, entry.Length() - divider - 1).ToInt();
|
||||||
@@ -387,6 +396,13 @@ class ERR_AdminMenu : ChimeraMenuBase
|
|||||||
m_ClickDelay = 0.3; SetText("Feedback", "Saving restart after last disconnect...");
|
m_ClickDelay = 0.3; SetText("Feedback", "Saving restart after last disconnect...");
|
||||||
m_Controller.ERR_AdminSubmit("mission restartempty set " + restartEnabled, true); return;
|
m_Controller.ERR_AdminSubmit("mission restartempty set " + restartEnabled, true); return;
|
||||||
}
|
}
|
||||||
|
if (name == "SitesOn" || name == "SitesOff")
|
||||||
|
{
|
||||||
|
if (m_SitesState < 0) return;
|
||||||
|
string sitesEnabled = "0"; if (name == "SitesOn") sitesEnabled = "1";
|
||||||
|
m_ClickDelay = 0.3; SetText("Feedback", "Saving site map visibility...");
|
||||||
|
m_Controller.ERR_AdminSubmit("intel sites set " + sitesEnabled, true); return;
|
||||||
|
}
|
||||||
if (name == "SelfEpiOn" || name == "SelfEpiOff")
|
if (name == "SelfEpiOn" || name == "SelfEpiOff")
|
||||||
{
|
{
|
||||||
if (m_SelfEpiState < 0) return;
|
if (m_SelfEpiState < 0) return;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class ERR_CommandArguments
|
|||||||
if (section == "mission" && option == "restartempty") return "restartOnEmpty";
|
if (section == "mission" && option == "restartempty") return "restartOnEmpty";
|
||||||
if (section == "mission" && option == "emptyhours") return "emptyRestartHours";
|
if (section == "mission" && option == "emptyhours") return "emptyRestartHours";
|
||||||
if (section == "mission" && option == "radio") return "radioDefenceSeconds";
|
if (section == "mission" && option == "radio") return "radioDefenceSeconds";
|
||||||
|
if (section == "intel" && option == "sites") return "showAllSites";
|
||||||
if (section == "intel" && option == "reveal") return "intelRevealChancePercent";
|
if (section == "intel" && option == "reveal") return "intelRevealChancePercent";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -35,8 +36,8 @@ class ERR_CommandArguments
|
|||||||
{
|
{
|
||||||
if (key == "aiDoctrine" && text == "current") { value = 0; return true; }
|
if (key == "aiDoctrine" && text == "current") { value = 0; return true; }
|
||||||
if (key == "aiDoctrine" && text == "coordinated") { value = 1; return true; }
|
if (key == "aiDoctrine" && text == "coordinated") { value = 1; return true; }
|
||||||
if ((key == "aiShadow" || key == "restartOnEmpty") && text == "off") { value = 0; return true; }
|
if ((key == "aiShadow" || key == "restartOnEmpty" || key == "showAllSites") && text == "off") { value = 0; return true; }
|
||||||
if ((key == "aiShadow" || key == "restartOnEmpty") && text == "on") { value = 1; return true; }
|
if ((key == "aiShadow" || key == "restartOnEmpty" || key == "showAllSites") && text == "on") { value = 1; return true; }
|
||||||
if (key == "startMode" && text == "prison") { value = 0; return true; }
|
if (key == "startMode" && text == "prison") { value = 0; return true; }
|
||||||
if (key == "startMode" && text == "crash") { value = 1; return true; }
|
if (key == "startMode" && text == "crash") { value = 1; return true; }
|
||||||
if (text == "random" && ERR_Settings.Randomizable(key)) { value = -1; return true; }
|
if (text == "random" && ERR_Settings.Randomizable(key)) { value = -1; return true; }
|
||||||
@@ -187,12 +188,13 @@ class ERR_AdminService
|
|||||||
if (key == "restartOnEmpty") return "On (1) restarts after the last disconnect; Off (0) preserves the round for reconnects. Default On. Applies immediately; normal round endings still apply.";
|
if (key == "restartOnEmpty") return "On (1) restarts after the last disconnect; Off (0) preserves the round for reconnects. Default On. Applies immediately; normal round endings still apply.";
|
||||||
if (key == "emptyRestartHours") return "0 disables idle restarts; 1..168 real hours continuously empty. Default 5. Applies immediately, measured from mission start or the last disconnect. Connected players, including spectators, prevent idle restarts.";
|
if (key == "emptyRestartHours") return "0 disables idle restarts; 1..168 real hours continuously empty. Default 5. Applies immediately, measured from mission start or the last disconnect. Connected players, including spectators, prevent idle restarts.";
|
||||||
if (key == "civilianTrafficCount") return "Set 0..6 civilian cars (default 3). Zero disables new traffic. Unclaimed cars retire only far from all players and out of sight; player-entered cars are preserved.";
|
if (key == "civilianTrafficCount") return "Set 0..6 civilian cars (default 3). Zero disables new traffic. Unclaimed cars retire only far from all players and out of sight; player-entered cars are preserved.";
|
||||||
|
if (key == "showAllSites") return "0 disabled (default), 1 enabled. Show prepared sites at their positions as question marks; recovered intel identifies their types. Applies immediately to everyone.";
|
||||||
if (key == "selfEpinephrine") return "0 disabled (default), 1 enabled. Unconscious players can press Space to use a carried epinephrine injector. Applies immediately; consumes the item and keeps its normal medical effect.";
|
if (key == "selfEpinephrine") return "0 disabled (default), 1 enabled. Unconscious players can press Space to use a carried epinephrine injector. Applies immediately; consumes the item and keeps its normal medical effect.";
|
||||||
if (key == "keepWeaponOnUnconscious") return "Set 1 to retain the held firearm during unconsciousness and equip it after recovery; 0 keeps normal dropping. Applies to the next knockout.";
|
if (key == "keepWeaponOnUnconscious") return "Set 1 to retain the held firearm during unconsciousness and equip it after recovery; 0 keeps normal dropping. Applies to the next knockout.";
|
||||||
if (key == "antiAirChancePercent" || key == "antiPersonnelMineChancePercent")
|
if (key == "antiAirChancePercent" || key == "antiPersonnelMineChancePercent")
|
||||||
return "Set 0..100 percent or Random. Applies to newly equipped enemy soldiers; existing loadouts are not rerolled or replenished.";
|
return "Set 0..100 percent or Random. Applies to newly equipped enemy soldiers; existing loadouts are not rerolled or replenished.";
|
||||||
if (key == "intelRevealChancePercent")
|
if (key == "intelRevealChancePercent")
|
||||||
return "Use /esc intel reveal set N (0-100) or random. This is the chance that a first document identifies its location exactly; otherwise it gives a rough location. A second document for that location always identifies it. Changes affect newly recovered documents immediately; known locations and spent documents remain unchanged.";
|
return "Use /esc intel reveal set N (0-100) or random. This is the chance that a first document identifies its location exactly; otherwise it gives a rough location. A second document for that location always identifies it. With all sites shown, the first document always identifies the type. Changes affect newly recovered documents immediately; known locations and spent documents remain unchanged.";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
protected string RoadblockTiming(string key)
|
protected string RoadblockTiming(string key)
|
||||||
@@ -240,6 +242,7 @@ class ERR_AdminService
|
|||||||
}
|
}
|
||||||
if (topic == "intel")
|
if (topic == "intel")
|
||||||
{
|
{
|
||||||
|
replies.Insert("/esc intel sites show|set on|off; show anonymous site positions and let intel identify their types.");
|
||||||
replies.Insert("/esc intel reveal show|set N|help (0-100); affects newly recovered documents immediately.");
|
replies.Insert("/esc intel reveal show|set N|help (0-100); affects newly recovered documents immediately.");
|
||||||
replies.Insert("AI carrying and reroll commands require the Intel addon.");
|
replies.Insert("AI carrying and reroll commands require the Intel addon.");
|
||||||
return;
|
return;
|
||||||
@@ -329,6 +332,7 @@ class ERR_AdminService
|
|||||||
if (!key.IsEmpty())
|
if (!key.IsEmpty())
|
||||||
{
|
{
|
||||||
SettingCommand(mode.Settings(), key, parts, replies);
|
SettingCommand(mode.Settings(), key, parts, replies);
|
||||||
|
if (key == "showAllSites") mode.PublishSiteVisibility();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
// A first clue identifies a stable search square, not the exact objective.
|
// Normal clues use stable search squares to prevent triangulating the site.
|
||||||
// Stable grid centers prevent repeated updates from triangulating the site.
|
// The optional anonymous-site mode intentionally exposes positions, never types.
|
||||||
class ERR_DiscoveryMapRules
|
class ERR_DiscoveryMapRules
|
||||||
{
|
{
|
||||||
|
// -1 hidden, 0 anonymous exact position, 1 approximate clue, 2 identified.
|
||||||
|
static int DisplayKnowledge(int knowledge, bool prepared, bool prison, bool showAll)
|
||||||
|
{
|
||||||
|
if (prison || !prepared) return -1;
|
||||||
|
if (knowledge >= 2) return 2;
|
||||||
|
if (showAll) return 0;
|
||||||
|
if (knowledge == 1) return 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
static int Coordinate(float coordinate, int knowledge)
|
static int Coordinate(float coordinate, int knowledge)
|
||||||
{
|
{
|
||||||
if (knowledge >= 2) return Math.Round(coordinate);
|
if (knowledge == 0 || knowledge >= 2) return Math.Round(coordinate);
|
||||||
return Math.Floor(coordinate / 500.0) * 500 + 250;
|
return Math.Floor(coordinate / 500.0) * 500 + 250;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,12 +118,12 @@ modded class SCR_MapMarkerManagerComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read replicated discovery locally. A server-wide marker list never leaks
|
// Read replicated discovery and the administrator-selected visibility locally.
|
||||||
// locations which have not been recovered through gameplay.
|
// Anonymous markers never expose a site label or type before discovery.
|
||||||
modded class ERR_LocationComponent
|
modded class ERR_LocationComponent
|
||||||
{
|
{
|
||||||
protected ref ERR_DiscoveryMarker m_ERRMarker;
|
protected ref ERR_DiscoveryMarker m_ERRMarker;
|
||||||
protected int m_ERRShown;
|
protected int m_ERRShown = -1;
|
||||||
protected string m_ERRShownLabel;
|
protected string m_ERRShownLabel;
|
||||||
|
|
||||||
protected override void EOnInit(IEntity owner)
|
protected override void EOnInit(IEntity owner)
|
||||||
@@ -126,20 +135,24 @@ modded class ERR_LocationComponent
|
|||||||
protected void ERR_UpdateMarker()
|
protected void ERR_UpdateMarker()
|
||||||
{
|
{
|
||||||
if (!GetGame().GetPlayerController()) return;
|
if (!GetGame().GetPlayerController()) return;
|
||||||
if (Kind() == ERR_LocationKind.PRISON || Knowledge() < 1)
|
ERR_GameMode mode = ERR_GameMode.Get();
|
||||||
|
bool showAll = mode && mode.ShowAllSites();
|
||||||
|
int shown = ERR_DiscoveryMapRules.DisplayKnowledge(Knowledge(), Prepared(), Kind() == ERR_LocationKind.PRISON, showAll);
|
||||||
|
if (shown < 0)
|
||||||
{
|
{
|
||||||
SCR_MapMarkerManagerComponent oldManager = SCR_MapMarkerManagerComponent.GetInstance();
|
SCR_MapMarkerManagerComponent oldManager = SCR_MapMarkerManagerComponent.GetInstance();
|
||||||
if (m_ERRMarker && oldManager) oldManager.ERR_RemoveDiscoveryMarker(m_ERRMarker);
|
if (m_ERRMarker && oldManager) oldManager.ERR_RemoveDiscoveryMarker(m_ERRMarker);
|
||||||
else if (m_ERRMarker) m_ERRMarker.OnDelete();
|
else if (m_ERRMarker) m_ERRMarker.OnDelete();
|
||||||
m_ERRMarker = null; m_ERRShown = 0; m_ERRShownLabel = "";
|
m_ERRMarker = null; m_ERRShown = -1; m_ERRShownLabel = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_ERRMarker) m_ERRMarker.RefreshPresentation();
|
if (m_ERRMarker) m_ERRMarker.RefreshPresentation();
|
||||||
if (Knowledge() == m_ERRShown && Label() == m_ERRShownLabel) return;
|
if (m_ERRMarker && shown == m_ERRShown && Label() == m_ERRShownLabel) return;
|
||||||
SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance();
|
SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance();
|
||||||
if (!manager || !manager.GetMarkerConfig()) return;
|
if (!manager || !manager.GetMarkerConfig()) return;
|
||||||
string label = "Unknown location (500 m area)";
|
string label = "Unknown location (500 m area)";
|
||||||
if (Knowledge() == 2)
|
if (shown == 0) label = "Unknown site";
|
||||||
|
if (shown == 2)
|
||||||
{
|
{
|
||||||
if (!Label().IsEmpty()) label = Label();
|
if (!Label().IsEmpty()) label = Label();
|
||||||
else if (Kind() == ERR_LocationKind.RADIO) label = "Radio station";
|
else if (Kind() == ERR_LocationKind.RADIO) label = "Radio station";
|
||||||
@@ -152,18 +165,18 @@ modded class ERR_LocationComponent
|
|||||||
{
|
{
|
||||||
m_ERRMarker = new ERR_DiscoveryMarker();
|
m_ERRMarker = new ERR_DiscoveryMarker();
|
||||||
m_ERRMarker.SetType(SCR_EMapMarkerType.PLACED_CUSTOM);
|
m_ERRMarker.SetType(SCR_EMapMarkerType.PLACED_CUSTOM);
|
||||||
m_ERRMarker.SetDiscoveryPosition(Position(), Knowledge());
|
m_ERRMarker.SetDiscoveryPosition(Position(), shown);
|
||||||
m_ERRMarker.SetMarkerConfigID(0);
|
m_ERRMarker.SetMarkerConfigID(0);
|
||||||
m_ERRMarker.SetLocationIcon(Kind(), Id(), Knowledge());
|
m_ERRMarker.SetLocationIcon(Kind(), Id(), shown);
|
||||||
m_ERRMarker.SetCustomText(label);
|
m_ERRMarker.SetCustomText(label);
|
||||||
manager.ERR_InsertDiscoveryMarker(m_ERRMarker);
|
manager.ERR_InsertDiscoveryMarker(m_ERRMarker);
|
||||||
}
|
}
|
||||||
m_ERRMarker.SetDiscoveryPosition(Position(), Knowledge());
|
m_ERRMarker.SetDiscoveryPosition(Position(), shown);
|
||||||
m_ERRMarker.SetLocationIcon(Kind(), Id(), Knowledge());
|
m_ERRMarker.SetLocationIcon(Kind(), Id(), shown);
|
||||||
m_ERRMarker.SetCustomText(label);
|
m_ERRMarker.SetCustomText(label);
|
||||||
// The objective presentation performs its own normal viewport culling.
|
// The objective presentation performs its own normal viewport culling.
|
||||||
m_ERRMarker.RefreshPresentation();
|
m_ERRMarker.RefreshPresentation();
|
||||||
m_ERRShown = Knowledge();
|
m_ERRShown = shown;
|
||||||
m_ERRShownLabel = Label();
|
m_ERRShownLabel = Label();
|
||||||
}
|
}
|
||||||
protected override void OnDelete(IEntity owner)
|
protected override void OnDelete(IEntity owner)
|
||||||
|
|||||||
@@ -26,6 +26,16 @@ class ERR_GameMode : SCR_BaseGameMode
|
|||||||
m_SelectedPlayerFaction = player; m_SelectedEnemyFaction = enemy; Replication.BumpMe();
|
m_SelectedPlayerFaction = player; m_SelectedEnemyFaction = enemy; Replication.BumpMe();
|
||||||
}
|
}
|
||||||
protected ref ERR_Settings m_Settings;
|
protected ref ERR_Settings m_Settings;
|
||||||
|
[RplProp()] protected bool m_ShowAllSites;
|
||||||
|
bool ShowAllSites() { return m_ShowAllSites; }
|
||||||
|
void PublishSiteVisibility()
|
||||||
|
{
|
||||||
|
if (!Replication.IsServer() || !m_Settings || m_Stopped || m_NativeEndHandled) return;
|
||||||
|
bool enabled = m_Settings.Get("showAllSites") == 1;
|
||||||
|
if (m_ShowAllSites == enabled) return;
|
||||||
|
m_ShowAllSites = enabled;
|
||||||
|
Replication.BumpMe();
|
||||||
|
}
|
||||||
[RplProp()] protected int m_StartMode;
|
[RplProp()] protected int m_StartMode;
|
||||||
protected bool m_StartModeFrozen;
|
protected bool m_StartModeFrozen;
|
||||||
protected bool m_StartPrepared;
|
protected bool m_StartPrepared;
|
||||||
@@ -498,6 +508,7 @@ class ERR_GameMode : SCR_BaseGameMode
|
|||||||
if (!Replication.IsServer()) return;
|
if (!Replication.IsServer()) return;
|
||||||
m_EmptySince = System.GetTickCount();
|
m_EmptySince = System.GetTickCount();
|
||||||
m_Settings = new ERR_Settings(SettingsPath());
|
m_Settings = new ERR_Settings(SettingsPath());
|
||||||
|
PublishSiteVisibility();
|
||||||
if (!System.IsCLIParam("errNoPerf")) m_Performance = new ERR_Performance();
|
if (!System.IsCLIParam("errNoPerf")) m_Performance = new ERR_Performance();
|
||||||
PublishViewDistance();
|
PublishViewDistance();
|
||||||
m_ContentSettings = new ERR_ContentSettings();
|
m_ContentSettings = new ERR_ContentSettings();
|
||||||
|
|||||||
@@ -50,10 +50,11 @@ class ERR_LocationComponent : ScriptComponent
|
|||||||
bool Discover(int roll, int chance)
|
bool Discover(int roll, int chance)
|
||||||
{
|
{
|
||||||
if (!Replication.IsServer() || !m_Prepared || m_Knowledge >= 2) return false;
|
if (!Replication.IsServer() || !m_Prepared || m_Knowledge >= 2) return false;
|
||||||
|
ERR_GameMode mode = ERR_GameMode.Get();
|
||||||
|
if (mode && mode.ShowAllSites()) chance = 100;
|
||||||
int previous = m_Knowledge;
|
int previous = m_Knowledge;
|
||||||
m_Knowledge = ERR_MissionRules.Discovery(m_Knowledge, roll, chance);
|
m_Knowledge = ERR_MissionRules.Discovery(m_Knowledge, roll, chance);
|
||||||
Replication.BumpMe();
|
Replication.BumpMe();
|
||||||
ERR_GameMode mode = ERR_GameMode.Get();
|
|
||||||
if (mode) mode.LocationDiscovered(this, previous, m_Knowledge);
|
if (mode) mode.LocationDiscovered(this, previous, m_Knowledge);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ERR_Settings
|
|||||||
|
|
||||||
static array<string> Keys()
|
static array<string> Keys()
|
||||||
{
|
{
|
||||||
return {"aiDoctrine", "aiShadow", "sarkaAngerPerCar", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "planeReconEnabled", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "startMode", "keepWeaponOnUnconscious", "selfEpinephrine", "restartOnEmpty", "emptyRestartHours", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "antiAirChancePercent", "antiPersonnelMineChancePercent", "automaticEquipmentChancePercent", "automaticConvoyEnabled", "convoyCount", "heliTimerMinutes"};
|
return {"aiDoctrine", "aiShadow", "sarkaAngerPerCar", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "planeReconEnabled", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "startMode", "keepWeaponOnUnconscious", "selfEpinephrine", "restartOnEmpty", "emptyRestartHours", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "showAllSites", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "antiAirChancePercent", "antiPersonnelMineChancePercent", "automaticEquipmentChancePercent", "automaticConvoyEnabled", "convoyCount", "heliTimerMinutes"};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Valid(string key, int value)
|
static bool Valid(string key, int value)
|
||||||
@@ -32,6 +32,7 @@ class ERR_Settings
|
|||||||
if (key == "roadblockCount") return value >= 0 && value <= 30;
|
if (key == "roadblockCount") return value >= 0 && value <= 30;
|
||||||
if (key == "civilianTrafficCount") return value >= 0 && value <= 6;
|
if (key == "civilianTrafficCount") return value >= 0 && value <= 6;
|
||||||
if (key == "startMode") return value == 0 || value == 1;
|
if (key == "startMode") return value == 0 || value == 1;
|
||||||
|
if (key == "showAllSites") return value == 0 || value == 1;
|
||||||
if (key == "selfEpinephrine" || key == "keepWeaponOnUnconscious" || key == "restartOnEmpty") return value == 0 || value == 1;
|
if (key == "selfEpinephrine" || key == "keepWeaponOnUnconscious" || key == "restartOnEmpty") return value == 0 || value == 1;
|
||||||
if (key == "emptyRestartHours") return value >= 0 && value <= 168;
|
if (key == "emptyRestartHours") return value >= 0 && value <= 168;
|
||||||
if (key == "heliTimerMinutes") return value >= 1 && value <= 1440;
|
if (key == "heliTimerMinutes") return value >= 1 && value <= 1440;
|
||||||
@@ -134,6 +135,7 @@ class ERR_Settings
|
|||||||
if (key == "hunterSpawnDistanceMetres") return 1000;
|
if (key == "hunterSpawnDistanceMetres") return 1000;
|
||||||
if (key == "roadblockCount") return 4;
|
if (key == "roadblockCount") return 4;
|
||||||
if (key == "civilianTrafficCount") return 3;
|
if (key == "civilianTrafficCount") return 3;
|
||||||
|
if (key == "showAllSites") return 0;
|
||||||
if (key == "startMode" || key == "selfEpinephrine") return 0;
|
if (key == "startMode" || key == "selfEpinephrine") return 0;
|
||||||
if (key == "keepWeaponOnUnconscious" || key == "restartOnEmpty") return 1;
|
if (key == "keepWeaponOnUnconscious" || key == "restartOnEmpty") return 1;
|
||||||
if (key == "emptyRestartHours") return 5;
|
if (key == "emptyRestartHours") return 5;
|
||||||
@@ -180,6 +182,7 @@ class ERR_Settings
|
|||||||
m_Values.Set("responseRadiusMetres", 2000);
|
m_Values.Set("responseRadiusMetres", 2000);
|
||||||
m_Values.Set("aiIntelChancePercent", 60);
|
m_Values.Set("aiIntelChancePercent", 60);
|
||||||
m_Values.Set("intelRevealChancePercent", 15);
|
m_Values.Set("intelRevealChancePercent", 15);
|
||||||
|
m_Values.Set("showAllSites", AddedDefault("showAllSites"));
|
||||||
m_Values.Set("radioDefenceSeconds", 180);
|
m_Values.Set("radioDefenceSeconds", 180);
|
||||||
m_Values.Set("startTimeMinutes", AddedDefault("startTimeMinutes"));
|
m_Values.Set("startTimeMinutes", AddedDefault("startTimeMinutes"));
|
||||||
m_Values.Set("timeMultiplier", AddedDefault("timeMultiplier"));
|
m_Values.Set("timeMultiplier", AddedDefault("timeMultiplier"));
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class ERR_IntelAdminProvider : ERR_AdminProvider
|
|||||||
if (arguments == "intel show")
|
if (arguments == "intel show")
|
||||||
{
|
{
|
||||||
replies.Insert("aiIntelChancePercent=" + mode.Settings().Get("aiIntelChancePercent").ToString());
|
replies.Insert("aiIntelChancePercent=" + mode.Settings().Get("aiIntelChancePercent").ToString());
|
||||||
|
replies.Insert("showAllSites=" + mode.Settings().Get("showAllSites").ToString());
|
||||||
replies.Insert("intelRevealChancePercent=" + mode.Settings().Get("intelRevealChancePercent").ToString());
|
replies.Insert("intelRevealChancePercent=" + mode.Settings().Get("intelRevealChancePercent").ToString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,7 @@ class ERR_IntelAdminProvider : ERR_AdminProvider
|
|||||||
override bool Help(string topic, array<string> replies)
|
override bool Help(string topic, array<string> replies)
|
||||||
{
|
{
|
||||||
if (topic != "intel") return false;
|
if (topic != "intel") return false;
|
||||||
|
replies.Insert("/esc intel sites show|set on|off; show anonymous site positions and let intel identify their types.");
|
||||||
replies.Insert("/esc intel show | intel carrying show|set N (0-100; alias: intel chance)");
|
replies.Insert("/esc intel show | intel carrying show|set N (0-100; alias: intel chance)");
|
||||||
replies.Insert("Carrying changes affect newly registered AI. /esc intel reroll applies to eligible living AI; intel reroll show reports progress.");
|
replies.Insert("Carrying changes affect newly registered AI. /esc intel reroll applies to eligible living AI; intel reroll show reports progress.");
|
||||||
replies.Insert("/esc intel reveal show|set N|help (0-100); newly recovered documents change, known locations and spent documents remain unchanged.");
|
replies.Insert("/esc intel reveal show|set N|help (0-100); newly recovered documents change, known locations and spent documents remain unchanged.");
|
||||||
|
|||||||
@@ -630,30 +630,30 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
} }
|
} }
|
||||||
FrameWidgetClass { "Is Visible" 0 Name "IntelPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
FrameWidgetClass { "Is Visible" 0 Name "IntelPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "IntelHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 }
|
Name "IntelHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 40 OffsetBottom -46 }
|
||||||
Color 0.9 0.92 0.94 1 Text "Control how often soldiers carry intel and whether the first clue reveals an exact location." "Font Size" 19 "Min Font Size" 19 Wrap 1
|
Color 0.9 0.92 0.94 1 Text "Choose how sites appear on the map and how often soldiers carry intel." "Font Size" 19 "Min Font Size" 19 Wrap 1
|
||||||
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 80 OffsetTop 80 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -108 }
|
Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 150 OffsetTop 150 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -178 }
|
||||||
Color 0.9 0.92 0.94 1 Text "AI carrying intel (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties {
|
Color 0.9 0.92 0.94 1 Text "AI carrying intel (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties {
|
||||||
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -136 }
|
Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 194 OffsetTop 194 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -214 }
|
||||||
Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties {
|
Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties {
|
||||||
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Help_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 136 OffsetTop 136 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -156 }
|
Name "Help_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 218 OffsetTop 218 SizeX 936 OffsetRight -964 SizeY 32 OffsetBottom -250 }
|
||||||
Color 0.72 0.81 0.87 1 Text "Chance for each new enemy soldier to carry intel. Reassign carried intel updates existing soldiers." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
Color 0.72 0.81 0.87 1 Text "Chance for each new enemy soldier to carry intel. Reassign carried intel updates existing soldiers." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
||||||
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
||||||
Name "aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 80 OffsetTop 80 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -122 }
|
Name "aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 150 OffsetTop 150 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
||||||
m_sLabel ""
|
m_sLabel ""
|
||||||
@@ -661,7 +661,7 @@ ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 80 OffsetTop 80 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -122 }
|
Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 150 OffsetTop 150 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Apply"
|
m_sText "Apply"
|
||||||
@@ -669,7 +669,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Random_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 80 OffsetTop 80 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -122 }
|
Name "Random_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 150 OffsetTop 150 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Random"
|
m_sText "Random"
|
||||||
@@ -677,25 +677,25 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -196 }
|
Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 252 OffsetTop 252 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -280 }
|
||||||
Color 0.9 0.92 0.94 1 Text "First-document exact reveal (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties {
|
Color 0.9 0.92 0.94 1 Text "First-document exact reveal (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties {
|
||||||
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 200 OffsetTop 200 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -224 }
|
Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 296 OffsetTop 296 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -316 }
|
||||||
Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties {
|
Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties {
|
||||||
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Help_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 224 OffsetTop 224 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -244 }
|
Name "Help_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 320 OffsetTop 320 SizeX 936 OffsetRight -964 SizeY 36 OffsetBottom -356 }
|
||||||
Color 0.72 0.81 0.87 1 Text "First clue: chance to reveal the exact site. Otherwise a question mark shows an approximate area." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
Color 0.72 0.81 0.87 1 Text "With all sites shown, intel always identifies the type. Otherwise this chance controls exact versus approximate clues." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
||||||
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
||||||
Name "intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 168 OffsetTop 168 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -210 }
|
Name "intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 252 OffsetTop 252 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
||||||
m_sLabel ""
|
m_sLabel ""
|
||||||
@@ -703,7 +703,7 @@ ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 168 OffsetTop 168 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -210 }
|
Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 252 OffsetTop 252 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Apply"
|
m_sText "Apply"
|
||||||
@@ -711,7 +711,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Random_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 168 OffsetTop 168 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -210 }
|
Name "Random_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 252 OffsetTop 252 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Random"
|
m_sText "Random"
|
||||||
@@ -719,7 +719,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "IntelSummary" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -288 SizeY 42 OffsetBottom -318 }
|
Name "IntelSummary" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 364 OffsetTop 364 SizeX 260 OffsetRight -288 SizeY 42 OffsetBottom -406 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Intel summary"
|
m_sText "Intel summary"
|
||||||
@@ -727,7 +727,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "RerollIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 306 OffsetLeft 306 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -566 SizeY 42 OffsetBottom -318 }
|
Name "RerollIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 306 OffsetLeft 306 PositionY 364 OffsetTop 364 SizeX 260 OffsetRight -566 SizeY 42 OffsetBottom -406 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Reassign carried intel"
|
m_sText "Reassign carried intel"
|
||||||
@@ -735,15 +735,31 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "IntelRerollHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 336 OffsetTop 336 SizeX 936 OffsetRight -964 SizeY 52 OffsetBottom -388 }
|
Name "IntelRerollHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 420 OffsetTop 420 SizeX 936 OffsetRight -964 SizeY 26 OffsetBottom -446 }
|
||||||
Color 0.9 0.92 0.94 1 Text "Reassign carried intel uses the saved chance on existing AI. Intel already collected stays revealed." "Font Size" 19 "Min Font Size" 19 Wrap 1
|
Color 0.9 0.92 0.94 1 Text "Reassign carried intel updates existing AI. Collected intel stays revealed." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
||||||
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "EvidenceHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 402 OffsetTop 402 SizeX 936 OffsetRight -964 SizeY 60 OffsetBottom -462 }
|
Name "EvidenceHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 454 OffsetTop 454 SizeX 936 OffsetRight -964 SizeY 28 OffsetBottom -482 }
|
||||||
Color 0.9 0.92 0.94 1 Text "Enemy bodies stay until a recovery team searches them and reports to HQ. Cleanup is then enabled with a five-minute delay." "Font Size" 19 "Min Font Size" 19 Wrap 1
|
Color 0.9 0.92 0.94 1 Text "Enemy bodies remain until searched and reported, then become eligible for cleanup after five minutes." "Font Size" 16 "Min Font Size" 16 Wrap 1
|
||||||
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
}
|
}
|
||||||
|
TextWidgetClass {
|
||||||
|
Name "Label_showAllSites" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 58 OffsetTop 58 SizeX 550 OffsetRight -578 SizeY 32 OffsetBottom -90 }
|
||||||
|
Color 0.9 0.92 0.94 1 Text "Show all sites as question marks" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
|
}
|
||||||
|
TextWidgetClass {
|
||||||
|
Name "Help_showAllSites" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 102 OffsetTop 102 SizeX 936 OffsetRight -964 SizeY 40 OffsetBottom -142 }
|
||||||
|
Color 0.72 0.81 0.87 1 Text "Show prepared site positions without names or types. Intel identifies each site. Applies now for everyone; disabled by default." "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
|
||||||
|
}
|
||||||
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
|
Name "SitesOn" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 54 OffsetTop 54 SizeX 146 OffsetRight -806 SizeY 42 OffsetBottom -96 }
|
||||||
|
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Enabled" } }
|
||||||
|
}
|
||||||
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
|
Name "SitesOff" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 818 OffsetLeft 818 PositionY 54 OffsetTop 54 SizeX 146 OffsetRight -964 SizeY 42 OffsetBottom -96 }
|
||||||
|
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Disabled" } }
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
FrameWidgetClass { "Is Visible" 0 Name "StatusPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
FrameWidgetClass { "Is Visible" 0 Name "StatusPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ navigation = source.with_name('ERR_AdminMenuPages.c')
|
|||||||
layout = BASE / 'addons/core/UI/layouts/ERR/AdminMenu.layout'
|
layout = BASE / 'addons/core/UI/layouts/ERR/AdminMenu.layout'
|
||||||
keys = re.findall(r'"([A-Za-z]+)"', body(fields, 'static array<string> Keys('))
|
keys = re.findall(r'"([A-Za-z]+)"', body(fields, 'static array<string> Keys('))
|
||||||
settings = re.findall(r'"([A-Za-z]+)"', body(BASE / 'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c', 'static array<string> Keys('))
|
settings = re.findall(r'"([A-Za-z]+)"', body(BASE / 'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c', 'static array<string> Keys('))
|
||||||
assert len(keys) == len(set(keys)) and set(settings) - set(keys) == {"automaticConvoyEnabled", "keepWeaponOnUnconscious", "selfEpinephrine", "planeReconEnabled", "restartOnEmpty"}
|
assert len(keys) == len(set(keys)) and set(settings) - set(keys) == {"automaticConvoyEnabled", "keepWeaponOnUnconscious", "selfEpinephrine", "planeReconEnabled", "restartOnEmpty", "showAllSites"}
|
||||||
assert set(keys) <= set(settings) # Every menu field must have a server setting.
|
assert set(keys) <= set(settings) # Every menu field must have a server setting.
|
||||||
# Native layouts place child widget declarations inside an anonymous Children
|
# Native layouts place child widget declarations inside an anonymous Children
|
||||||
# block. A missing brace can preserve most widget names yet prevent menu load.
|
# block. A missing brace can preserve most widget names yet prevent menu load.
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ int main(){
|
|||||||
assert(Valid("fieldHospitalCount",1)&&Valid("fieldHospitalCount",6)&&Valid("fieldHospitalCount",8));
|
assert(Valid("fieldHospitalCount",1)&&Valid("fieldHospitalCount",6)&&Valid("fieldHospitalCount",8));
|
||||||
assert(!Valid("fieldHospitalCount",0)&&!Valid("fieldHospitalCount",9));
|
assert(!Valid("fieldHospitalCount",0)&&!Valid("fieldHospitalCount",9));
|
||||||
|
|
||||||
|
assert(CoreSetting("intel","sites")=="showAllSites");
|
||||||
|
assert(Valid("showAllSites",0)&&Valid("showAllSites",1));
|
||||||
|
assert(!Valid("showAllSites",-1)&&!Valid("showAllSites",2));
|
||||||
assert(CoreSetting("intel","reveal")=="intelRevealChancePercent");
|
assert(CoreSetting("intel","reveal")=="intelRevealChancePercent");
|
||||||
assert(CoreSetting("mission","radio")=="radioDefenceSeconds");
|
assert(CoreSetting("mission","radio")=="radioDefenceSeconds");
|
||||||
assert(CoreSetting("mission","objectguards")=="objectGuardCount");
|
assert(CoreSetting("mission","objectguards")=="objectGuardCount");
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ template<class T> struct Array:std::vector<T>{void Insert(T v){this->push_back(v
|
|||||||
template<class T> struct Set:std::set<T>{bool Contains(T v){return this->count(v);}void Insert(T v){this->insert(v);}int Count(){return this->size();}};
|
template<class T> struct Set:std::set<T>{bool Contains(T v){return this->count(v);}void Insert(T v){this->insert(v);}int Count(){return this->size();}};
|
||||||
namespace Replication { bool server=true; bool IsServer(){return server;} }
|
namespace Replication { bool server=true; bool IsServer(){return server;} }
|
||||||
struct Number {int n;string ToString(){return std::to_string(n);}};
|
struct Number {int n;string ToString(){return std::to_string(n);}};
|
||||||
struct Settings {Number Get(string key){return {key=="aiIntelChancePercent"?60:15};}};
|
struct Settings {Number Get(string key){return {key=="aiIntelChancePercent"?60:(key=="showAllSites"?0:15)};}};
|
||||||
struct Intel {int starts=0;bool canStart=true;bool BeginReroll(){starts++;return canStart;}string RerollStatus(){return "batch status";}};
|
struct Intel {int starts=0;bool canStart=true;bool BeginReroll(){starts++;return canStart;}string RerollStatus(){return "batch status";}};
|
||||||
struct Journal {int Sequence(){return 0;}void Read(int,Array<string>&,int&) {}};
|
struct Journal {int Sequence(){return 0;}void Read(int,Array<string>&,int&) {}};
|
||||||
struct HQ {struct Journal journal;static HQ* Cast(HQ* h){return h;}string Status(){return "hq";}struct Journal* Journal(){return &journal;}};
|
struct HQ {struct Journal journal;static HQ* Cast(HQ* h){return h;}string Status(){return "hq";}struct Journal* Journal(){return &journal;}};
|
||||||
@@ -40,7 +40,7 @@ struct Ledger {Set<IEntity> m_Spent;
|
|||||||
};
|
};
|
||||||
int main(){
|
int main(){
|
||||||
Admin admin;Mode mode;Array<string> replies;Intel intel;mode.intel=&intel;
|
Admin admin;Mode mode;Array<string> replies;Intel intel;mode.intel=&intel;
|
||||||
assert(admin.Extension(&mode,"intel show",replies));assert(replies.size()==2&&replies[0]=="aiIntelChancePercent=60"&&replies[1]=="intelRevealChancePercent=15"&&intel.starts==0);
|
assert(admin.Extension(&mode,"intel show",replies));assert(replies.size()==3&&replies[0]=="aiIntelChancePercent=60"&&replies[1]=="showAllSites=0"&&replies[2]=="intelRevealChancePercent=15"&&intel.starts==0);
|
||||||
replies.clear();assert(admin.Extension(&mode,"intel reroll show",replies));assert(intel.starts==0&&replies.size()==1&&replies[0]=="batch status");
|
replies.clear();assert(admin.Extension(&mode,"intel reroll show",replies));assert(intel.starts==0&&replies.size()==1&&replies[0]=="batch status");
|
||||||
replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==1&&replies.size()==1);
|
replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==1&&replies.size()==1);
|
||||||
intel.canStart=false;replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==2&&replies.size()==2&&replies[1]=="batch status");
|
intel.canStart=false;replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==2&&replies.size()==2&&replies[1]=="batch status");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from policy_harness import ROOT,body,run
|
|||||||
spec=importlib.util.spec_from_file_location('import_settings',BASE/'tools/import_settings.py')
|
spec=importlib.util.spec_from_file_location('import_settings',BASE/'tools/import_settings.py')
|
||||||
m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
|
m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
|
||||||
result,deferred=m.merge({'configVersion':1,'reportIntervalSeconds':20.0,'supportSquadLimit':2,'responseRadiusMetres':1500,'convoyCount':3},{'aiIntelChancePercent':0,'intelRevealChancePercent':100})
|
result,deferred=m.merge({'configVersion':1,'reportIntervalSeconds':20.0,'supportSquadLimit':2,'responseRadiusMetres':1500,'convoyCount':3},{'aiIntelChancePercent':0,'intelRevealChancePercent':100})
|
||||||
assert result==dict(aiDoctrine=0,aiShadow=0,planeAltitudeMetres=250,planeReplacementSeconds=60,planeSectorSeconds=120,planeReconEnabled=1,roadblockCount=4,civilianTrafficCount=3,startMode=0,keepWeaponOnUnconscious=1,selfEpinephrine=0,restartOnEmpty=1,emptyRestartHours=5,reportIntervalSeconds=20,supportSquadLimit=2,responseRadiusMetres=1500,aiIntelChancePercent=0,intelRevealChancePercent=100,radioDefenceSeconds=180,startTimeMinutes=840,timeMultiplier=1,startDateCode=0,weatherProfile=0,viewDistanceMetres=0,automaticEquipmentChancePercent=25,antiAirChancePercent=7,antiPersonnelMineChancePercent=60,automaticConvoyEnabled=1,convoyCount=3,heliTimerMinutes=15)
|
assert result==dict(aiDoctrine=0,aiShadow=0,planeAltitudeMetres=250,planeReplacementSeconds=60,planeSectorSeconds=120,planeReconEnabled=1,roadblockCount=4,civilianTrafficCount=3,startMode=0,keepWeaponOnUnconscious=1,selfEpinephrine=0,restartOnEmpty=1,emptyRestartHours=5,reportIntervalSeconds=20,supportSquadLimit=2,responseRadiusMetres=1500,aiIntelChancePercent=0,intelRevealChancePercent=100,showAllSites=0,radioDefenceSeconds=180,startTimeMinutes=840,timeMultiplier=1,startDateCode=0,weatherProfile=0,viewDistanceMetres=0,automaticEquipmentChancePercent=25,antiAirChancePercent=7,antiPersonnelMineChancePercent=60,automaticConvoyEnabled=1,convoyCount=3,heliTimerMinutes=15)
|
||||||
assert deferred==[]
|
assert deferred==[]
|
||||||
for count in (0,1,3,20):
|
for count in (0,1,3,20):
|
||||||
values,notes=m.merge(ai={'convoyCount':count})
|
values,notes=m.merge(ai={'convoyCount':count})
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
"""Run production marker transitions and discovery with engine boundary doubles."""
|
||||||
|
from policy_harness import ROOT, body, run
|
||||||
|
base = ROOT/'addons/core/Scripts/Game/ERR/00_Core'
|
||||||
|
map_source = base/'ERR_DiscoveryMap.c'
|
||||||
|
rules = '\n'.join(body(map_source, s) for s in ('static int DisplayKnowledge(', 'static int Coordinate(')).replace('Math.Round','std::round').replace('Math.Floor','std::floor')
|
||||||
|
update = body(map_source, 'protected void ERR_UpdateMarker(').replace('protected ', '')
|
||||||
|
discover = body(base/'ERR_Location.c', 'bool Discover(')
|
||||||
|
icon = body(map_source, 'void SetLocationIcon(')
|
||||||
|
for name in ('ERR_GameMode', 'SCR_MapMarkerManagerComponent', 'ERR_DiscoveryMapRules', 'ERR_LocationKind', 'SCR_EMapMarkerType', 'Replication', 'ERR_MissionRules'):
|
||||||
|
update = update.replace(name+'.', name+'::')
|
||||||
|
discover = discover.replace(name+'.', name+'::')
|
||||||
|
for typename in ('ERR_GameMode', 'SCR_MapMarkerManagerComponent'):
|
||||||
|
update = update.replace(typename+' ', typename+'* ')
|
||||||
|
discover = discover.replace('ERR_GameMode mode', 'ERR_GameMode* mode')
|
||||||
|
for name in ('mode', 'manager', 'oldManager', 'm_ERRMarker'):
|
||||||
|
update = update.replace(name+'.',name+'->')
|
||||||
|
discover = discover.replace('mode.', 'mode->')
|
||||||
|
update = update.replace('GetGame().','GetGame()->').replace('null','nullptr')
|
||||||
|
mission = body(base/'ERR_MissionRules.c', 'static int Discovery(')
|
||||||
|
run(r'''
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}};
|
||||||
|
namespace ERR_LocationKind {enum Kind{PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT,MORTAR,HOSPITAL};}
|
||||||
|
namespace SCR_EMapMarkerType {constexpr int PLACED_CUSTOM=0;}
|
||||||
|
struct Game{bool controller=true;bool GetPlayerController(){return controller;}}game;
|
||||||
|
Game* GetGame(){return &game;}
|
||||||
|
struct Replication{static inline bool server=true;static bool IsServer(){return server;}static void BumpMe(){}};
|
||||||
|
struct ERR_GameMode{bool enabled=false;int events=0;static ERR_GameMode* Get();bool ShowAllSites(){return enabled;}void LocationDiscovered(void*,int,int){events++;}}mode;
|
||||||
|
ERR_GameMode* ERR_GameMode::Get(){return &mode;}
|
||||||
|
struct ERR_MissionRules {'''+mission+r'''};
|
||||||
|
struct ERR_DiscoveryMapRules {'''+rules+r'''};
|
||||||
|
struct ERR_DiscoveryMarker{
|
||||||
|
string label,m_Icon;int x=0,refreshes=0;bool removed=false;
|
||||||
|
static string Icon(int kind,string){return kind==ERR_LocationKind::RADIO?"radio":"supplies";}
|
||||||
|
void ApplyIcon(){}void SetType(int){}void SetMarkerConfigID(int){}
|
||||||
|
void SetCustomText(string v){label=v;}void RefreshPresentation(){refreshes++;}
|
||||||
|
void SetDiscoveryPosition(float p,int knowledge){x=ERR_DiscoveryMapRules::Coordinate(p,knowledge);}
|
||||||
|
void OnDelete(){removed=true;}
|
||||||
|
'''+icon.replace('ERR_LocationKind kind','int kind')+r'''
|
||||||
|
};
|
||||||
|
struct SCR_MapMarkerManagerComponent{
|
||||||
|
static inline bool ready=true;int inserts=0,removes=0;
|
||||||
|
static SCR_MapMarkerManagerComponent* GetInstance();
|
||||||
|
bool GetMarkerConfig(){return ready;}
|
||||||
|
void ERR_InsertDiscoveryMarker(ERR_DiscoveryMarker*){inserts++;}
|
||||||
|
void ERR_RemoveDiscoveryMarker(ERR_DiscoveryMarker* marker){removes++;delete marker;}
|
||||||
|
}manager;
|
||||||
|
SCR_MapMarkerManagerComponent* SCR_MapMarkerManagerComponent::GetInstance(){return &manager;}
|
||||||
|
struct Location{
|
||||||
|
ERR_DiscoveryMarker* m_ERRMarker=nullptr;int m_ERRShown=-1,m_Knowledge=0;string m_ERRShownLabel;
|
||||||
|
bool m_Prepared=true;int kind=ERR_LocationKind::RADIO;
|
||||||
|
int Knowledge(){return m_Knowledge;}bool Prepared(){return m_Prepared;}int Kind(){return kind;}
|
||||||
|
string Label(){return "Secret radio station";}string Id(){return "secret-radio-id";}float Position(){return 6123.25f;}
|
||||||
|
'''+update+'\n'+discover+r'''
|
||||||
|
~Location(){delete m_ERRMarker;}
|
||||||
|
};
|
||||||
|
int main(){
|
||||||
|
Location site;site.ERR_UpdateMarker();assert(!site.m_ERRMarker&&site.m_Knowledge==0);
|
||||||
|
mode.enabled=true;site.ERR_UpdateMarker();assert(site.m_ERRMarker);
|
||||||
|
assert(site.m_ERRMarker->label=="Unknown site"&&site.m_ERRMarker->m_Icon=="mark-question"&&site.m_ERRMarker->x==6123);
|
||||||
|
assert(site.m_Knowledge==0&&mode.events==0); // Visibility never grants discovery or objective progress.
|
||||||
|
auto* first=site.m_ERRMarker;site.ERR_UpdateMarker();assert(site.m_ERRMarker==first&&manager.inserts==1);
|
||||||
|
mode.enabled=false;site.ERR_UpdateMarker();assert(!site.m_ERRMarker&&manager.removes==1);
|
||||||
|
mode.enabled=true;site.ERR_UpdateMarker();assert(site.m_ERRMarker&&manager.inserts==2);
|
||||||
|
assert(site.Discover(99,0)); // An actual clue identifies even when normal exact chance is zero.
|
||||||
|
site.ERR_UpdateMarker();assert(site.Knowledge()==2&&mode.events==1);
|
||||||
|
assert(site.m_ERRMarker->label=="Secret radio station"&&site.m_ERRMarker->m_Icon=="radio");
|
||||||
|
mode.enabled=false;site.ERR_UpdateMarker();assert(site.m_ERRMarker&&site.m_ERRMarker->x==6123);
|
||||||
|
assert(!site.Discover(0,100)&&mode.events==1);
|
||||||
|
Location rough;assert(rough.Discover(99,0)&&rough.Knowledge()==1);rough.ERR_UpdateMarker();
|
||||||
|
assert(rough.m_ERRMarker->label=="Unknown location (500 m area)"&&rough.m_ERRMarker->x==6250);
|
||||||
|
mode.enabled=true;rough.ERR_UpdateMarker();assert(rough.Knowledge()==1&&rough.m_ERRMarker->x==6123&&rough.m_ERRMarker->m_Icon=="mark-question");
|
||||||
|
mode.enabled=false;rough.ERR_UpdateMarker();assert(rough.m_ERRMarker->x==6250);
|
||||||
|
mode.enabled=true;assert(rough.Discover(99,0)&&rough.Knowledge()==2);
|
||||||
|
Location pending;pending.m_Prepared=false;pending.ERR_UpdateMarker();assert(!pending.m_ERRMarker&&!pending.Discover(0,100));
|
||||||
|
pending.m_Prepared=true;pending.ERR_UpdateMarker();assert(pending.m_ERRMarker);
|
||||||
|
pending.m_Prepared=false;pending.ERR_UpdateMarker();assert(!pending.m_ERRMarker);
|
||||||
|
Location prison;prison.kind=ERR_LocationKind::PRISON;prison.ERR_UpdateMarker();assert(!prison.m_ERRMarker);
|
||||||
|
Location late;manager.ready=false;late.ERR_UpdateMarker();assert(!late.m_ERRMarker);
|
||||||
|
manager.ready=true;late.ERR_UpdateMarker();assert(late.m_ERRMarker&&late.m_ERRMarker->m_Icon=="mark-question");
|
||||||
|
Replication::server=false;assert(!late.Discover(0,100)&&late.Knowledge()==0);
|
||||||
|
for(int kind=ERR_LocationKind::RADIO;kind<=ERR_LocationKind::HOSPITAL;kind++){
|
||||||
|
Location other;other.kind=kind;other.ERR_UpdateMarker();assert(other.m_ERRMarker&&other.m_ERRMarker->label=="Unknown site"&&other.m_ERRMarker->m_Icon=="mark-question");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
# Persisted authority and runtime presentation wiring (including late-join replication).
|
||||||
|
settings=base/'ERR_Settings.c'
|
||||||
|
assert '"showAllSites"' in body(settings,'static array<string> Keys(')
|
||||||
|
assert 'if (key == "showAllSites") return 0;' in body(settings,'static int AddedDefault(')
|
||||||
|
assert 'showAllSites' not in body(settings,'static bool Randomizable(')
|
||||||
|
mode_source=(base/'ERR_GameMode.c').read_text()
|
||||||
|
assert '[RplProp()] protected bool m_ShowAllSites;' in mode_source
|
||||||
|
assert 'PublishSiteVisibility();' in body(base/'ERR_GameMode.c','protected override void EOnInit(')
|
||||||
|
publish=body(base/'ERR_GameMode.c','void PublishSiteVisibility(')
|
||||||
|
assert '!Replication.IsServer()' in publish and 'Replication.BumpMe()' in publish
|
||||||
|
admin=body(base/'ERR_AdminService.c','void Execute(')
|
||||||
|
assert admin.index('!authorized') < admin.index('mode.PublishSiteVisibility()')
|
||||||
|
assert admin.index('SettingCommand(mode.Settings(), key, parts, replies);') < admin.index('mode.PublishSiteVisibility()')
|
||||||
|
click=body(base/'ERR_AdminMenu.c','protected void OnButton(')
|
||||||
|
assert click.index('!m_Ready') < click.index('"intel sites set "')
|
||||||
|
print('PASS: hidden/anonymous/rough/identified markers, toggle transitions, prepared sites, no identity leakage, intel discovery and replicated authority wiring')
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -21,6 +21,7 @@ SCHEMA={
|
|||||||
'responseRadiusMetres':(2000,500,5000),
|
'responseRadiusMetres':(2000,500,5000),
|
||||||
'aiIntelChancePercent':(60,0,100),
|
'aiIntelChancePercent':(60,0,100),
|
||||||
'intelRevealChancePercent':(15,0,100),
|
'intelRevealChancePercent':(15,0,100),
|
||||||
|
'showAllSites':(0,0,1),
|
||||||
'radioDefenceSeconds':(180,30,1800),
|
'radioDefenceSeconds':(180,30,1800),
|
||||||
'startTimeMinutes':(840,0,1439),
|
'startTimeMinutes':(840,0,1439),
|
||||||
'timeMultiplier':(1,1,24),
|
'timeMultiplier':(1,1,24),
|
||||||
@@ -35,7 +36,7 @@ SCHEMA={
|
|||||||
'heliTimerMinutes':(15,1,1440),
|
'heliTimerMinutes':(15,1,1440),
|
||||||
}
|
}
|
||||||
AI_KEYS=('aiDoctrine','aiShadow','planeAltitudeMetres','planeReplacementSeconds','planeSectorSeconds','planeReconEnabled','reportIntervalSeconds','supportSquadLimit','responseRadiusMetres','automaticEquipmentChancePercent','antiAirChancePercent','antiPersonnelMineChancePercent','automaticConvoyEnabled','heliTimerMinutes')
|
AI_KEYS=('aiDoctrine','aiShadow','planeAltitudeMetres','planeReplacementSeconds','planeSectorSeconds','planeReconEnabled','reportIntervalSeconds','supportSquadLimit','responseRadiusMetres','automaticEquipmentChancePercent','antiAirChancePercent','antiPersonnelMineChancePercent','automaticConvoyEnabled','heliTimerMinutes')
|
||||||
INTEL_KEYS=('aiIntelChancePercent','intelRevealChancePercent')
|
INTEL_KEYS=('aiIntelChancePercent','intelRevealChancePercent','showAllSites')
|
||||||
def merge(ai=None,intel=None):
|
def merge(ai=None,intel=None):
|
||||||
result={key:spec[0] for key,spec in SCHEMA.items()};deferred=[]
|
result={key:spec[0] for key,spec in SCHEMA.items()};deferred=[]
|
||||||
for label,data,keys in [('ai',ai,AI_KEYS),('intel',intel,INTEL_KEYS)]:
|
for label,data,keys in [('ai',ai,AI_KEYS),('intel',intel,INTEL_KEYS)]:
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
FrameWidgetClass { "Is Visible" {{VISIBLE_IntelPage}} Name "IntelPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
FrameWidgetClass { "Is Visible" {{VISIBLE_IntelPage}} Name "IntelPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "IntelHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 }
|
Name "IntelHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 40 OffsetBottom -46 }
|
||||||
Color {{COLOR_TEXT}} Text "Control how often soldiers carry intel and whether the first clue reveals an exact location." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1
|
Color {{COLOR_TEXT}} Text "Choose how sites appear on the map and how often soldiers carry intel." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1
|
||||||
FontProperties FontProperties { Font "{{FONT}}" }
|
FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 80 OffsetTop 80 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -108 }
|
Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 150 OffsetTop 150 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -178 }
|
||||||
Color {{COLOR_TEXT}} Text "AI carrying intel (0-100%)" "Font Size" {{SIZE_LABEL}} "Min Font Size" {{SIZE_LABEL}} Wrap 1 FontProperties FontProperties {
|
Color {{COLOR_TEXT}} Text "AI carrying intel (0-100%)" "Font Size" {{SIZE_LABEL}} "Min Font Size" {{SIZE_LABEL}} Wrap 1 FontProperties FontProperties {
|
||||||
Font "{{FONT}}"
|
Font "{{FONT}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -136 }
|
Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 194 OffsetTop 194 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -214 }
|
||||||
Color {{COLOR_TEXT}} Text "Waiting for saved value" "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1 FontProperties FontProperties {
|
Color {{COLOR_TEXT}} Text "Waiting for saved value" "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1 FontProperties FontProperties {
|
||||||
Font "{{FONT}}"
|
Font "{{FONT}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Help_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 136 OffsetTop 136 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -156 }
|
Name "Help_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 218 OffsetTop 218 SizeX 936 OffsetRight -964 SizeY 32 OffsetBottom -250 }
|
||||||
Color {{COLOR_MUTED}} Text "Chance for each new enemy soldier to carry intel. Reassign carried intel updates existing soldiers." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
Color {{COLOR_MUTED}} Text "Chance for each new enemy soldier to carry intel. Reassign carried intel updates existing soldiers." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
||||||
FontProperties FontProperties { Font "{{FONT}}" }
|
FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
||||||
Name "aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 80 OffsetTop 80 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -122 }
|
Name "aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 150 OffsetTop 150 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
||||||
m_sLabel ""
|
m_sLabel ""
|
||||||
@@ -31,7 +31,7 @@ ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 80 OffsetTop 80 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -122 }
|
Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 150 OffsetTop 150 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Apply"
|
m_sText "Apply"
|
||||||
@@ -39,7 +39,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Random_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 80 OffsetTop 80 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -122 }
|
Name "Random_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 150 OffsetTop 150 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -192 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Random"
|
m_sText "Random"
|
||||||
@@ -47,25 +47,25 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -196 }
|
Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 252 OffsetTop 252 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -280 }
|
||||||
Color {{COLOR_TEXT}} Text "First-document exact reveal (0-100%)" "Font Size" {{SIZE_LABEL}} "Min Font Size" {{SIZE_LABEL}} Wrap 1 FontProperties FontProperties {
|
Color {{COLOR_TEXT}} Text "First-document exact reveal (0-100%)" "Font Size" {{SIZE_LABEL}} "Min Font Size" {{SIZE_LABEL}} Wrap 1 FontProperties FontProperties {
|
||||||
Font "{{FONT}}"
|
Font "{{FONT}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 200 OffsetTop 200 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -224 }
|
Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 296 OffsetTop 296 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -316 }
|
||||||
Color {{COLOR_TEXT}} Text "Waiting for saved value" "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1 FontProperties FontProperties {
|
Color {{COLOR_TEXT}} Text "Waiting for saved value" "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1 FontProperties FontProperties {
|
||||||
Font "{{FONT}}"
|
Font "{{FONT}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "Help_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 224 OffsetTop 224 SizeX 936 OffsetRight -964 SizeY 20 OffsetBottom -244 }
|
Name "Help_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 320 OffsetTop 320 SizeX 936 OffsetRight -964 SizeY 36 OffsetBottom -356 }
|
||||||
Color {{COLOR_MUTED}} Text "First clue: chance to reveal the exact site. Otherwise a question mark shows an approximate area." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
Color {{COLOR_MUTED}} Text "With all sites shown, intel always identifies the type. Otherwise this chance controls exact versus approximate clues." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
||||||
FontProperties FontProperties { Font "{{FONT}}" }
|
FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
||||||
Name "intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 168 OffsetTop 168 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -210 }
|
Name "intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 252 OffsetTop 252 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
SCR_EditBoxComponent "{547290FFBD5B33E9}" {
|
||||||
m_sLabel ""
|
m_sLabel ""
|
||||||
@@ -73,7 +73,7 @@ ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 168 OffsetTop 168 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -210 }
|
Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 252 OffsetTop 252 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Apply"
|
m_sText "Apply"
|
||||||
@@ -81,7 +81,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "Random_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 168 OffsetTop 168 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -210 }
|
Name "Random_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 252 OffsetTop 252 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -294 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Random"
|
m_sText "Random"
|
||||||
@@ -89,7 +89,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "IntelSummary" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -288 SizeY 42 OffsetBottom -318 }
|
Name "IntelSummary" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 364 OffsetTop 364 SizeX 260 OffsetRight -288 SizeY 42 OffsetBottom -406 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Intel summary"
|
m_sText "Intel summary"
|
||||||
@@ -97,7 +97,7 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
Name "RerollIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 306 OffsetLeft 306 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -566 SizeY 42 OffsetBottom -318 }
|
Name "RerollIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 306 OffsetLeft 306 PositionY 364 OffsetTop 364 SizeX 260 OffsetRight -566 SizeY 42 OffsetBottom -406 }
|
||||||
components {
|
components {
|
||||||
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
SCR_ButtonTextComponent "{5548F0143AE99095}" {
|
||||||
m_sText "Reassign carried intel"
|
m_sText "Reassign carried intel"
|
||||||
@@ -105,13 +105,29 @@ ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_But
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "IntelRerollHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 336 OffsetTop 336 SizeX 936 OffsetRight -964 SizeY 52 OffsetBottom -388 }
|
Name "IntelRerollHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 420 OffsetTop 420 SizeX 936 OffsetRight -964 SizeY 26 OffsetBottom -446 }
|
||||||
Color {{COLOR_TEXT}} Text "Reassign carried intel uses the saved chance on existing AI. Intel already collected stays revealed." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1
|
Color {{COLOR_TEXT}} Text "Reassign carried intel updates existing AI. Collected intel stays revealed." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
||||||
FontProperties FontProperties { Font "{{FONT}}" }
|
FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
}
|
}
|
||||||
TextWidgetClass {
|
TextWidgetClass {
|
||||||
Name "EvidenceHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 402 OffsetTop 402 SizeX 936 OffsetRight -964 SizeY 60 OffsetBottom -462 }
|
Name "EvidenceHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 454 OffsetTop 454 SizeX 936 OffsetRight -964 SizeY 28 OffsetBottom -482 }
|
||||||
Color {{COLOR_TEXT}} Text "Enemy bodies stay until a recovery team searches them and reports to HQ. Cleanup is then enabled with a five-minute delay." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1
|
Color {{COLOR_TEXT}} Text "Enemy bodies remain until searched and reported, then become eligible for cleanup after five minutes." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1
|
||||||
FontProperties FontProperties { Font "{{FONT}}" }
|
FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
}
|
}
|
||||||
|
TextWidgetClass {
|
||||||
|
Name "Label_showAllSites" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 58 OffsetTop 58 SizeX 550 OffsetRight -578 SizeY 32 OffsetBottom -90 }
|
||||||
|
Color {{COLOR_TEXT}} Text "Show all sites as question marks" "Font Size" {{SIZE_LABEL}} "Min Font Size" {{SIZE_LABEL}} Wrap 1 FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
|
}
|
||||||
|
TextWidgetClass {
|
||||||
|
Name "Help_showAllSites" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 102 OffsetTop 102 SizeX 936 OffsetRight -964 SizeY 40 OffsetBottom -142 }
|
||||||
|
Color {{COLOR_MUTED}} Text "Show prepared site positions without names or types. Intel identifies each site. Applies now for everyone; disabled by default." "Font Size" {{SIZE_CAPTION}} "Min Font Size" {{SIZE_CAPTION}} Wrap 1 FontProperties FontProperties { Font "{{FONT}}" }
|
||||||
|
}
|
||||||
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
|
Name "SitesOn" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 54 OffsetTop 54 SizeX 146 OffsetRight -806 SizeY 42 OffsetBottom -96 }
|
||||||
|
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Enabled" } }
|
||||||
|
}
|
||||||
|
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||||
|
Name "SitesOff" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 818 OffsetLeft 818 PositionY 54 OffsetTop 54 SizeX 146 OffsetRight -964 SizeY 42 OffsetBottom -96 }
|
||||||
|
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Disabled" } }
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
|
|||||||
Reference in New Issue
Block a user