Make Sarka special-forces cars per anger point configurable

This commit is contained in:
2026-10-17 17:42:41 +02:00
parent 38fd8f7dd2
commit 0e71ef1fa7
12 changed files with 124 additions and 18 deletions
@@ -8,11 +8,12 @@ class ERR_AdminMenuFields
{
static array<string> Keys()
{
return {"aiDoctrine", "aiShadow", "automaticEquipmentChancePercent", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "emptyRestartHours", "startMode", "radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "convoyCount", "antiAirChancePercent", "antiPersonnelMineChancePercent", "heliTimerMinutes"};
return {"aiDoctrine", "aiShadow", "automaticEquipmentChancePercent", "sarkaCarsPerAnger", "motorbikeCount", "planeAltitudeMetres", "planeReplacementSeconds", "planeSectorSeconds", "fieldCampCount", "fieldHospitalCount", "startWeaponCount", "startMagazineCount", "objectGuardCount", "objectGuardEvery", "objectGuardHQMode", "hunterSpawnDistanceMetres", "roadblockCount", "civilianTrafficCount", "emptyRestartHours", "startMode", "radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "viewDistanceMetres", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "convoyCount", "antiAirChancePercent", "antiPersonnelMineChancePercent", "heliTimerMinutes"};
}
static bool Available(string key, bool hq, bool intel)
{
if (key == "aiDoctrine" || key == "aiShadow") return hq;
if (key == "sarkaCarsPerAnger") return hq;
if (key == "aiIntelChancePercent") return intel;
if (key == "automaticEquipmentChancePercent" || key == "motorbikeCount" || key == "planeAltitudeMetres" || key == "planeReplacementSeconds" || key == "planeSectorSeconds" || key == "planeReconEnabled" || key == "objectGuardCount" || key == "objectGuardEvery" || key == "objectGuardHQMode" || key == "hunterSpawnDistanceMetres" || key == "heliTimerMinutes" || key == "antiAirChancePercent" || key == "antiPersonnelMineChancePercent" || key == "convoyCount" || key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres") return hq;
return Keys().Contains(key);
@@ -50,6 +51,7 @@ class ERR_AdminMenuFields
if (key == "aiDoctrine") prefix = "mission doctrine";
else if (key == "aiShadow") prefix = "mission aishadow";
else if (key == "automaticEquipmentChancePercent") prefix = "hq equipment";
else if (key == "sarkaCarsPerAnger") prefix = "mission sarkacars";
else if (key == "motorbikeCount") prefix = "mission motorbikes";
else if (key == "planeReconEnabled") prefix = "mission plane";
else if (key == "planeAltitudeMetres") prefix = "mission planealtitude";
@@ -135,6 +137,7 @@ class ERR_AdminMenu : ChimeraMenuBase
names.Insert("RandomDay_startTimeMinutes");
names.Insert("Default_viewDistanceMetres");
names.Insert("OpenForces");
names.Insert("OpenSarka"); names.Insert("SarkaBack");
names.Insert("RestartEmptyOn"); names.Insert("RestartEmptyOff");
names.Insert("OpenGuards"); names.Insert("GuardsBack");
names.Insert("OpenSites"); names.Insert("SitesBack");
@@ -236,8 +239,8 @@ class ERR_AdminMenu : ChimeraMenuBase
if (widget) widget.SetText(value);
}
// Stable page order is also used by the shared navigation bar and native probe.
static array<string> Pages() { return {"SettingsPage", "HQPage", "JournalPage", "ModsPage", "FactionsPage", "WorldPage", "IntelPage", "StatusPage", "TerrainsPage", "ItemsPage", "TTSPage", "ForcesPage", "GuardsPage", "SitesPage", "PlanePage", "RecommendationsPage", "WeightsPage", "AllowedItemsPage", "ItemPresetsPage", "AIPage", "StarterPage"}; }
static array<string> Navigation() { return {"OpenSettings", "OpenHQ", "OpenJournal", "OpenMods", "OpenFactions", "OpenWorld", "OpenIntel", "OpenStatus", "OpenTerrains", "OpenItems", "OpenTTS", "OpenForces", "OpenGuards", "OpenSites", "OpenPlane", "OpenRecommendations", "OpenWeights", "OpenAllowedItems", "OpenItemPresets", "OpenAI", "OpenStarter"}; }
static array<string> Pages() { return {"SettingsPage", "HQPage", "JournalPage", "ModsPage", "FactionsPage", "WorldPage", "IntelPage", "StatusPage", "TerrainsPage", "ItemsPage", "TTSPage", "ForcesPage", "GuardsPage", "SitesPage", "PlanePage", "RecommendationsPage", "WeightsPage", "AllowedItemsPage", "ItemPresetsPage", "AIPage", "StarterPage", "SarkaPage"}; }
static array<string> Navigation() { return {"OpenSettings", "OpenHQ", "OpenJournal", "OpenMods", "OpenFactions", "OpenWorld", "OpenIntel", "OpenStatus", "OpenTerrains", "OpenItems", "OpenTTS", "OpenForces", "OpenGuards", "OpenSites", "OpenPlane", "OpenRecommendations", "OpenWeights", "OpenAllowedItems", "OpenItemPresets", "OpenAI", "OpenStarter", "OpenSarka"}; }
protected void ShowPage(int page)
{
array<string> pages = Pages();
@@ -438,7 +441,7 @@ class ERR_AdminMenu : ChimeraMenuBase
if (name == "RecommendedWeapons") { ShowPage(9); return; }
if (name == "PlaneBack") { ShowPage(1); return; }
if (name == "AIBack") { ShowPage(1); return; }
if (name == "GuardsBack" || name == "SitesBack") { ShowPage(11); return; }
if (name == "GuardsBack" || name == "SitesBack" || name == "SarkaBack") { ShowPage(11); return; }
int page = Navigation().Find(name);
if (page >= 0) { ShowPage(page); return; }
if (name == "JournalDetails")
@@ -6,6 +6,7 @@ class ERR_CommandArguments
{
if (section == "mission" && option == "doctrine") return "aiDoctrine";
if (section == "mission" && option == "aishadow") return "aiShadow";
if (section == "mission" && option == "sarkacars") return "sarkaCarsPerAnger";
if (section == "mission" && option == "motorbikes") return "motorbikeCount";
if (section == "mission" && option == "planealtitude") return "planeAltitudeMetres";
if (section == "mission" && option == "planereplacement") return "planeReplacementSeconds";
@@ -170,6 +171,7 @@ class ERR_AdminService
if (key == "aiShadow") return "On (1) records coordinated proposals without issuing their orders; Off (0) uses the selected doctrine. Saved for next round.";
if (key == "startWeaponCount") return "0..12 pistols in the shared prison/crash supply backpack; default 5. Applies next round.";
if (key == "startMagazineCount") return "0..48 spare pistol magazines in the shared prison/crash supply backpack; default 8. Applies next round.";
if (key == "sarkaCarsPerAnger") return "0-5 cars per anger point; 0 disables new waves. Default 1; maximum 30 cars per wave, four special-forces crew per car. Applies to new waves; existing teams remain.";
if (key == "motorbikeCount") return "0-6; default 2; 0 disabled. Optional WCS Motorbikes, two response specialists per bike. Applies next round; losses are not replaced.";
if (key == "planeAltitudeMetres") return "150-500; default 250. Applies next round.";
if (key == "planeReplacementSeconds") return "30-1800; default 60. Applies next round.";
@@ -1,7 +1,20 @@
#ifdef WORKBENCH
modded class ERR_AdminMenu
{
bool ERR_SarkaProbeReady() { return m_Ready && m_AvailableFields.Contains("sarkaCarsPerAnger"); }
bool ERR_SarkaProbeSet(int cars)
{
ShowPage(Navigation().Find("OpenSarka"));
SCR_EditBoxComponent edit = SCR_EditBoxComponent.GetEditBoxComponent("sarkaCarsPerAnger", GetRootWidget());
SCR_ButtonTextComponent button = SCR_ButtonTextComponent.GetButtonText("Apply_sarkaCarsPerAnger", GetRootWidget());
if (!edit || !button || !button.IsEnabled()) return false;
edit.SetValue(cars.ToString()); OnButton(button); return true;
}
}
modded class ERR_HunterService
{
void ERR_ProbeSarkaDue(float now) { m_SarkaWaves.NextWave = now; }
bool ERR_ProbeSarkaDisabled() { return m_SarkaWaves.CarsPerAnger == 0 && m_SarkaWaves.Pending == 0; }
void ERR_ProbeSarkas(out array<ERR_HunterVehicle> cars)
{
cars.Clear();
@@ -52,6 +65,23 @@ modded class ERR_GameMode
float now = GetWorld().GetWorldTime();
if (m_ERRSarkaStage == 0)
{
if (!ERR_SarkaProbeCheck(Settings().Get("sarkaCarsPerAnger") == 1, "default one car per anger point")) return;
ERR_AdminMenu.Open(); m_ERRSarkaStage = 10; return;
}
if (m_ERRSarkaStage == 10)
{
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu();
if (!menu || !menu.ERR_SarkaProbeReady()) return;
if (!ERR_SarkaProbeCheck(menu.ERR_SarkaProbeSet(2), "real menu submits two cars per anger point")) return;
m_ERRSarkaStage = 11; return;
}
if (m_ERRSarkaStage == 11)
{
if (Settings().Get("sarkaCarsPerAnger") != 2) return;
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu(); if (!menu || !menu.ERR_SarkaProbeReady()) return;
System.MakeScreenshot("$logs:err-sarka-settings"); menu.Close();
ERR_Settings reloaded = new ERR_Settings();
if (!ERR_SarkaProbeCheck(reloaded.Get("sarkaCarsPerAnger") == 2, "menu owner RPC persists multiplier")) return;
if (!ERR_SarkaProbeCheck(UnlockPrison(player) || Phase() >= ERR_Phase.RADIO_SEARCH, "prison released")) return;
hq.ERR_ProbeSarkaBodies(now);
if (!ERR_SarkaProbeCheck(hq.Watch().Aggression() == 2, "six delivered bodies produce two anger points")) return;
@@ -59,10 +89,26 @@ modded class ERR_GameMode
hq.Hunters().ERR_ProbeSarkaDue(now); m_ERRSarkaStage = 1;
}
array<ERR_HunterVehicle> cars = {}; hq.Hunters().ERR_ProbeSarkas(cars);
if (cars.Count() < 2) return;
if (cars.Count() < 4) return;
if (m_ERRSarkaStage == 20)
{
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu();
if (!menu || !menu.ERR_SarkaProbeReady()) return;
if (!ERR_SarkaProbeCheck(menu.ERR_SarkaProbeSet(0), "real menu submits disable")) return;
m_ERRSarkaStage = 21; return;
}
if (m_ERRSarkaStage == 21)
{
if (Settings().Get("sarkaCarsPerAnger") != 0 || !hq.Hunters().ERR_ProbeSarkaDisabled()) return;
foreach (ERR_HunterVehicle retained : cars)
if (!ERR_SarkaProbeCheck(retained.Entity && retained.Members.Count() == 4, "disabling retains deployed cars and teams")) return;
ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu(); if (menu) menu.Close();
GetGame().GetCallqueue().Remove(ERR_SarkaProbeTick);
Print("ERR SMOKE COMPLETE: sarka menu save, multiplier, four SF cars, radio, driving and disable"); return;
}
if (m_ERRSarkaStage == 1)
{
if (!ERR_SarkaProbeCheck(cars.Count() == 2, "two physical cars for two anger points")) return;
if (!ERR_SarkaProbeCheck(cars.Count() == 4, "two cars per anger point produce four physical cars")) return;
array<vector> positions = {player.GetOrigin()};
foreach (ERR_HunterVehicle car : cars)
{
@@ -87,8 +133,7 @@ modded class ERR_GameMode
if (!m_ERRSarkaOrder || vector.DistanceXZ(cars[0].PatrolHome, cars[0].Entity.GetOrigin()) < 30) return;
if (!ERR_SarkaProbeCheck(hq.Hunters().Deployed() <= hq.Watch().HunterTarget(), "cars do not spend ordinary hunter allowance")) return;
ERR_SarkaProbeCheck(true, "native patrol order and over 30 metres driven; all crew enhanced");
GetGame().GetCallqueue().Remove(ERR_SarkaProbeTick);
Print("ERR SMOKE COMPLETE: sarka hunters, two anger points, two four-person SF cars, road distance, radio and driving");
ERR_AdminMenu.Open(); m_ERRSarkaStage = 20;
}
}
#endif
@@ -9,12 +9,13 @@ class ERR_Settings
static array<string> Keys()
{
return {"aiDoctrine", "aiShadow", "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", "sarkaCarsPerAnger", "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"};
}
static bool Valid(string key, int value)
{
if (key == "aiDoctrine" || key == "aiShadow") return value == 0 || value == 1;
if (key == "sarkaCarsPerAnger") return value >= 0 && value <= 5;
if (key == "motorbikeCount") return value >= 0 && value <= 6;
if (key == "planeAltitudeMetres") return value >= 150 && value <= 500;
if (key == "planeReplacementSeconds") return value >= 30 && value <= 1800;
@@ -117,6 +118,7 @@ class ERR_Settings
static int AddedDefault(string key)
{
if (key == "aiDoctrine" || key == "aiShadow") return 0;
if (key == "sarkaCarsPerAnger") return 1;
if (key == "motorbikeCount") return 2;
if (key == "planeAltitudeMetres") return 250;
if (key == "planeReplacementSeconds") return 60;
@@ -152,6 +154,7 @@ class ERR_Settings
m_Path = path;
m_Values.Set("aiDoctrine", AddedDefault("aiDoctrine"));
m_Values.Set("aiShadow", AddedDefault("aiShadow"));
m_Values.Set("sarkaCarsPerAnger", AddedDefault("sarkaCarsPerAnger"));
m_Values.Set("motorbikeCount", AddedDefault("motorbikeCount"));
m_Values.Set("planeAltitudeMetres", AddedDefault("planeAltitudeMetres"));
m_Values.Set("planeReplacementSeconds", AddedDefault("planeReplacementSeconds"));
@@ -173,6 +173,7 @@ class ERR_HQ : ERR_CommandService
m_Hunters = new ERR_HunterService(mode, null);
m_Hunters.ConfigureOpening(mode.Settings().Get("hunterSpawnDistanceMetres"));
m_Hunters.ConfigureMotorbikes(mode.Settings().Get("motorbikeCount"));
m_Hunters.ConfigureSarka();
m_ObjectiveDefence = new ERR_ObjectiveDefence(mode, this);
m_Towns = new ERR_TownGarrisons(mode);
m_Roadblocks = new ERR_Roadblocks(mode);
@@ -8,15 +8,22 @@ class ERR_SarkaWaves
int Target;
int Wave;
int Spawned;
int CarsPerAnger = 1;
void Configure(int cars)
{
if (CarsPerAnger == cars) return;
CarsPerAnger = cars;
if (cars == 0) Pause();
}
void Pause() { NextWave = -1; Pending = 0; Target = 0; }
bool Due(float now, int aggression, bool playing)
{
if (!playing) { Pause(); return false; }
if (!playing || CarsPerAnger == 0) { Pause(); return false; }
if (NextWave < 0) { NextWave = now + 600000; return false; }
if (now >= NextWave)
{
NextWave = now + 600000; NextAttempt = now;
Target = Math.Clamp(aggression, 0, 30); Pending = Target; Wave++;
Target = Math.Clamp(Math.Clamp(aggression, 0, 30) * CarsPerAnger, 0, 30); Pending = Target; Wave++;
}
if (Pending == 0 || now < NextAttempt) return false;
NextAttempt = now + 5000;
@@ -138,10 +138,18 @@ class ERR_HunterService : ERR_ConvoyService
protected float m_NextReserve;
protected ref ERR_HunterVehicle m_PendingReserve;
protected ref ERR_SarkaWaves m_SarkaWaves = new ERR_SarkaWaves();
protected string m_SarkaStatus = "first wave ten minutes after prison escape";
protected string m_SarkaStatus = "waiting for first wave after prison escape";
void ConfigureSarka()
{
int cars = m_Mode.Settings().Get("sarkaCarsPerAnger");
bool changed = cars != m_SarkaWaves.CarsPerAnger;
m_SarkaWaves.Configure(cars);
if (changed) m_SarkaStatus = "saved car count applies to the next wave";
if (cars == 0) m_SarkaStatus = "new waves disabled; existing teams remain";
}
string SarkaStatus()
{
return string.Format(" Sarka waves: %1 deployed, %2/%3 pending in wave %4; %5.", m_SarkaWaves.Spawned, m_SarkaWaves.Pending, m_SarkaWaves.Target, m_SarkaWaves.Wave, m_SarkaStatus);
return string.Format(" Sarka waves: %1 deployed, %2/%3 pending in wave %4; %5.", m_SarkaWaves.Spawned, m_SarkaWaves.Pending, m_SarkaWaves.Target, m_SarkaWaves.Wave, m_SarkaStatus) + string.Format(" %1 cars per anger point (30 per wave maximum).", m_SarkaWaves.CarsPerAnger);
}
// HQ maintenance runs even while tactical ticks pause in an empty round.
void PauseSarkaIfEmpty()
@@ -152,6 +160,7 @@ class ERR_HunterService : ERR_ConvoyService
}
protected void TickSarka(ERR_HQ hq, float now)
{
ConfigureSarka();
// Released crews keep their physical/HQ ownership; discard only wave tracking.
for (int retired = m_Hunters.Count() - 1; retired >= 0; retired--)
if (m_Hunters[retired].Sarka && m_Hunters[retired].Released) m_Hunters.Remove(retired);
@@ -161,7 +170,7 @@ class ERR_HunterService : ERR_ConvoyService
if (previousWave != m_SarkaWaves.Wave)
{
m_SarkaStatus = "placing four-person special-forces teams on roads";
if (m_SarkaWaves.Target == 0) m_SarkaStatus = "no aggression; next wave check in ten minutes";
if (m_SarkaWaves.Target == 0) m_SarkaStatus = "no aggression; waiting for the next interval";
ERR_HQ.Event("SARKA WAVE", string.Format("wave=%1 aggression=%2 cars=%3 identified bodies=%4", m_SarkaWaves.Wave, hq.Watch().Aggression(), m_SarkaWaves.Target, hq.Watch().IdentifiedBodies()));
}
if (!due) return;
@@ -192,7 +201,7 @@ class ERR_HunterService : ERR_ConvoyService
else m_SarkaStatus = "vehicle or crew setup failed; retrying this wave";
return;
}
m_SarkaStatus = "waiting for a clear road 1-1.25 km from the nearest player";
m_SarkaStatus = "waiting for a clear road away from players";
}
protected bool SpawnSarka(float now, vector position, vector angles)
{
+14 -1
View File
@@ -67,7 +67,7 @@ TextWidgetClass { Name "Help_emptyRestartHours" Slot FrameWidgetSlot { Anchor 0
} }
FrameWidgetClass { Name "ForcesPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } {
TextWidgetClass {
Name "ForcesHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 }
Name "ForcesHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 710 OffsetRight -738 SizeY 50 OffsetBottom -56 }
Color 0.9 0.92 0.94 1 Text "Enemy patrols, site guards and equipment. Equipment changes apply to newly equipped soldiers." "Font Size" 19 "Min Font Size" 19 Wrap 1
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
}
@@ -210,6 +210,19 @@ TextWidgetClass {
Color 0.72 0.81 0.87 1 Text "Chance of anti-personnel mines for newly equipped soldiers." "Font Size" 14 "Min Font Size" 14 Wrap 1
FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" }
}
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "OpenSarka" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 788 OffsetLeft 788 PositionY 4 OffsetTop 4 SizeX 176 OffsetRight -964 SizeY 38 OffsetBottom -42 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Šárka hunters" } } }
ImageWidgetClass { Name "Selected_OpenSarka" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 788 OffsetLeft 788 PositionY 45 OffsetTop 45 SizeX 176 OffsetRight -964 SizeY 3 OffsetBottom -48 } Color 0.9 0.66 0.25 1 }
} }
FrameWidgetClass { Name "SarkaPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } {
TextWidgetClass { Name "SarkaHeading" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 710 OffsetRight -738 SizeY 32 OffsetBottom -38 } Color 0.9 0.92 0.94 1 Text "Šárka special-forces hunters" "Font Size" 22 "Min Font Size" 22 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "SarkaBack" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 788 OffsetLeft 788 PositionY 4 OffsetTop 4 SizeX 176 OffsetRight -964 SizeY 38 OffsetBottom -42 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Back to Forces" } } }
TextWidgetClass { Name "SarkaHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 50 OffsetTop 50 SizeX 936 OffsetRight -964 SizeY 44 OffsetBottom -94 } Color 0.9 0.92 0.94 1 Text "Four soldiers per car, including a medic. Anger rises from identified enemy casualties." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
TextWidgetClass { Name "Label_sarkaCarsPerAnger" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 590 OffsetRight -618 SizeY 32 OffsetBottom -144 } Color 0.9 0.92 0.94 1 Text "Šárkas per anger point (0-5; 0 disables waves)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { Name "sarkaCarsPerAnger" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 640 OffsetLeft 640 PositionY 108 OffsetTop 108 SizeX 112 OffsetRight -752 SizeY 38 OffsetBottom -146 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } }
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "Apply_sarkaCarsPerAnger" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 764 OffsetLeft 764 PositionY 108 OffsetTop 108 SizeX 200 OffsetRight -964 SizeY 38 OffsetBottom -146 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } }
TextWidgetClass { Name "Saved_sarkaCarsPerAnger" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 640 OffsetLeft 640 PositionY 148 OffsetTop 148 SizeX 324 OffsetRight -964 SizeY 24 OffsetBottom -172 } Color 0.9 0.92 0.94 1 Text "Waiting for server" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
TextWidgetClass { Name "Help_sarkaCarsPerAnger" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 176 OffsetTop 176 SizeX 936 OffsetRight -964 SizeY 26 OffsetBottom -202 } Color 0.9 0.92 0.94 1 Text "Default 1; up to 30 cars per wave. Existing teams remain when disabled." "Font Size" 17 "Min Font Size" 17 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
TextWidgetClass { Name "SarkaSettingsHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 424 OffsetTop 424 SizeX 936 OffsetRight -964 SizeY 52 OffsetBottom -476 } Color 0.9 0.92 0.94 1 Text "Apply saves this setting for new waves. Existing teams remain. Empty sessions do not build up extra waves." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
} }
FrameWidgetClass { Name "SitesPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } {
TextWidgetClass { Name "SitesHeading" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 710 OffsetRight -738 SizeY 32 OffsetBottom -38 } Color 0.9 0.92 0.94 1 Text "Camps and hospitals - next round" "Font Size" 22 "Min Font Size" 22 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }