diff --git a/OpenRA.Game/Network/Session.cs b/OpenRA.Game/Network/Session.cs index c2e995b140..c10ff6fe82 100644 --- a/OpenRA.Game/Network/Session.cs +++ b/OpenRA.Game/Network/Session.cs @@ -82,7 +82,7 @@ namespace OpenRA.Network public string[] Mods = { "ra" }; // mod names public int OrderLatency = 3; public int RandomSeed = 0; - public bool LockTeams = true; // don't allow team changes after game start. + public bool FragileAlliances = false; // Allow diplomatic stance changes after game start. public bool AllowCheats = false; public bool Dedicated; public string Difficulty; diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index e1db2476f1..a1259da378 100755 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -163,7 +163,7 @@ namespace OpenRA.Network case "SetStance": { - if (Game.orderManager.LobbyInfo.GlobalSettings.LockTeams) + if (!Game.orderManager.LobbyInfo.GlobalSettings.FragileAlliances) return; var targetPlayer = order.Player.World.Players.FirstOrDefault(p => p.InternalName == order.TargetString); diff --git a/OpenRA.Game/Widgets/CheckboxWidget.cs b/OpenRA.Game/Widgets/CheckboxWidget.cs index a896c70f62..e2378a2a7d 100644 --- a/OpenRA.Game/Widgets/CheckboxWidget.cs +++ b/OpenRA.Game/Widgets/CheckboxWidget.cs @@ -56,7 +56,8 @@ namespace OpenRA.Widgets var textSize = font.Measure(Text); font.DrawText(Text, - new float2(rect.Left + rect.Height * 1.5f, RenderOrigin.Y - BaseLine + (Bounds.Height - textSize.Y)/2), Color.White); + new float2(rect.Left + rect.Height * 1.5f, RenderOrigin.Y - BaseLine + (Bounds.Height - textSize.Y)/2), + disabled ? Color.Gray : Color.White); if (IsChecked() || (Depressed && HasPressedState && !disabled)) { diff --git a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs index cfbf1b086b..11dcbe635a 100644 --- a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs @@ -292,7 +292,7 @@ namespace OpenRA.Mods.RA.Server server.SyncLobbyInfo(); return true; }}, - { "lockteams", + { "fragilealliance", s => { if (!client.IsAdmin) @@ -301,7 +301,7 @@ namespace OpenRA.Mods.RA.Server return true; } - bool.TryParse(s, out server.lobbyInfo.GlobalSettings.LockTeams); + bool.TryParse(s, out server.lobbyInfo.GlobalSettings.FragileAlliances); server.SyncLobbyInfo(); return true; }}, diff --git a/OpenRA.Mods.RA/Widgets/Logic/DiplomacyLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/DiplomacyLogic.cs index 7673691c24..b2e6b46ed0 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/DiplomacyLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/DiplomacyLogic.cs @@ -111,6 +111,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic GetText = () => world.LocalPlayer.Stances[ pp ].ToString(), }; + if (!p.World.LobbyInfo.GlobalSettings.FragileAlliances) + myStance.Disabled = true; + myStance.OnMouseDown = mi => ShowDropDown(pp, myStance); bg.AddChild(myStance); @@ -138,7 +141,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic void SetStance(ButtonWidget bw, Player p, Stance ss) { - if (p.World.LobbyInfo.GlobalSettings.LockTeams) + if (!p.World.LobbyInfo.GlobalSettings.FragileAlliances) return; // team changes are banned // NOTE(jsd): Abuse of the type system here with `CPos` diff --git a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs index 9f2aaf3acc..aa8548b4f0 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs @@ -36,6 +36,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic readonly Action onExit; readonly OrderManager orderManager; + public bool TeamGame; + // Listen for connection failures void ConnectionStateChanged(OrderManager om) { @@ -204,6 +206,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates))); } + var fragileAlliance = lobby.GetOrNull("FRAGILEALLIANCES_CHECKBOX"); + if (fragileAlliance != null) + { + fragileAlliance.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances; + fragileAlliance.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null + || orderManager.LocalClient.IsReady || TeamGame; // only available in FFA + fragileAlliance.OnClick = () => orderManager.IssueOrder(Order.Command( + "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances))); + }; + + var difficulty = lobby.GetOrNull("DIFFICULTY_DROPDOWNBUTTON"); if (difficulty != null) { @@ -326,6 +339,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic void UpdatePlayerList() { var idx = 0; + TeamGame = false; + foreach (var kv in orderManager.LobbyInfo.Slots) { var key = kv.Key; @@ -414,6 +429,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic team.OnMouseDown = _ => LobbyUtils.ShowTeamDropDown(team, client, orderManager, Map); team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); + if (slot.LockTeam || client.Team > 0) + TeamGame = true; + if (client.Bot == null) { // local player @@ -552,6 +570,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic while (Players.Children.Count > idx) Players.RemoveChild(Players.Children[idx]); + + if (orderManager.LobbyInfo.GlobalSettings.FragileAlliances && TeamGame) + orderManager.IssueOrder(Order.Command("fragilealliance false")); // No back-stabbing in Team games. } void CycleReady() diff --git a/mods/ra/chrome/lobby.yaml b/mods/ra/chrome/lobby.yaml index 410f1b59ff..e260d375d3 100644 --- a/mods/ra/chrome/lobby.yaml +++ b/mods/ra/chrome/lobby.yaml @@ -420,9 +420,15 @@ Background@SERVER_LOBBY: Width: 80 Height: 20 Text: Crates + Checkbox@FRAGILEALLIANCES_CHECKBOX: + X: PARENT_RIGHT-154 + Y: PARENT_BOTTOM-119 + Width: 80 + Height: 20 + Text: Fragile Alliances Button@DISCONNECT_BUTTON: X:PARENT_RIGHT-154 - Y:PARENT_BOTTOM-99 + Y:PARENT_BOTTOM-94 Width:120 Height:25 Text:Disconnect