Expose player names to localization.
This commit is contained in:
committed by
Gustas
parent
9a46f3053a
commit
4e5556dccc
@@ -19,6 +19,9 @@ namespace OpenRA
|
||||
{
|
||||
public class GameInformation
|
||||
{
|
||||
[TranslationReference("name", "number")]
|
||||
const string EnumeratedBotName = "enumerated-bot-name";
|
||||
|
||||
public string Mod;
|
||||
public string Version;
|
||||
|
||||
@@ -118,6 +121,7 @@ namespace OpenRA
|
||||
Name = runtimePlayer.PlayerName,
|
||||
IsHuman = !runtimePlayer.IsBot,
|
||||
IsBot = runtimePlayer.IsBot,
|
||||
BotType = runtimePlayer.BotType,
|
||||
FactionName = runtimePlayer.Faction.Name,
|
||||
FactionId = runtimePlayer.Faction.InternalName,
|
||||
DisplayFactionName = runtimePlayer.DisplayFaction.Name,
|
||||
@@ -143,6 +147,20 @@ namespace OpenRA
|
||||
return player;
|
||||
}
|
||||
|
||||
public string ResolvedPlayerName(Player player)
|
||||
{
|
||||
if (player.IsBot)
|
||||
{
|
||||
var number = Players.Where(p => p.BotType == player.BotType).ToList().IndexOf(player) + 1;
|
||||
return TranslationProvider.GetString(EnumeratedBotName,
|
||||
Translation.Arguments(
|
||||
"name", TranslationProvider.GetString(player.Name),
|
||||
"number", number));
|
||||
}
|
||||
|
||||
return player.Name;
|
||||
}
|
||||
|
||||
public class Player
|
||||
{
|
||||
#region Start-up information
|
||||
@@ -153,6 +171,7 @@ namespace OpenRA
|
||||
public string Name;
|
||||
public bool IsHuman;
|
||||
public bool IsBot;
|
||||
public string BotType;
|
||||
|
||||
/// <summary>The faction's display name.</summary>
|
||||
public string FactionName;
|
||||
|
||||
@@ -465,7 +465,7 @@ namespace OpenRA
|
||||
public override string ToString()
|
||||
{
|
||||
return $"OrderString: \"{OrderString}\" \n\t Type: \"{Type}\". \n\t Subject: \"{Subject}\". \n\t Target: \"{Target}\"." +
|
||||
$"\n\t TargetString: \"{TargetString}\".\n\t IsImmediate: {IsImmediate}.\n\t Player(PlayerName): {Player?.PlayerName}\n";
|
||||
$"\n\t TargetString: \"{TargetString}\".\n\t IsImmediate: {IsImmediate}.\n\t Player(PlayerName): {Player?.ResolvedPlayerName}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ namespace OpenRA
|
||||
|
||||
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
|
||||
{
|
||||
[TranslationReference("name", "number")]
|
||||
const string EnumeratedBotName = "enumerated-bot-name";
|
||||
|
||||
public readonly Actor PlayerActor;
|
||||
public readonly string PlayerName;
|
||||
public readonly string InternalName;
|
||||
@@ -80,6 +83,9 @@ namespace OpenRA
|
||||
readonly IUnlocksRenderPlayer[] unlockRenderPlayer;
|
||||
readonly INotifyPlayerDisconnected[] notifyDisconnected;
|
||||
|
||||
readonly IReadOnlyCollection<IBotInfo> botInfos;
|
||||
string resolvedPlayerName;
|
||||
|
||||
// Each player is identified with a unique bit in the set
|
||||
// Cache masks for the player's index and ally/enemy player indices for performance.
|
||||
public LongBitSet<PlayerBitMask> PlayerMask;
|
||||
@@ -97,6 +103,16 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The chosen player name including localized and enumerated bot names.</summary>
|
||||
public string ResolvedPlayerName
|
||||
{
|
||||
get
|
||||
{
|
||||
resolvedPlayerName ??= ResolvePlayerName();
|
||||
return resolvedPlayerName;
|
||||
}
|
||||
}
|
||||
|
||||
public static FactionInfo ResolveFaction(
|
||||
string factionName, IEnumerable<FactionInfo> factionInfos, MersenneTwister playerRandom, bool requireSelectable = true)
|
||||
{
|
||||
@@ -133,18 +149,6 @@ namespace OpenRA
|
||||
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
|
||||
}
|
||||
|
||||
public static string ResolvePlayerName(Session.Client client, IEnumerable<Session.Client> clients, IEnumerable<IBotInfo> botInfos)
|
||||
{
|
||||
if (client.Bot != null)
|
||||
{
|
||||
var botInfo = botInfos.First(b => b.Type == client.Bot);
|
||||
var botsOfSameType = clients.Where(c => c.Bot == client.Bot).ToArray();
|
||||
return botsOfSameType.Length == 1 ? botInfo.Name : $"{botInfo.Name} {botsOfSameType.IndexOf(client) + 1}";
|
||||
}
|
||||
|
||||
return client.Name;
|
||||
}
|
||||
|
||||
public Player(World world, Session.Client client, PlayerReference pr, MersenneTwister playerRandom)
|
||||
{
|
||||
World = world;
|
||||
@@ -152,6 +156,7 @@ namespace OpenRA
|
||||
PlayerReference = pr;
|
||||
|
||||
inMissionMap = world.Map.Visibility.HasFlag(MapVisibility.MissionSelector);
|
||||
botInfos = World.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>();
|
||||
|
||||
// Real player or host-created bot
|
||||
if (client != null)
|
||||
@@ -159,7 +164,7 @@ namespace OpenRA
|
||||
ClientIndex = client.Index;
|
||||
color = client.Color;
|
||||
Color = color;
|
||||
PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>());
|
||||
PlayerName = client.Name;
|
||||
|
||||
BotType = client.Bot;
|
||||
Faction = ResolveFaction(world, client.Faction, playerRandom, !pr.LockFaction);
|
||||
@@ -224,7 +229,21 @@ namespace OpenRA
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{PlayerName} ({ClientIndex})";
|
||||
return $"{ResolvedPlayerName} ({ClientIndex})";
|
||||
}
|
||||
|
||||
string ResolvePlayerName()
|
||||
{
|
||||
if (IsBot)
|
||||
{
|
||||
var botInfo = botInfos.First(b => b.Type == BotType);
|
||||
var botsOfSameType = World.Players.Where(c => c.BotType == BotType).ToArray();
|
||||
return TranslationProvider.GetString(EnumeratedBotName,
|
||||
Translation.Arguments("name", TranslationProvider.GetString(botInfo.Name),
|
||||
"number", botsOfSameType.IndexOf(this) + 1));
|
||||
}
|
||||
|
||||
return PlayerName;
|
||||
}
|
||||
|
||||
public PlayerRelationship RelationshipWith(Player other)
|
||||
@@ -310,7 +329,7 @@ namespace OpenRA
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime)
|
||||
{
|
||||
return $"Player ({PlayerName})";
|
||||
return $"Player ({ResolvedPlayerName})";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace OpenRA.Scripting
|
||||
readonly Player player;
|
||||
|
||||
protected override string DuplicateKeyError(string memberName) =>
|
||||
$"Player '{player.PlayerName}' defines the command '{memberName}' on multiple traits";
|
||||
$"Player '{player.ResolvedPlayerName}' defines the command '{memberName}' on multiple traits";
|
||||
protected override string MemberNotFoundError(string memberName) =>
|
||||
$"Player '{player.PlayerName}' does not define a property '{memberName}'";
|
||||
$"Player '{player.ResolvedPlayerName}' does not define a property '{memberName}'";
|
||||
|
||||
public ScriptPlayerInterface(ScriptContext context, Player player)
|
||||
: base(context)
|
||||
|
||||
@@ -1323,7 +1323,7 @@ namespace OpenRA.Server
|
||||
foreach (var cmpi in Map.WorldActorInfo.TraitInfos<ICreatePlayersInfo>())
|
||||
cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom);
|
||||
|
||||
gameInfo = new GameInformation
|
||||
gameInfo = new GameInformation()
|
||||
{
|
||||
Mod = Game.ModData.Manifest.Id,
|
||||
Version = Game.ModData.Manifest.Metadata.Version,
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
public string InternalName => Player.InternalName;
|
||||
|
||||
[Desc("The player's name.")]
|
||||
public string Name => Player.PlayerName;
|
||||
public string Name => Player.ResolvedPlayerName;
|
||||
|
||||
[Desc("The player's color.")]
|
||||
public Color Color => Player.GetColor(Player);
|
||||
|
||||
@@ -83,14 +83,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
if (powerDecision == null)
|
||||
{
|
||||
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, sp.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {sp.Info.OrderName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var attackLocation = FindCoarseAttackLocationToSupportPower(sp);
|
||||
if (attackLocation == null)
|
||||
{
|
||||
AIUtils.BotDebug("{0} can't find suitable coarse attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} can't find suitable coarse attack location for support power {sp.Info.OrderName}. Delaying rescan.");
|
||||
waitingPowers[sp] += powerDecision.GetNextScanTime(world);
|
||||
|
||||
continue;
|
||||
@@ -100,14 +100,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
attackLocation = FindFineAttackLocationToSupportPower(sp, (CPos)attackLocation);
|
||||
if (attackLocation == null)
|
||||
{
|
||||
AIUtils.BotDebug("{0} can't find suitable final attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} can't find suitable final attack location for support power {sp.Info.OrderName}. Delaying rescan.");
|
||||
waitingPowers[sp] += powerDecision.GetNextScanTime(world);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Valid target found, delay by a few ticks to avoid rescanning before power fires via order
|
||||
AIUtils.BotDebug("{0} found new target location {1} for support power {2}.", player.PlayerName, attackLocation, sp.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} found new target location {attackLocation} for support power {sp.Info.OrderName}.");
|
||||
waitingPowers[sp] += 10;
|
||||
|
||||
// Note: SelectDirectionalTarget uses uint.MaxValue in ExtraData to indicate that the player did not pick a direction.
|
||||
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var powerDecision = powerDecisions[readyPower.Info.OrderName];
|
||||
if (powerDecision == null)
|
||||
{
|
||||
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, readyPower.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {readyPower.Info.OrderName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var powerDecision = powerDecisions[readyPower.Info.OrderName];
|
||||
if (powerDecision == null)
|
||||
{
|
||||
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, readyPower.Info.OrderName);
|
||||
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {readyPower.Info.OrderName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (info.SuppressNotifications)
|
||||
return;
|
||||
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.PlayerName));
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.ResolvedPlayerName));
|
||||
Game.RunAfterDelay(info.NotificationDelay, () =>
|
||||
{
|
||||
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
|
||||
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (info.SuppressNotifications)
|
||||
return;
|
||||
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.PlayerName));
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.ResolvedPlayerName));
|
||||
Game.RunAfterDelay(info.NotificationDelay, () =>
|
||||
{
|
||||
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
|
||||
|
||||
@@ -275,7 +275,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return;
|
||||
}
|
||||
|
||||
var arguments = Translation.Arguments("cheat", order.OrderString, "player", self.Owner.PlayerName, "suffix", debugSuffix);
|
||||
var arguments = Translation.Arguments("cheat", order.OrderString, "player", self.Owner.ResolvedPlayerName, "suffix", debugSuffix);
|
||||
TextNotificationsManager.Debug(TranslationProvider.GetString(CheatUsed, arguments));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Internal id for this bot.")]
|
||||
public readonly string Type = null;
|
||||
|
||||
[TranslationReference]
|
||||
[Desc("Human-readable name this bot uses.")]
|
||||
public readonly string Name = "Unnamed Bot";
|
||||
public readonly string Name = null;
|
||||
|
||||
[Desc("Minimum portion of pending orders to issue each tick (e.g. 5 issues at least 1/5th of all pending orders). " +
|
||||
"Excess orders remain queued for subsequent ticks.")]
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (info.SuppressNotifications)
|
||||
return;
|
||||
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.PlayerName));
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.ResolvedPlayerName));
|
||||
Game.RunAfterDelay(info.NotificationDelay, () =>
|
||||
{
|
||||
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
|
||||
@@ -167,7 +167,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (info.SuppressNotifications)
|
||||
return;
|
||||
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.PlayerName));
|
||||
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.ResolvedPlayerName));
|
||||
Game.RunAfterDelay(info.NotificationDelay, () =>
|
||||
{
|
||||
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
font = Game.Renderer.Fonts[info.Font];
|
||||
this.info = info;
|
||||
|
||||
name = self.Owner.PlayerName;
|
||||
name = self.Owner.ResolvedPlayerName;
|
||||
if (name.Length > info.MaxLength)
|
||||
name = name[..info.MaxLength];
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||
{
|
||||
name = self.Owner.PlayerName;
|
||||
name = self.Owner.ResolvedPlayerName;
|
||||
if (name.Length > Info.MaxLength)
|
||||
name = name[..Info.MaxLength];
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var player = new GameInformation.Player
|
||||
{
|
||||
ClientIndex = client.Index,
|
||||
Name = Player.ResolvePlayerName(client, lobbyInfo.Clients, bots),
|
||||
Name = client.Name,
|
||||
IsHuman = client.Bot == null,
|
||||
IsBot = client.Bot != null,
|
||||
FactionName = resolvedFaction.Name,
|
||||
|
||||
@@ -30,7 +30,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
if (subjectClient == null)
|
||||
{
|
||||
Log.Write("debug", $"Tick {world.WorldTick}: Order sent to {order.Subject.Owner.PlayerName}: resolved ClientIndex `{subjectClientId}` doesn't exist");
|
||||
Log.Write("debug", $"Tick {world.WorldTick}: " +
|
||||
$"Order sent to {order.Subject.Owner.ResolvedPlayerName}: " +
|
||||
$"resolved ClientIndex `{subjectClientId}` doesn't exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
TextNotificationsManager.MutedPlayers.Add(c.Index, false);
|
||||
|
||||
tabCompletion.Commands = chatTraits.OfType<ChatCommands>().ToArray().SelectMany(x => x.Commands.Keys);
|
||||
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
|
||||
tabCompletion.Names = orderManager.LobbyInfo.Clients.Where(c => !c.IsBot).Select(c => c.Name).Distinct().ToList();
|
||||
|
||||
if (logicArgs.TryGetValue("Templates", out var templateIds))
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
public CameraOption(ObserverShroudSelectorLogic logic, Player p)
|
||||
{
|
||||
Player = p;
|
||||
Label = p.PlayerName;
|
||||
Label = p.ResolvedPlayerName;
|
||||
Color = p.Color;
|
||||
Faction = p.Faction.InternalName;
|
||||
IsSelected = () => p.World.RenderPlayer == p;
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
incomeGraph.GetSeries = () =>
|
||||
players.Select(p => new LineGraphSeries(
|
||||
p.PlayerName,
|
||||
p.ResolvedPlayerName,
|
||||
p.Color,
|
||||
(p.PlayerActor.TraitOrDefault<PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).IncomeSamples.Select(s => (float)s)));
|
||||
}
|
||||
@@ -271,7 +271,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
armyValueGraph.GetSeries = () =>
|
||||
players.Select(p => new LineGraphSeries(
|
||||
p.PlayerName,
|
||||
p.ResolvedPlayerName,
|
||||
p.Color,
|
||||
(p.PlayerActor.TraitOrDefault<PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).ArmySamples.Select(s => (float)s)));
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (showOwner)
|
||||
{
|
||||
flagFaction = o.Faction.InternalName;
|
||||
ownerName = o.PlayerName;
|
||||
ownerName = o.ResolvedPlayerName;
|
||||
widget.Bounds.Height = doubleHeight;
|
||||
widget.Bounds.Width = Math.Max(widget.Bounds.Width,
|
||||
owner.Bounds.X + ownerFont.Measure(ownerName).X + label.Bounds.X);
|
||||
|
||||
@@ -853,7 +853,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
while (players.Children.Count > idx)
|
||||
players.RemoveChild(players.Children[idx]);
|
||||
|
||||
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
|
||||
tabCompletion.Names = orderManager.LobbyInfo.Clients.Where(c => !c.IsBot).Select(c => c.Name).Distinct().ToList();
|
||||
}
|
||||
|
||||
void UpdateDiscordStatus()
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
foreach (var b in map.PlayerActorInfo.TraitInfos<IBotInfo>())
|
||||
{
|
||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||
bots.Add(new SlotDropDownOption(b.Name,
|
||||
bots.Add(new SlotDropDownOption(TranslationProvider.GetString(b.Name),
|
||||
$"slot_bot {slot.PlayerReference} {botController.Index} {b.Type}",
|
||||
() => client != null && client.Bot == b.Type));
|
||||
}
|
||||
@@ -422,11 +422,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
public static void SetupNameWidget(Widget parent, Session.Client c, OrderManager orderManager, WorldRenderer worldRenderer)
|
||||
{
|
||||
var name = parent.Get<LabelWidget>("NAME");
|
||||
name.IsVisible = () => true;
|
||||
var font = Game.Renderer.Fonts[name.Font];
|
||||
var label = WidgetUtils.TruncateText(c.Name, name.Bounds.Width, font);
|
||||
name.GetText = () => label;
|
||||
var label = parent.Get<LabelWidget>("NAME");
|
||||
label.IsVisible = () => true;
|
||||
var font = Game.Renderer.Fonts[label.Font];
|
||||
var name = c.IsBot ? TranslationProvider.GetString(c.Name) : c.Name;
|
||||
var text = WidgetUtils.TruncateText(name, label.Bounds.Width, font);
|
||||
label.GetText = () => text;
|
||||
|
||||
SetupProfileWidget(parent, c, orderManager, worldRenderer);
|
||||
}
|
||||
@@ -444,7 +445,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var closed = TranslationProvider.GetString(Closed);
|
||||
var open = TranslationProvider.GetString(Open);
|
||||
slot.GetText = () => truncated.Update(c != null ? c.Name : s.Closed ? closed : open);
|
||||
slot.GetText = () => truncated.Update(c != null ?
|
||||
c.IsBot ? TranslationProvider.GetString(c.Name) : c.Name
|
||||
: s.Closed ? closed : open);
|
||||
|
||||
slot.OnMouseDown = _ => ShowSlotDropDown(slot, s, c, orderManager, map, modData);
|
||||
|
||||
// Ensure Name selector (if present) is hidden
|
||||
|
||||
@@ -407,7 +407,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_PLAYER_DROPDOWNBUTTON");
|
||||
if (ddb != null)
|
||||
{
|
||||
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => r.GameInfo.ResolvedPlayerName(p)))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
options.Sort(StringComparer.OrdinalIgnoreCase);
|
||||
options.Insert(0, null); // no filter
|
||||
|
||||
@@ -666,7 +668,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (!string.IsNullOrEmpty(filter.PlayerName))
|
||||
{
|
||||
var player = replay.GameInfo.Players.FirstOrDefault(
|
||||
p => string.Equals(filter.PlayerName, p.Name, StringComparison.CurrentCultureIgnoreCase));
|
||||
p => string.Equals(filter.PlayerName, replay.GameInfo.ResolvedPlayerName(p), StringComparison.CurrentCultureIgnoreCase));
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
@@ -751,7 +753,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var label = item.Get<LabelWidget>("LABEL");
|
||||
var font = Game.Renderer.Fonts[label.Font];
|
||||
var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font);
|
||||
var name = WidgetUtils.TruncateText(replay.GameInfo.ResolvedPlayerName(o), label.Bounds.Width, font);
|
||||
label.GetText = () => name;
|
||||
label.GetColor = () => color;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
public SpawnOccupant(Session.Client client)
|
||||
{
|
||||
Color = client.Color;
|
||||
PlayerName = client.Name;
|
||||
PlayerName = client.IsBot ? TranslationProvider.GetString(client.Name) : client.Name;;
|
||||
Team = client.Team;
|
||||
Faction = client.Faction;
|
||||
SpawnPoint = client.SpawnPoint;
|
||||
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
public SpawnOccupant(GameInformation.Player player)
|
||||
{
|
||||
Color = player.Color;
|
||||
PlayerName = player.Name;
|
||||
PlayerName = player.IsBot ? TranslationProvider.GetString(player.Name) : player.Name;
|
||||
Team = player.Team;
|
||||
Faction = player.FactionId;
|
||||
SpawnPoint = player.SpawnPoint;
|
||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
public SpawnOccupant(GameClient player, bool suppressFaction)
|
||||
{
|
||||
Color = player.Color;
|
||||
PlayerName = player.Name;
|
||||
PlayerName = player.IsBot ? TranslationProvider.GetString(player.Name) : player.Name;
|
||||
Team = player.Team;
|
||||
Faction = !suppressFaction ? player.Faction : null;
|
||||
SpawnPoint = player.SpawnPoint;
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
var self = p.Instances[0].Self;
|
||||
var time = WidgetUtils.FormatTime(p.RemainingTicks, false, self.World.Timestep);
|
||||
var text = TranslationProvider.GetString(Format, Translation.Arguments("player", self.Owner.PlayerName, "support-power", p.Name, "time", time));
|
||||
var text = TranslationProvider.GetString(Format, Translation.Arguments("player", self.Owner.ResolvedPlayerName, "support-power", p.Name, "time", time));
|
||||
|
||||
var color = !p.Ready || Game.LocalTick % 50 < 25 ? self.OwnerColor() : Color.White;
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public static class WidgetUtils
|
||||
{
|
||||
[TranslationReference]
|
||||
const string Gone = "label-client-state-disconnected";
|
||||
|
||||
[TranslationReference]
|
||||
const string Won = "label-win-state-won";
|
||||
|
||||
[TranslationReference]
|
||||
const string Lost = "label-win-state-lost";
|
||||
|
||||
public static string GetStatefulImageName(
|
||||
string baseName, bool disabled = false, bool pressed = false, bool hover = false, bool focused = false)
|
||||
{
|
||||
@@ -324,19 +333,29 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
var client = p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
|
||||
var nameFont = Game.Renderer.Fonts[label.Font];
|
||||
var name = new CachedTransform<(string Name, WinState WinState, Session.ClientState ClientState), string>(c =>
|
||||
var name = new CachedTransform<(WinState WinState, Session.ClientState ClientState), string>(c =>
|
||||
{
|
||||
var suffix = c.WinState == WinState.Undefined ? "" : " (" + c.WinState + ")";
|
||||
if (c.ClientState == Session.ClientState.Disconnected)
|
||||
suffix = " (Gone)";
|
||||
var text = p.ResolvedPlayerName;
|
||||
|
||||
return TruncateText(c.Name, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix;
|
||||
var suffix = "";
|
||||
if (c.WinState == WinState.Won)
|
||||
suffix = $" ({TranslationProvider.GetString(Won)})";
|
||||
else if (c.WinState == WinState.Lost)
|
||||
suffix = $" ({TranslationProvider.GetString(Lost)})";
|
||||
|
||||
if (client.State == Session.ClientState.Disconnected)
|
||||
suffix = $" ({TranslationProvider.GetString(Gone)})";
|
||||
|
||||
text += suffix;
|
||||
|
||||
var size = nameFont.Measure(text) - nameFont.Measure(p.ResolvedPlayerName);
|
||||
return TruncateText(text, label.Bounds.Width - size.X, nameFont);
|
||||
});
|
||||
|
||||
label.GetText = () =>
|
||||
{
|
||||
var clientState = client != null ? client.State : Session.ClientState.Ready;
|
||||
return name.Update((p.PlayerName, p.WinState, clientState));
|
||||
return name.Update((p.WinState, clientState));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ options-difficulty =
|
||||
.normal = Normal
|
||||
.hard = Hard
|
||||
|
||||
## player
|
||||
bot-campaign-ai =
|
||||
.name = Campaign Player AI
|
||||
|
||||
## campaign-maprules.yaml
|
||||
actor-moneycrate-name = Money Crate
|
||||
|
||||
|
||||
@@ -559,3 +559,13 @@ actor-truck =
|
||||
Builds fast
|
||||
Unarmed
|
||||
.name = Supply Truck
|
||||
|
||||
## ai.yaml
|
||||
bot-cabal =
|
||||
.name = Cabal
|
||||
|
||||
bot-watson =
|
||||
.name = Watson
|
||||
|
||||
bot-hal9001 =
|
||||
.name = HAL 9001
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Player:
|
||||
ModularBot@Cabal:
|
||||
Name: Cabal
|
||||
Name: bot-cabal.name
|
||||
Type: cabal
|
||||
ModularBot@Watson:
|
||||
Name: Watson
|
||||
Name: bot-watson.name
|
||||
Type: watson
|
||||
ModularBot@HAL9001:
|
||||
Name: HAL 9001
|
||||
Name: bot-hal9001.name
|
||||
Type: hal9001
|
||||
GrantConditionOnBotOwner@cabal:
|
||||
Condition: enable-cabal-ai
|
||||
|
||||
@@ -51,7 +51,7 @@ Player:
|
||||
DeveloperMode:
|
||||
CheckboxVisible: False
|
||||
ModularBot@CampaignAI:
|
||||
Name: Campaign Player AI
|
||||
Name: bot-campaign-ai.name
|
||||
Type: campaign
|
||||
|
||||
airstrike.proxy:
|
||||
|
||||
@@ -860,3 +860,14 @@ notification-desync-compare-logs = Out of sync in frame { $frame }.
|
||||
|
||||
## SupportPowerTimerWidget
|
||||
support-power-timer = { $player }'s { $support-power }: { $time }
|
||||
|
||||
## WidgetUtils
|
||||
label-win-state-won = Won
|
||||
label-win-state-lost = Lost
|
||||
|
||||
## Player
|
||||
enumerated-bot-name =
|
||||
{ $name } { $number ->
|
||||
*[zero] {""}
|
||||
[other] { $number }
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ options-difficulty =
|
||||
.normal = Normal
|
||||
.hard = Hard
|
||||
|
||||
## player
|
||||
bot-campaign-ai =
|
||||
.name = Campaign Player AI
|
||||
|
||||
## campaign-tooltips.yaml
|
||||
neutral-prefix = Neutral
|
||||
|
||||
|
||||
@@ -569,3 +569,13 @@ meta-destroyabletile =
|
||||
meta-destroyedtile =
|
||||
.generic-name = Passage (repairable)
|
||||
.name = Passage (repairable)
|
||||
|
||||
## ai.yaml
|
||||
bot-omnius =
|
||||
.name = Omnius
|
||||
|
||||
bot-vidius =
|
||||
.name = Vidious
|
||||
|
||||
bot-gladius =
|
||||
.name = Gladius
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Player:
|
||||
ModularBot@Omnius:
|
||||
Name: Omnius
|
||||
Name: bot-omnius.name
|
||||
Type: omnius
|
||||
ModularBot@Vidius:
|
||||
Name: Vidious
|
||||
Name: bot-vidius.name
|
||||
Type: vidious
|
||||
ModularBot@Gladius:
|
||||
Name: Gladius
|
||||
Name: bot-gladius.name
|
||||
Type: gladius
|
||||
GrantConditionOnBotOwner@omnius:
|
||||
Condition: enable-omnius-ai
|
||||
|
||||
@@ -20,7 +20,7 @@ Player:
|
||||
DeveloperMode:
|
||||
CheckboxVisible: False
|
||||
ModularBot@CampaignAI:
|
||||
Name: Campaign Player AI
|
||||
Name: bot-campaign-ai.name
|
||||
Type: campaign
|
||||
|
||||
World:
|
||||
|
||||
@@ -8,6 +8,10 @@ options-difficulty =
|
||||
.normal = Normal
|
||||
.hard = Hard
|
||||
|
||||
## player
|
||||
bot-campaign-ai =
|
||||
.name = Campaign Player AI
|
||||
|
||||
## campaign-rules.yaml
|
||||
actor-crate-name = Crate
|
||||
|
||||
|
||||
@@ -849,3 +849,16 @@ actor-powerproxy-paratroopers =
|
||||
.name = Paratroopers
|
||||
.description = A Badger drops a squad of infantry
|
||||
anywhere on the map.
|
||||
|
||||
## ai.yaml
|
||||
bot-rush-ai =
|
||||
.name = Rush AI
|
||||
|
||||
bot-normal-ai =
|
||||
.name = Normal AI
|
||||
|
||||
bot-turtle-ai =
|
||||
.name = Turtle AI
|
||||
|
||||
bot-naval-ai =
|
||||
.name = Naval AI
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Player:
|
||||
ModularBot@RushAI:
|
||||
Name: Rush AI
|
||||
Name: bot-rush-ai.name
|
||||
Type: rush
|
||||
ModularBot@NormalAI:
|
||||
Name: Normal AI
|
||||
Name: bot-normal-ai.name
|
||||
Type: normal
|
||||
ModularBot@TurtleAI:
|
||||
Name: Turtle AI
|
||||
Name: bot-turtle-ai.name
|
||||
Type: turtle
|
||||
ModularBot@NavalAI:
|
||||
Name: Naval AI
|
||||
Name: bot-naval-ai.name
|
||||
Type: naval
|
||||
GrantConditionOnBotOwner@rush:
|
||||
Condition: enable-rush-ai
|
||||
|
||||
@@ -29,7 +29,7 @@ Player:
|
||||
DeveloperMode:
|
||||
CheckboxVisible: False
|
||||
ModularBot@CampaignAI:
|
||||
Name: Campaign Player AI
|
||||
Name: bot-campaign-ai.name
|
||||
Type: campaign
|
||||
|
||||
World:
|
||||
|
||||
@@ -751,3 +751,7 @@ actor-cahosp =
|
||||
.name = Civilian Hospital
|
||||
.captured-desc = Provides infantry with self-healing.
|
||||
.capturable-desc = Capture to enable self-healing for infantry.
|
||||
|
||||
## ai.yaml
|
||||
bot-test-ai =
|
||||
.name = Test AI
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Player:
|
||||
ModularBot@TestAI:
|
||||
Name: Test AI
|
||||
ModularBot@bot-test-ai:
|
||||
Name: bot-test-ai.name
|
||||
Type: test
|
||||
GrantConditionOnBotOwner@test:
|
||||
Condition: enable-test-ai
|
||||
|
||||
Reference in New Issue
Block a user