Add a bot type identifier.
This commit is contained in:
@@ -106,8 +106,9 @@ namespace OpenRA
|
||||
Color = client.Color;
|
||||
if (client.Bot != null)
|
||||
{
|
||||
var botInfo = world.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().First(b => b.Type == client.Bot);
|
||||
var botsOfSameType = world.LobbyInfo.Clients.Where(c => c.Bot == client.Bot).ToArray();
|
||||
PlayerName = botsOfSameType.Length == 1 ? client.Bot : "{0} {1}".F(client.Bot, botsOfSameType.IndexOf(client) + 1);
|
||||
PlayerName = botsOfSameType.Length == 1 ? botInfo.Name : "{0} {1}".F(botInfo.Name, botsOfSameType.IndexOf(client) + 1);
|
||||
}
|
||||
else
|
||||
PlayerName = client.Name;
|
||||
@@ -139,7 +140,7 @@ namespace OpenRA
|
||||
IsBot = BotType != null;
|
||||
if (IsBot && Game.IsHost)
|
||||
{
|
||||
var logic = PlayerActor.TraitsImplementing<IBot>().FirstOrDefault(b => b.Info.Name == BotType);
|
||||
var logic = PlayerActor.TraitsImplementing<IBot>().FirstOrDefault(b => b.Info.Type == BotType);
|
||||
if (logic == null)
|
||||
Log.Write("debug", "Invalid bot type: {0}", BotType);
|
||||
else
|
||||
|
||||
@@ -337,7 +337,12 @@ namespace OpenRA.Traits
|
||||
public interface IWorldLoaded { void WorldLoaded(World w, WorldRenderer wr); }
|
||||
public interface ICreatePlayers { void CreatePlayers(World w); }
|
||||
|
||||
public interface IBotInfo : ITraitInfoInterface { string Name { get; } }
|
||||
public interface IBotInfo : ITraitInfoInterface
|
||||
{
|
||||
string Type { get; }
|
||||
string Name { get; }
|
||||
}
|
||||
|
||||
public interface IBot
|
||||
{
|
||||
void Activate(Player p);
|
||||
|
||||
@@ -15,9 +15,15 @@ namespace OpenRA.Mods.Common.AI
|
||||
{
|
||||
public sealed class DummyAIInfo : ITraitInfo, IBotInfo
|
||||
{
|
||||
[Desc("Ingame name this bot uses.")]
|
||||
[Desc("Human-readable name this bot uses.")]
|
||||
public readonly string Name = "Unnamed Bot";
|
||||
|
||||
[FieldLoader.Require]
|
||||
[Desc("Internal id for this bot.")]
|
||||
public readonly string Type = null;
|
||||
|
||||
string IBotInfo.Type { get { return Type; } }
|
||||
|
||||
string IBotInfo.Name { get { return Name; } }
|
||||
|
||||
public object Create(ActorInitializer init) { return new DummyAI(this); }
|
||||
|
||||
@@ -58,7 +58,11 @@ namespace OpenRA.Mods.Common.AI
|
||||
public readonly HashSet<string> Silo = new HashSet<string>();
|
||||
}
|
||||
|
||||
[Desc("Ingame name this bot uses.")]
|
||||
[FieldLoader.Require]
|
||||
[Desc("Internal id for this bot.")]
|
||||
public readonly string Type = null;
|
||||
|
||||
[Desc("Human-readable name this bot uses.")]
|
||||
public readonly string Name = "Unnamed Bot";
|
||||
|
||||
[Desc("Minimum number of units AI must have before attacking.")]
|
||||
@@ -162,8 +166,6 @@ namespace OpenRA.Mods.Common.AI
|
||||
[Desc("Should the AI repair its buildings if damaged?")]
|
||||
public readonly bool ShouldRepairBuildings = true;
|
||||
|
||||
string IBotInfo.Name { get { return Name; } }
|
||||
|
||||
[Desc("What units to the AI should build.", "What % of the total army must be this type of unit.")]
|
||||
public readonly Dictionary<string, float> UnitsToBuild = null;
|
||||
|
||||
@@ -233,6 +235,10 @@ namespace OpenRA.Mods.Common.AI
|
||||
return ret;
|
||||
}
|
||||
|
||||
string IBotInfo.Type { get { return Type; } }
|
||||
|
||||
string IBotInfo.Name { get { return Name; } }
|
||||
|
||||
public object Create(ActorInitializer init) { return new HackyAI(this, init); }
|
||||
}
|
||||
|
||||
|
||||
@@ -280,8 +280,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
return false;
|
||||
}
|
||||
|
||||
var botType = parts.Skip(2).JoinWith(" ");
|
||||
|
||||
// Invalid slot
|
||||
if (bot != null && bot.Bot == null)
|
||||
{
|
||||
@@ -289,6 +287,16 @@ namespace OpenRA.Mods.Common.Server
|
||||
return true;
|
||||
}
|
||||
|
||||
var botType = parts[2];
|
||||
var botInfo = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>()
|
||||
.FirstOrDefault(b => b.Type == botType);
|
||||
|
||||
if (botInfo == null)
|
||||
{
|
||||
server.SendOrderTo(conn, "Message", "Invalid bot type.");
|
||||
return true;
|
||||
}
|
||||
|
||||
slot.Closed = false;
|
||||
if (bot == null)
|
||||
{
|
||||
@@ -296,7 +304,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
bot = new Session.Client()
|
||||
{
|
||||
Index = server.ChooseFreePlayerIndex(),
|
||||
Name = botType,
|
||||
Name = botInfo.Name,
|
||||
Bot = botType,
|
||||
Slot = parts[0],
|
||||
Faction = "Random",
|
||||
@@ -319,7 +327,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
else
|
||||
{
|
||||
// Change the type of the existing bot
|
||||
bot.Name = botType;
|
||||
bot.Name = botInfo.Name;
|
||||
bot.Bot = botType;
|
||||
}
|
||||
|
||||
@@ -366,7 +374,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
// - Players who now lack a slot are made observers
|
||||
// - Bots who now lack a slot are dropped
|
||||
// - Bots who are not defined in the map rules are dropped
|
||||
var botNames = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
|
||||
var botTypes = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Type);
|
||||
var slots = server.LobbyInfo.Slots.Keys.ToArray();
|
||||
var i = 0;
|
||||
foreach (var os in oldSlots)
|
||||
@@ -380,7 +388,7 @@ namespace OpenRA.Mods.Common.Server
|
||||
if (c.Slot != null)
|
||||
{
|
||||
// Remove Bot from slot if slot forbids bots
|
||||
if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botNames.Contains(c.Bot)))
|
||||
if (c.Bot != null && (!server.Map.Players.Players[c.Slot].AllowBots || !botTypes.Contains(c.Bot)))
|
||||
server.LobbyInfo.Clients.Remove(c);
|
||||
S.SyncClientToPlayerReference(c, server.Map.Players.Players[c.Slot]);
|
||||
}
|
||||
|
||||
@@ -808,6 +808,19 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
}
|
||||
}
|
||||
|
||||
// Bots must now specify an internal type as well as their display name
|
||||
if (engineVersion < 20170707)
|
||||
{
|
||||
if (node.Key.StartsWith("HackyAI", StringComparison.Ordinal) || node.Key.StartsWith("DummyAI", StringComparison.Ordinal))
|
||||
{
|
||||
var nameNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Name");
|
||||
|
||||
// Just duplicate the name to avoid incompatibility with maps
|
||||
if (nameNode != null)
|
||||
node.Value.Nodes.Add(new MiniYamlNode("Type", nameNode.Value.Value));
|
||||
}
|
||||
}
|
||||
|
||||
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
slotsButton.OnMouseDown = _ =>
|
||||
{
|
||||
var botNames = map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
|
||||
var botTypes = map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Type);
|
||||
var options = new Dictionary<string, IEnumerable<DropDownOption>>();
|
||||
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
@@ -215,7 +215,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
foreach (var slot in orderManager.LobbyInfo.Slots)
|
||||
{
|
||||
var bot = botNames.Random(Game.CosmeticRandom);
|
||||
var bot = botTypes.Random(Game.CosmeticRandom);
|
||||
var c = orderManager.LobbyInfo.ClientInSlot(slot.Key);
|
||||
if (slot.Value.AllowBots == true && (c == null || c.Bot != null))
|
||||
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot.Key, botController.Index, bot)));
|
||||
@@ -621,7 +621,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (addBotOnMapLoad)
|
||||
{
|
||||
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
|
||||
var bot = currentMap.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name).FirstOrDefault();
|
||||
var bot = currentMap.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Type).FirstOrDefault();
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
if (slot != null && bot != null)
|
||||
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
|
||||
|
||||
@@ -50,13 +50,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var bots = new List<SlotDropDownOption>();
|
||||
if (slot.AllowBots)
|
||||
{
|
||||
foreach (var b in map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name))
|
||||
foreach (var b in map.Rules.Actors["player"].TraitInfos<IBotInfo>())
|
||||
{
|
||||
var bot = b;
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
bots.Add(new SlotDropDownOption(bot,
|
||||
"slot_bot {0} {1} {2}".F(slot.PlayerReference, botController.Index, bot),
|
||||
() => client != null && client.Bot == bot));
|
||||
bots.Add(new SlotDropDownOption(b.Name,
|
||||
"slot_bot {0} {1} {2}".F(slot.PlayerReference, botController.Index, b.Type),
|
||||
() => client != null && client.Bot == b.Type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Player:
|
||||
HackyAI@Cabal:
|
||||
Name: Cabal
|
||||
Type: Cabal
|
||||
MinimumExcessPower: 60
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
@@ -122,6 +123,7 @@ Player:
|
||||
CheckRadius: 7c0
|
||||
HackyAI@Watson:
|
||||
Name: Watson
|
||||
Type: Watson
|
||||
MinimumExcessPower: 60
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
@@ -243,6 +245,7 @@ Player:
|
||||
CheckRadius: 7c0
|
||||
HackyAI@HAL9001:
|
||||
Name: HAL 9001
|
||||
Type: HAL 9001
|
||||
MinimumExcessPower: 60
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Player:
|
||||
HackyAI@Omnius:
|
||||
Name: Omnius
|
||||
Type: Omnius
|
||||
MinimumExcessPower: 60
|
||||
BuildingQueues: Building, Upgrade
|
||||
UnitQueues: Infantry, Vehicle, Armor, Starport, Aircraft
|
||||
@@ -119,6 +120,7 @@ Player:
|
||||
Against: Ally
|
||||
HackyAI@Vidius:
|
||||
Name: Vidious
|
||||
Type: Vidious
|
||||
MinimumExcessPower: 60
|
||||
BuildingQueues: Building, Upgrade
|
||||
UnitQueues: Infantry, Vehicle, Armor, Starport, Aircraft
|
||||
@@ -239,6 +241,7 @@ Player:
|
||||
Against: Ally
|
||||
HackyAI@Gladius:
|
||||
Name: Gladius
|
||||
Type: Gladius
|
||||
MinimumExcessPower: 60
|
||||
BuildingQueues: Building, Upgrade
|
||||
UnitQueues: Infantry, Vehicle, Armor, Starport, Aircraft
|
||||
|
||||
@@ -100,6 +100,7 @@ Player:
|
||||
-HackyAI@TurtleAI:
|
||||
DummyAI@LonestarAI:
|
||||
Name: Lonestar AI
|
||||
Type: Lonestar AI
|
||||
|
||||
^Infantry:
|
||||
Inherits@IC: ^IronCurtainable
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Player:
|
||||
HackyAI@RushAI:
|
||||
Name: Rush AI
|
||||
Type: Rush AI
|
||||
MinimumExcessPower: 40
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
@@ -114,6 +115,7 @@ Player:
|
||||
CheckRadius: 7c0
|
||||
HackyAI@NormalAI:
|
||||
Name: Normal AI
|
||||
Type: Normal AI
|
||||
MinimumExcessPower: 60
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
@@ -245,6 +247,7 @@ Player:
|
||||
CheckRadius: 7c0
|
||||
HackyAI@TurtleAI:
|
||||
Name: Turtle AI
|
||||
Type: Turtle AI
|
||||
MinimumExcessPower: 100
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
@@ -376,6 +379,7 @@ Player:
|
||||
CheckRadius: 7c0
|
||||
HackyAI@NavalAI:
|
||||
Name: Naval AI
|
||||
Type: Naval AI
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: fact
|
||||
Refinery: proc
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Player:
|
||||
HackyAI@TestAI:
|
||||
Name: Test AI
|
||||
Type: Test AI
|
||||
MinimumExcessPower: 60
|
||||
BuildingCommonNames:
|
||||
ConstructionYard: gacnst
|
||||
|
||||
Reference in New Issue
Block a user