diff --git a/OpenRA.Game/Player.cs b/OpenRA.Game/Player.cs index b687cba371..b79f45211f 100644 --- a/OpenRA.Game/Player.cs +++ b/OpenRA.Game/Player.cs @@ -36,7 +36,8 @@ namespace OpenRA public readonly CountryInfo Country; public readonly int Index; public readonly bool NonCombatant = false; - public readonly int ClientIndex; + public readonly int ClientIndex; + public readonly PlayerReference PlayerRef; public ShroudRenderer Shroud; public World World { get; private set; } @@ -57,29 +58,32 @@ namespace OpenRA PlayerName = InternalName = pr.Name; NonCombatant = pr.NonCombatant; Country = world.GetCountries() - .FirstOrDefault(c => pr.Race == c.Race); + .FirstOrDefault(c => pr.Race == c.Race); + + PlayerRef = pr; RegisterPlayerColor(world, Palette); } - public Player( World world, Session.Client client ) + public Player( World world, Session.Client client, PlayerReference pr, int index ) { World = world; Shroud = new ShroudRenderer(this, world.Map); PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) }); - Index = client.Index; - Palette = "player"+client.Index; + Index = index; + Palette = "player"+index; Color = client.Color1; Color2 = client.Color2; - PlayerName = client.Name; - InternalName = "Multi{0}".F(client.Index); + PlayerName = client.Name; + InternalName = pr.Name; Country = world.GetCountries() .FirstOrDefault(c => client != null && client.Country == c.Race) ?? world.GetCountries().Random(world.SharedRandom); - ClientIndex = client.Index; + ClientIndex = client.Index; + PlayerRef = pr; RegisterPlayerColor(world, Palette); } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 0ac3703669..f355076672 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -162,6 +162,8 @@ namespace OpenRA.Traits public interface ILoadWorldHook { void WorldLoaded(World w); } public interface IGameStarted { void GameStarted(World w); } public interface ICreatePlayers { void CreatePlayers(World w); } + + public interface IBot { void Activate(Player p); } public interface IActivity { diff --git a/OpenRA.Mods.RA/CreateMPPlayers.cs b/OpenRA.Mods.RA/CreateMPPlayers.cs index ce7336d652..096bd01e9b 100644 --- a/OpenRA.Mods.RA/CreateMPPlayers.cs +++ b/OpenRA.Mods.RA/CreateMPPlayers.cs @@ -8,7 +8,6 @@ */ #endregion -using System.Collections.Generic; using System.Linq; using OpenRA.Network; using OpenRA.Traits; @@ -20,12 +19,31 @@ namespace OpenRA.Mods.RA public class CreateMPPlayers : ICreatePlayers { public void CreatePlayers(World w) - { - // Add real players - w.SetLocalPlayer(Game.LocalClientId); - - foreach (var c in Game.LobbyInfo.Clients) - w.AddPlayer(new Player(w, c)); + { + var playerIndex = 0; + foreach (var slot in Game.LobbyInfo.Slots) + { + var client = Game.LobbyInfo.Clients.FirstOrDefault(c => c.Slot == slot.Index); + if (client != null) + { + /* spawn a real player in this slot. */ + var player = new Player(w, client, w.Map.Players[slot.MapPlayer], playerIndex++); + w.AddPlayer(player); + if (client.Index == Game.LocalClientId) + w.SetLocalPlayer(player.Index); // bind this one to the local player. + } + else if (slot.Bot != null) + { + /* spawn a bot in this slot, "owned" by the host */ + var player = new Player(w, w.Map.Players[slot.MapPlayer], playerIndex++); + w.AddPlayer(player); + + /* todo: init its bot -- but only on the host! */ + if (Game.IsHost) + foreach (var bot in player.PlayerActor.TraitsImplementing()) + bot.Activate(player); + } + } foreach (var p in w.players.Values) foreach (var q in w.players.Values) diff --git a/OpenRA.Mods.RA/World/HackyAI.cs b/OpenRA.Mods.RA/HackyAI.cs similarity index 92% rename from OpenRA.Mods.RA/World/HackyAI.cs rename to OpenRA.Mods.RA/HackyAI.cs index b40e0c2609..66c4c11246 100644 --- a/OpenRA.Mods.RA/World/HackyAI.cs +++ b/OpenRA.Mods.RA/HackyAI.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA /* a pile of hacks, which control a local player on the host. */ - class HackyAI : IGameStarted, ITick + class HackyAI : ITick, IBot { bool enabled; int ticks; @@ -62,23 +62,14 @@ namespace OpenRA.Mods.RA BuildState state = BuildState.WaitForFeedback; - public void GameStarted(World w) + /* called by the host's player creation code */ + public void Activate(Player p) { - try - { - p = Game.world.players.First(c => c.Value.PlayerName.Equals("bot")).Value; - } - catch (Exception) - { - //Could not find a bot. - } - //p = Game.world.LocalPlayer; - enabled = Game.IsHost && p != null; - if (enabled) - { - productionQueue = p.PlayerActor.Trait(); - playerResources = p.PlayerActor.Trait(); - } + this.p = p; + enabled = true; + + productionQueue = p.PlayerActor.Trait(); + playerResources = p.PlayerActor.Trait(); } int GetPowerProvidedBy(string building) @@ -341,6 +332,5 @@ namespace OpenRA.Mods.RA break; } } - - } + } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 60ba683244..ebadf88c06 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -238,7 +238,7 @@ - + diff --git a/OpenRA.Mods.RA/SpawnMPUnits.cs b/OpenRA.Mods.RA/SpawnMPUnits.cs index ffbdf149b9..c915a4be2b 100644 --- a/OpenRA.Mods.RA/SpawnMPUnits.cs +++ b/OpenRA.Mods.RA/SpawnMPUnits.cs @@ -8,9 +8,6 @@ */ #endregion -using System; -using System.Collections.Generic; -using System.Linq; using OpenRA.FileFormats; using OpenRA.Traits; @@ -28,6 +25,9 @@ namespace OpenRA.Mods.RA void SpawnUnitsForPlayer(Player p, int2 sp) { + if (!p.PlayerRef.DefaultStartingUnits) + return; /* they don't want an mcv, the map provides something else for them. */ + p.World.CreateActor("mcv", new TypeDictionary { new LocationInit( sp ),