diff --git a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs index 1530fcb925..556b0b8f02 100644 --- a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs @@ -24,13 +24,13 @@ namespace OpenRA.Mods.RA.Server { if (!server.lobbyInfo.Slots.ContainsKey(arg)) { - Log.Write("server", "Invalid slot: {0}", arg ); + Log.Write("server", "Invalid slot: {0}", arg); return false; } - + if (requiresHost && !client.IsAdmin) { - server.SendChatTo( conn, "Only the host can do that" ); + server.SendChatTo(conn, "Only the host can do that"); return false; } @@ -318,6 +318,47 @@ namespace OpenRA.Mods.RA.Server server.SyncLobbyInfo(); return true; }}, + { "assignteams", + s => + { + if (!client.IsAdmin) + { + server.SendChatTo(conn, "Only the host can set that option"); + return true; + } + + int teams; + if (!int.TryParse(s, out teams)) + { + server.SendChatTo(conn, "Number of teams could not be parsed: {0}".F(s)); + return true; + } + + teams = teams.Clamp(2, 8); + + var clients = server.lobbyInfo.Slots + .Select(slot => server.lobbyInfo.Clients.SingleOrDefault(c => c.Slot == slot.Key)) + .Where(c => c != null && !server.lobbyInfo.Slots[c.Slot].LockTeam).ToArray(); + + var teamSizes = new int[clients.Length]; + + for (var i = 0; i < clients.Length; i++) + teamSizes[i % teams]++; + + var clientIndex = 0; + for (var team = 1; team <= teams; team++) + { + for (var teamClientIndex = 0; teamClientIndex < teamSizes[team - 1]; clientIndex++, teamClientIndex++) + { + var cl = clients[clientIndex]; + if (cl.Bot == null) + cl.State = Session.ClientState.NotReady; + cl.Team = team; + } + } + server.SyncLobbyInfo(); + return true; + }}, { "crates", s => { @@ -481,14 +522,14 @@ namespace OpenRA.Mods.RA.Server var cmdName = cmd.Split(' ').First(); var cmdValue = cmd.Split(' ').Skip(1).JoinWith(" "); - Func a; + Func a; if (!dict.TryGetValue(cmdName, out a)) return false; return a(cmdValue); } - public void ServerStarted(S server) + public void ServerStarted(S server) { LoadMap(server); SetDefaultDifficulty(server); diff --git a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs index bee8804315..2a3e159efe 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs @@ -125,6 +125,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic .ToDictionary(a => a.Race, a => a.Name); CountryNames.Add("random", "Any"); + var gameStarting = false; + var mapButton = lobby.Get("CHANGEMAP_BUTTON"); mapButton.OnClick = () => { @@ -157,11 +159,33 @@ namespace OpenRA.Mods.RA.Widgets.Logic randomMapButton.IsVisible = () => mapButton.Visible && Game.IsHost; } + var assignTeams = lobby.GetOrNull("ASSIGNTEAMS_DROPDOWNBUTTON"); + if (assignTeams != null) + { + assignTeams.IsVisible = () => Game.IsHost; + assignTeams.IsDisabled = () => gameStarting || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; + + assignTeams.OnMouseDown = _ => + { + var options = Enumerable.Range(2, orderManager.LobbyInfo.Clients.Count.Clamp(2, 8) - 1).Select(d => new DropDownOption + { + Title = "{0} Teams".F(d), + IsSelected = () => false, + OnClick = () => orderManager.IssueOrder(Order.Command("assignteams {0}".F(d.ToString()))) + }); + Func setupItem = (option, template) => + { + var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); + item.Get("LABEL").GetText = () => option.Title; + return item; + }; + assignTeams.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); + }; + } + var disconnectButton = lobby.Get("DISCONNECT_BUTTON"); disconnectButton.OnClick = () => { CloseWindow(); onExit(); }; - var gameStarting = false; - var allowCheats = lobby.Get("ALLOWCHEATS_CHECKBOX"); allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; allowCheats.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null @@ -187,13 +211,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty; difficulty.OnMouseDown = _ => { - var options = Map.Difficulties.Select(d => new DifficultyDropDownOption + var options = Map.Difficulties.Select(d => new DropDownOption { Title = d, IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d, OnClick = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d))) }); - Func setupItem = (option, template) => + Func setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get("LABEL").GetText = () => option.Title; @@ -492,7 +516,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic orderManager.IssueOrder(Order.Command("ready")); } - class DifficultyDropDownOption + class DropDownOption { public string Title; public Func IsSelected; diff --git a/mods/ra/chrome/lobby.yaml b/mods/ra/chrome/lobby.yaml index 66ff373fd6..7384706be9 100644 --- a/mods/ra/chrome/lobby.yaml +++ b/mods/ra/chrome/lobby.yaml @@ -386,22 +386,30 @@ Background@SERVER_LOBBY: Height:25 Text:Random Map Font:Bold - DropDownButton@DIFFICULTY_DROPDOWNBUTTON: + DropDownButton@ASSIGNTEAMS_DROPDOWNBUTTON: X:PARENT_RIGHT-154 Y:PARENT_BOTTOM-229 Width:120 Height:25 Font:Bold Visible:false + Text:Assign + DropDownButton@DIFFICULTY_DROPDOWNBUTTON: + X:PARENT_RIGHT-154 + Y:PARENT_BOTTOM-199 + Width:120 + Height:25 + Font:Bold + Visible:false Checkbox@ALLOWCHEATS_CHECKBOX: X: PARENT_RIGHT-154 - Y: PARENT_BOTTOM-179 + Y: PARENT_BOTTOM-169 Width: 80 Height: 20 Text: Allow Cheats Checkbox@CRATES_CHECKBOX: X: PARENT_RIGHT-154 - Y: PARENT_BOTTOM-154 + Y: PARENT_BOTTOM-144 Width: 80 Height: 20 Text: Crates