diff --git a/OpenRA.Game/Network/Session.cs b/OpenRA.Game/Network/Session.cs index 45e25626c2..ef2c5aa814 100644 --- a/OpenRA.Game/Network/Session.cs +++ b/OpenRA.Game/Network/Session.cs @@ -66,6 +66,7 @@ namespace OpenRA.Network public bool LockRace; public bool LockColor; public bool LockTeam; + public bool LockSpawn; } public class Global diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs index 0008e23e9b..7b9769d0dc 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs @@ -355,11 +355,31 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic return item; }; - var options = Graphics.Util.MakeArray(Map.PlayerCount, i => i).ToList(); + var options = Graphics.Util.MakeArray(Map.SpawnPoints.Count()+1, i => i).ToList(); dropdown.ShowDropDown("TEAM_DROPDOWN_TEMPLATE", 150, options, setupItem); return true; } - + + bool ShowSpawnDropDown(DropDownButtonWidget dropdown, Session.Client client) + { + Func setupItem = (ii, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => client.SpawnPoint == ii, + () => orderManager.IssueOrder(Order.Command("spawn {0} {1}".F(client.Index, ii)))); + item.GetWidget("LABEL").GetText = () => ii == 0 ? "-" : ii.ToString(); + return item; + }; + + var taken = orderManager.LobbyInfo.Clients + .Where(c => c.SpawnPoint != 0 && c.SpawnPoint != client.SpawnPoint && c.Slot != null) + .Select(c => c.SpawnPoint).ToList(); + + var options = Graphics.Util.MakeArray(Map.SpawnPoints.Count() + 1, i => i).Except(taken).ToList(); + dropdown.ShowDropDown("TEAM_DROPDOWN_TEMPLATE", 150, options, setupItem); + return true; + } + bool ShowColorDropDown(DropDownButtonWidget color, Session.Client client) { Action onSelect = c => @@ -483,6 +503,11 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic team.OnMouseDown = _ => { if (team.IsDisabled()) return true; return ShowTeamDropDown(team, client); }; team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); + var spawn = template.GetWidget("SPAWN"); + spawn.IsDisabled = () => slot.LockSpawn; + spawn.OnMouseDown = _ => { if (spawn.IsDisabled()) return true; return ShowSpawnDropDown(spawn, client); }; + spawn.GetText = () => (client.SpawnPoint == 0) ? "-" : client.SpawnPoint.ToString(); + if (client.Bot == null) { // local player @@ -493,7 +518,6 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic } else // Bot template.GetWidget("STATUS_IMAGE").IsVisible = () => true; - } // Non-editable player in slot else diff --git a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs index a5f3a25648..dfcfca1efc 100644 --- a/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.RA/ServerTraits/LobbyCommands.cs @@ -321,7 +321,8 @@ namespace OpenRA.Mods.RA.Server AllowBots = pr.AllowBots, LockRace = pr.LockRace, LockColor = pr.LockColor, - LockTeam = false + LockTeam = false, + LockSpawn = false }; } diff --git a/OpenRA.Mods.RA/ServerTraits/PlayerCommands.cs b/OpenRA.Mods.RA/ServerTraits/PlayerCommands.cs index 62b12971dc..581c14711d 100644 --- a/OpenRA.Mods.RA/ServerTraits/PlayerCommands.cs +++ b/OpenRA.Mods.RA/ServerTraits/PlayerCommands.cs @@ -94,7 +94,11 @@ namespace OpenRA.Mods.RA.Server return true; // Spectators don't need a spawnpoint - if (client.Slot == null) + if (targetClient.Slot == null) + return true; + + // Map has disabled spawn changes + if (server.lobbyInfo.Slots[targetClient.Slot].LockSpawn) return true; int spawnPoint;