diff --git a/OpenRA.Server/Server.cs b/OpenRA.Server/Server.cs index 9c7c9d678f..7834cd8669 100644 --- a/OpenRA.Server/Server.cs +++ b/OpenRA.Server/Server.cs @@ -251,6 +251,32 @@ namespace OpenRA.Server GetClient(conn).Race = 1 + race; SyncLobbyInfo(); return true; + }}, + { "spawn", + s => + { + if (GameStarted) + { + SendChatTo( conn, "You can't change your spawn point after the game has started" ); + return true; + } + + int spawnPoint; + if (!int.TryParse(s, out spawnPoint) || spawnPoint < 0 || spawnPoint > 8) //TODO: SET properly! + { + Console.WriteLine("Invalid spawn point: {0}", s); + return false; + } + + if (lobbyInfo.Clients.Where( c => c != GetClient(conn) ).Any( c => c.SpawnPoint == spawnPoint )) //TODO: except 0 + { + SendChatTo( conn, "You can't be at the same spawn point as another player" ); + return true; + } + + GetClient(conn).SpawnPoint = spawnPoint; + SyncLobbyInfo(); + return true; }}, { "pal", s => diff --git a/OpenRa.FileFormats/Session.cs b/OpenRa.FileFormats/Session.cs index 1cb07a8ddd..a89080cc33 100644 --- a/OpenRa.FileFormats/Session.cs +++ b/OpenRa.FileFormats/Session.cs @@ -22,7 +22,7 @@ namespace OpenRa.FileFormats public int Index; public int PaletteIndex; public int Race; - // public int SpawnPoint; + public int SpawnPoint; public string Name; public ClientState State; } diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 200d5e600f..945e600e0e 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -346,6 +346,10 @@ namespace OpenRa } bool PaletteAvailable(int index) { return Game.LobbyInfo.Clients.All(c => c.PaletteIndex != index); } + + bool SpawnPointAvailable(int index) { return Game.LobbyInfo.Clients.All(c => c.SpawnPoint != index); } + + void CyclePalette(bool left) { var d = left ? +1 : Player.PlayerColors.Count() - 1; @@ -354,9 +358,11 @@ namespace OpenRa while (!PaletteAvailable(newIndex) && newIndex != (int)Game.world.LocalPlayer.PaletteIndex) newIndex = (newIndex + d) % Player.PlayerColors.Count(); - + + Game.world.Minimap.InvalidateSpawnPoints(); Game.IssueOrder( Order.Chat("/pal " + newIndex)); + } void CycleRace(bool left) @@ -371,6 +377,21 @@ namespace OpenRa new Order("ToggleReady", Game.world.LocalPlayer.PlayerActor, "") { IsImmediate = true }); } + void CycleSpawnPoint(bool left) + { + var d = left ? +1 : Game.world.Map.SpawnPoints.Count() - 1; + + var newIndex = (Game.world.LocalPlayer.SpawnPointIndex + d) % Game.world.Map.SpawnPoints.Count(); + + while (!SpawnPointAvailable(newIndex) && newIndex != (int)Game.world.LocalPlayer.SpawnPointIndex) + newIndex = (newIndex + d) % Game.world.Map.SpawnPoints.Count(); + + Game.world.Minimap.InvalidateSpawnPoints(); + Game.IssueOrder( + Order.Chat("/spawn " + newIndex)); + + } + public void DrawLobby( World world ) { buttons.Clear(); @@ -408,32 +429,37 @@ namespace OpenRa } renderer.DrawText2("Name", new int2(r.Left + 40, r.Top + 50), Color.White); - renderer.DrawText2("Color", new int2(r.Left + 230, r.Top + 50), Color.White); - renderer.DrawText2("Faction", new int2(r.Left + 300, r.Top + 50), Color.White); - renderer.DrawText2("Status", new int2(r.Left + 370, r.Top + 50), Color.White); + renderer.DrawText2("Color", new int2(r.Left + 140, r.Top + 50), Color.White); + renderer.DrawText2("Faction", new int2(r.Left + 220, r.Top + 50), Color.White); + renderer.DrawText2("Status", new int2(r.Left + 290, r.Top + 50), Color.White); + renderer.DrawText2("Spawn", new int2(r.Left + 390, r.Top + 50), Color.White); var y = r.Top + 80; foreach (var client in Game.LobbyInfo.Clients) { var isLocalPlayer = client.Index == Game.orderManager.Connection.LocalClientId; - var paletteRect = new Rectangle(r.Left + 220, y - 2, 65, 22); + var paletteRect = new Rectangle(r.Left + 130, y - 2, 65, 22); if (isLocalPlayer) { // todo: name editing - var nameRect = new Rectangle(r.Left + 30, y - 2, 185, 22); + var nameRect = new Rectangle(r.Left + 30, y - 2, 95, 22); DrawDialogBackground(nameRect, "panel"); DrawDialogBackground(paletteRect, "panel"); AddButton(paletteRect, CyclePalette); - var raceRect = new Rectangle(r.Left + 290, y - 2, 65, 22); + var raceRect = new Rectangle(r.Left + 210, y - 2, 65, 22); DrawDialogBackground(raceRect, "panel"); AddButton(raceRect, CycleRace); - var readyRect = new Rectangle(r.Left + 360, y - 2, 95, 22); + var readyRect = new Rectangle(r.Left + 280, y - 2, 95, 22); DrawDialogBackground(readyRect, "panel"); AddButton(readyRect, CycleReady); + + var spawnPointRect = new Rectangle(r.Left + 380, y - 2, 70, 22); + DrawDialogBackground(spawnPointRect, "panel"); + AddButton(spawnPointRect, CycleSpawnPoint); } shpRenderer.Flush(); @@ -445,8 +471,9 @@ namespace OpenRa paletteRect.Bottom+Game.viewport.Location.Y - 5), Player.PlayerColors[client.PaletteIndex].c); lineRenderer.Flush(); - renderer.DrawText(((Race)client.Race).ToString(), new int2(r.Left + 300, y), Color.White); - renderer.DrawText(client.State.ToString(), new int2(r.Left + 370, y), Color.White); + renderer.DrawText(((Race)client.Race).ToString(), new int2(r.Left + 220, y), Color.White); + renderer.DrawText(client.State.ToString(), new int2(r.Left + 290, y), Color.White); + renderer.DrawText((client.SpawnPoint == 0)? "-" : client.SpawnPoint.ToString(), new int2(r.Left + 410, y), Color.White); y += 30; } diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index 1ea77ed98c..a6cf1fa3e9 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -239,12 +239,16 @@ namespace OpenRa foreach (var client in LobbyInfo.Clients) { - // todo: allow players to choose their own spawn points. - // only select a point for them if they didn't. - + int2 sp; + if (client.SpawnPoint == 0) + sp = ChooseSpawnPoint(available, taken); + else + { + sp = world.Map.SpawnPoints.ElementAt(client.SpawnPoint - 1); + taken.Add(sp); + available.Remove(sp); + } // todo: spawn more than one unit, in most cases! - - var sp = ChooseSpawnPoint(available, taken); world.CreateActor("mcv", sp, world.players[client.Index]); } diff --git a/OpenRa.Game/Graphics/Minimap.cs b/OpenRa.Game/Graphics/Minimap.cs index 0f52cbeaf5..4bcaac4407 100644 --- a/OpenRa.Game/Graphics/Minimap.cs +++ b/OpenRa.Game/Graphics/Minimap.cs @@ -5,6 +5,7 @@ using OpenRa.Traits; using OpenRa.FileFormats; using System.Drawing.Imaging; using IjwFramework.Collections; +using System.Collections.Generic; namespace OpenRa.Graphics { @@ -62,6 +63,7 @@ namespace OpenRa.Graphics static Color shroudColor; public void InvalidateOre() { oreLayer = null; } + public void InvalidateSpawnPoints() { spawnPointsLayer = null; } public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset) { @@ -78,8 +80,8 @@ namespace OpenRa.Graphics public static Bitmap RenderTerrainBitmapWithSpawnPoints(Map map, TileSet tileset) { var terrain = RenderTerrainBitmap(map, tileset); - foreach (var point in map.SpawnPoints) - terrain.SetPixel(point.X, point.Y, Color.White); + foreach (var sp in map.SpawnPoints) + terrain.SetPixel(sp.X, sp.Y, Color.White); return terrain; } @@ -105,9 +107,19 @@ namespace OpenRa.Graphics if (spawnPointsLayer == null) { spawnPointsLayer = new Bitmap(terrain); - foreach (var point in world.Map.SpawnPoints){ - spawnPointsLayer.SetPixel(point.X, point.Y, Color.White); + var available = Game.world.Map.SpawnPoints.ToList(); + + foreach (var player in Game.world.players.Values) + { + if (player.SpawnPointIndex != 0) + { + int2 sp = Game.world.Map.SpawnPoints.ElementAt(player.SpawnPointIndex - 1); + spawnPointsLayer.SetPixel(sp.X, sp.Y, player.Color); + available.Remove(sp); + } } + foreach (var sp in available) + spawnPointsLayer.SetPixel(sp.X, sp.Y, Color.White); } mapSpawnPointSheet.Texture.SetData(spawnPointsLayer); diff --git a/OpenRa.Game/Player.cs b/OpenRa.Game/Player.cs index 4d2c9c0adc..613f8d92a3 100644 --- a/OpenRa.Game/Player.cs +++ b/OpenRa.Game/Player.cs @@ -26,6 +26,7 @@ namespace OpenRa public int DisplayCash = 0; public int PowerProvided = 0; public int PowerDrained = 0; + public int SpawnPointIndex = 0; public World World { get { return PlayerActor.World; } } @@ -189,6 +190,12 @@ namespace OpenRa PaletteIndex = client.PaletteIndex; Game.chat.AddLine(this, "has changed color to {0}".F(PlayerColors[client.PaletteIndex].b)); } + + if (SpawnPointIndex != client.SpawnPoint) + { + SpawnPointIndex = client.SpawnPoint; + Game.chat.AddLine(this, "has changed spawn point to {0}".F(client.SpawnPoint)); + } } } }