diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs index 42a54ce8c4..3f3151a695 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs @@ -39,9 +39,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly string chatLineSound = ChromeMetrics.Get("ChatLineSound"); - bool disableTeamChat; - bool teamChat; - [ObjectCreator.UseCtor] public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat, Dictionary logicArgs) { @@ -51,8 +48,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic chatTraits = world.WorldActor.TraitsImplementing().ToArray(); var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot); - disableTeamChat = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1 || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer))); - teamChat = !disableTeamChat; + var isObserver = orderManager.LocalClient != null && orderManager.LocalClient.IsObserver; + var isOnlyObserver = isObserver && orderManager.LobbyInfo.Clients.All(c => c == orderManager.LocalClient || !c.IsObserver); + var observersExist = orderManager.LobbyInfo.Clients.Any(c => c.IsObserver); + var alwaysDisabled = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1; + var disableTeamChat = alwaysDisabled || isOnlyObserver || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer))); + var teamChat = !disableTeamChat; tabCompletion.Commands = chatTraits.OfType().SelectMany(x => x.Commands.Keys).ToList(); tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList(); @@ -71,7 +72,46 @@ namespace OpenRA.Mods.Common.Widgets.Logic var chatMode = chatChrome.Get("CHAT_MODE"); chatMode.GetText = () => teamChat ? "Team" : "All"; chatMode.OnClick = () => teamChat ^= true; - chatMode.IsDisabled = () => disableTeamChat; + + // Team chat is disabled if we are the only spectator + // This changes as soon as a defeated player can talk in the spectator chat + if (!alwaysDisabled && isOnlyObserver) + { + chatMode.IsDisabled = () => + { + if (world.IsGameOver) + return true; + + disableTeamChat = players.All(p => p.WinState == WinState.Undefined); + return disableTeamChat; + }; + } + else if (!alwaysDisabled && world.LocalPlayer != null) + { + chatMode.IsDisabled = () => + { + if (world.IsGameOver) + return true; + + // Nothing changed since the start + if (world.LocalPlayer.WinState == WinState.Undefined) + return disableTeamChat; + + // At this point our player is dead + // Allow to chat with existing spectators + if (observersExist) + { + disableTeamChat = false; + return disableTeamChat; + } + + // Or wait until another player died + disableTeamChat = players.All(p => p.WinState == WinState.Undefined); + return disableTeamChat; + }; + } + else + chatMode.IsDisabled = () => disableTeamChat; chatText = chatChrome.Get("CHAT_TEXTFIELD"); chatText.MaxLength = UnitOrders.ChatMessageMaxLength;