diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 25d30212e9..4724884176 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -61,7 +61,6 @@ namespace OpenRA public bool? Creeps; public bool? AllyBuildRadius; public string TechLevel; - public bool ConfigurableStartingUnits = true; public string[] Difficulties = { }; public bool? ShortGame; @@ -118,7 +117,6 @@ namespace OpenRA public string Description; public string Author; public string Tileset; - public bool AllowStartUnitConfig = true; public Bitmap CustomPreview; public bool InvalidCustomRules { get; private set; } diff --git a/OpenRA.Game/Network/Session.cs b/OpenRA.Game/Network/Session.cs index dbb6e48341..3eb3ea5267 100644 --- a/OpenRA.Game/Network/Session.cs +++ b/OpenRA.Game/Network/Session.cs @@ -191,7 +191,7 @@ namespace OpenRA.Network public bool AllyBuildRadius = true; public int StartingCash = 5000; public string TechLevel = "none"; - public string StartingUnitsClass = "none"; + public string StartingUnitsClass; public string GameSpeedType = "default"; public bool ShortGame = true; public bool AllowVersionMismatch; diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index f9070afb67..03f84d407b 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -617,7 +617,8 @@ namespace OpenRA.Mods.Common.Server return true; } - if (!server.Map.Options.ConfigurableStartingUnits) + var startingUnits = server.Map.Rules.Actors["world"].TraitInfoOrDefault(); + if (startingUnits == null || startingUnits.Locked) { server.SendOrderTo(conn, "Message", "Map has disabled start unit configuration."); return true; @@ -1030,6 +1031,9 @@ namespace OpenRA.Mods.Common.Server var resources = server.Map.Rules.Actors["player"].TraitInfo(); gs.StartingCash = resources.DefaultCash; + var startingUnits = server.Map.Rules.Actors["world"].TraitInfoOrDefault(); + gs.StartingUnitsClass = startingUnits == null ? "none" : startingUnits.StartingUnitsClass; + server.Map.Options.UpdateServerSettings(server.LobbyInfo.GlobalSettings); } diff --git a/OpenRA.Mods.Common/Traits/World/SpawnMPUnits.cs b/OpenRA.Mods.Common/Traits/World/SpawnMPUnits.cs index c4f461ae40..3bbc5e5e02 100644 --- a/OpenRA.Mods.Common/Traits/World/SpawnMPUnits.cs +++ b/OpenRA.Mods.Common/Traits/World/SpawnMPUnits.cs @@ -18,7 +18,13 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Spawn base actor at the spawnpoint and support units in an annulus around the base actor. Both are defined at MPStartUnits. Attach this to the world actor.")] - public class SpawnMPUnitsInfo : TraitInfo, Requires, Requires { } + public class SpawnMPUnitsInfo : TraitInfo, Requires, Requires + { + public readonly string StartingUnitsClass = "none"; + + [Desc("Prevent the starting units option from being changed in the lobby.")] + public bool Locked = false; + } public class SpawnMPUnits : IWorldLoaded { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index e44aeaa6be..7b52a6cb8d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -429,19 +429,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic var startingUnits = optionsBin.GetOrNull("STARTINGUNITS_DROPDOWNBUTTON"); if (startingUnits != null) { - var startUnitsInfo = modRules.Actors["world"].TraitInfos(); - var classes = startUnitsInfo.Select(a => a.Class).Distinct(); + var startUnitsInfos = new CachedTransform>( + map => map.Rules.Actors["world"].TraitInfos()); + + var startUnitsLocked = new CachedTransform(map => + { + var spawnUnitsInfo = map.Rules.Actors["world"].TraitInfoOrDefault(); + return spawnUnitsInfo == null || spawnUnitsInfo.Locked; + }); + Func className = c => { - var selectedClass = startUnitsInfo.Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault(); + var selectedClass = startUnitsInfos.Update(Map).Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault(); return selectedClass != null ? selectedClass : c; }; - startingUnits.IsDisabled = () => configurationDisabled() || !Map.Options.ConfigurableStartingUnits; + startingUnits.IsDisabled = () => configurationDisabled() || startUnitsLocked.Update(Map); startingUnits.GetText = () => MapPreview.Status != MapStatus.Available || - Map == null || !Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); + Map == null || startUnitsLocked.Update(Map) ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); startingUnits.OnMouseDown = _ => { + var classes = startUnitsInfos.Update(Map).Select(a => a.Class).Distinct(); var options = classes.Select(c => new DropDownOption { Title = className(c), diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 0277b7c4ac..eac9c02431 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -163,7 +163,6 @@ ServerTraits: LobbySettingsNotification LobbyDefaults: - StartingUnitsClass: light TechLevel: Unrestricted ChromeMetrics: diff --git a/mods/cnc/rules/world.yaml b/mods/cnc/rules/world.yaml index 5ff347d8eb..4006d6c919 100644 --- a/mods/cnc/rules/world.yaml +++ b/mods/cnc/rules/world.yaml @@ -135,6 +135,7 @@ World: BaseActor: mcv SupportActors: e1,e1,e1,e1,e1,e2,e2,e2,e3,e3,apc,mtnk SpawnMPUnits: + StartingUnitsClass: light CrateSpawner: Minimum: 1 Maximum: 6