Example #1
0
        public override void Activate(Actor collector)
        {
            TextNotificationsManager.AddSystemLine("Battlefield Control", collector.Owner.PlayerName + " has taken the armageddon crate!");

            if (!string.IsNullOrEmpty(Info.Notification))
            {
                foreach (var player in self.World.Players)
                {
                    // Don't play it twice to the collector, it is already handled in base.Activate()
                    if (collector.Owner == player)
                    {
                        continue;
                    }

                    Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech",
                                                Info.Notification, collector.Owner.Faction.InternalName);
                }
            }

            var actors = self.World.Actors.Where(a => a.Owner.Playable && a.TraitOrDefault <SSMultiplierManager>() != null);

            foreach (var actor in actors)
            {
                actor.Kill(self, info.DeathTypes);
            }

            base.Activate(collector);
        }
Example #2
0
        void OnCrushInner(Actor crusher, int flagTeam, int crusherTeam)
        {
            if (Collected)
            {
                return;
            }

            self.World.Remove(self);
            Collected = true;

            var carriesFlag = crusher.TraitOrDefault <CarriesFlag>();

            if (carriesFlag != null)
            {
                if (self.Owner == crusher.Owner || (flagTeam != 0 && flagTeam == crusherTeam))
                {
                    TextNotificationsManager.AddSystemLine("Battlefield Control", crusher.Owner.PlayerName + " has taken their flag.");
                }
                else
                {
                    TextNotificationsManager.AddSystemLine("Battlefield Control", crusher.Owner.PlayerName + " has taken flag of " + (flagTeam == 0 || !spawner.TeamSpawns ? self.Owner.PlayerName : "Team " + flagTeam) + ".");
                }

                carriesFlag.GrantCondition(crusher);
                carriesFlag.TakeFlag(crusher, self);
            }
        }
        public override void Activate(Actor collector)
        {
            TextNotificationsManager.AddSystemLine("Battlefield Control", collector.Owner.PlayerName + " has reshrouded the map.");

            foreach (var player in collector.World.Players)
            {
                player.Shroud.ResetExploration();
            }

            base.Activate(collector);
        }
Example #4
0
        void INotifyTimeLimit.NotifyTimerExpired(Actor self)
        {
            if (countdownLabel != null)
            {
                countdownLabel.GetText = () => null;
            }

            if (!info.SkipTimerExpiredNotification)
            {
                TextNotificationsManager.AddSystemLine("Time limit has expired.");
            }
        }
Example #5
0
        void INotifyWinStateChanged.OnPlayerWon(Player player)
        {
            if (info.SuppressNotifications)
            {
                return;
            }

            TextNotificationsManager.AddSystemLine(player.PlayerName + " is victorious.");
            Game.RunAfterDelay(info.NotificationDelay, () =>
            {
                if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
                {
                    Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.WinNotification, player.Faction.InternalName);
                }
            });
        }
Example #6
0
        public void DisplaySystemMessage(string text, string prefix = null)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            if (string.IsNullOrEmpty(prefix))
            {
                TextNotificationsManager.AddSystemLine(text);
            }
            else
            {
                TextNotificationsManager.AddSystemLine(prefix, text);
            }
        }
Example #7
0
        protected override bool OnHotkeyActivated(KeyInput e)
        {
            Game.Settings.Sound.Mute ^= true;

            if (Game.Settings.Sound.Mute)
            {
                Game.Sound.MuteAudio();
                TextNotificationsManager.AddSystemLine("Audio muted");
            }
            else
            {
                Game.Sound.UnmuteAudio();
                TextNotificationsManager.AddSystemLine("Audio unmuted");
            }

            return(true);
        }
Example #8
0
        void ITick.Tick(Actor self)
        {
            if (TimeLimit <= 0)
            {
                return;
            }

            ticksRemaining = TimeLimit - self.World.WorldTick;

            if (ticksRemaining == 0)
            {
                foreach (var ntl in self.TraitsImplementing <INotifyTimeLimit>())
                {
                    ntl.NotifyTimerExpired(self);
                }

                foreach (var p in self.World.Players)
                {
                    foreach (var ntl in p.PlayerActor.TraitsImplementing <INotifyTimeLimit>())
                    {
                        ntl.NotifyTimerExpired(p.PlayerActor);
                    }
                }

                return;
            }

            if (ticksRemaining < 0 || info.SkipTimeRemainingNotifications)
            {
                return;
            }

            foreach (var m in info.TimeLimitWarnings.Keys)
            {
                if (ticksRemaining == m * 60 * ticksPerSecond)
                {
                    TextNotificationsManager.AddSystemLine(Notification.F(m, m > 1 ? "s" : null));

                    var faction = self.World.LocalPlayer == null ? null : self.World.LocalPlayer.Faction.InternalName;
                    Game.Sound.PlayNotification(self.World.Map.Rules, self.World.LocalPlayer, "Speech", info.TimeLimitWarnings[m], faction);
                }
            }
        }
Example #9
0
        void INotifyWinStateChanged.OnPlayerLost(Player player)
        {
            foreach (var a in player.World.ActorsWithTrait <INotifyOwnerLost>().Where(a => a.Actor.Owner == player))
            {
                a.Trait.OnOwnerLost(a.Actor);
            }

            if (info.SuppressNotifications)
            {
                return;
            }

            TextNotificationsManager.AddSystemLine(player.PlayerName + " is defeated.");
            Game.RunAfterDelay(info.NotificationDelay, () =>
            {
                if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
                {
                    Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.LoseNotification, player.Faction.InternalName);
                }
            });
        }
Example #10
0
        internal static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order)
        {
            switch (order.OrderString)
            {
            // Server message
            case "Message":
                TextNotificationsManager.AddSystemLine(order.TargetString);
                break;

            case "DisableChatEntry":
            {
                // Order must originate from the server
                if (clientId != 0)
                {
                    break;
                }

                // Server may send MaxValue to indicate that it is disabled until further notice
                if (order.ExtraData == uint.MaxValue)
                {
                    TextNotificationsManager.ChatDisabledUntil = uint.MaxValue;
                }
                else
                {
                    TextNotificationsManager.ChatDisabledUntil = Game.RunTime + order.ExtraData;
                }

                break;
            }

            case "Chat":
            {
                var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
                if (client == null)
                {
                    break;
                }

                // Cut chat messages to the hard limit to avoid exploits
                var message = order.TargetString;
                if (message.Length > ChatMessageMaxLength)
                {
                    message = order.TargetString.Substring(0, ChatMessageMaxLength);
                }

                // ExtraData 0 means this is a normal chat order, everything else is team chat
                if (order.ExtraData == 0)
                {
                    var p = world != null?world.FindPlayerByClient(client) : null;

                    var suffix = (p != null && p.WinState == WinState.Lost) ? " (Dead)" : "";
                    suffix = client.IsObserver ? " (Spectator)" : suffix;

                    if (orderManager.LocalClient != null && client != orderManager.LocalClient && client.Team > 0 && client.Team == orderManager.LocalClient.Team)
                    {
                        suffix += " (Ally)";
                    }

                    TextNotificationsManager.AddChatLine(client.Name + suffix, message, client.Color);
                    break;
                }

                // We are still in the lobby
                if (world == null)
                {
                    var prefix = order.ExtraData == uint.MaxValue ? "[Spectators] " : "[Team] ";
                    if (orderManager.LocalClient != null && client.Team == orderManager.LocalClient.Team)
                    {
                        TextNotificationsManager.AddChatLine(prefix + client.Name, message, client.Color);
                    }

                    break;
                }

                var player = world.FindPlayerByClient(client);
                var localClientIsObserver = world.IsReplay || (orderManager.LocalClient != null && orderManager.LocalClient.IsObserver) ||
                                            (world.LocalPlayer != null && world.LocalPlayer.WinState != WinState.Undefined);

                // ExtraData gives us the team number, uint.MaxValue means Spectators
                if (order.ExtraData == uint.MaxValue && localClientIsObserver)
                {
                    // Validate before adding the line
                    if (client.IsObserver || (player != null && player.WinState != WinState.Undefined))
                    {
                        TextNotificationsManager.AddChatLine("[Spectators] " + client.Name, message, client.Color);
                    }

                    break;
                }

                var valid      = client.Team == order.ExtraData && player != null && player.WinState == WinState.Undefined;
                var isSameTeam = orderManager.LocalClient != null && order.ExtraData == orderManager.LocalClient.Team &&
                                 world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined;

                if (valid && (isSameTeam || world.IsReplay))
                {
                    TextNotificationsManager.AddChatLine("[Team" + (world.IsReplay ? " " + order.ExtraData : "") + "] " + client.Name, message, client.Color);
                }

                break;
            }

            case "StartGame":
            {
                if (Game.ModData.MapCache[orderManager.LobbyInfo.GlobalSettings.Map].Status != MapStatus.Available)
                {
                    Game.Disconnect();
                    Game.LoadShellMap();

                    // TODO: After adding a startup error dialog, notify the replay load failure.
                    break;
                }

                if (!string.IsNullOrEmpty(order.TargetString))
                {
                    var data = MiniYaml.FromString(order.TargetString);
                    var saveLastOrdersFrame = data.FirstOrDefault(n => n.Key == "SaveLastOrdersFrame");
                    if (saveLastOrdersFrame != null)
                    {
                        orderManager.GameSaveLastFrame =
                            FieldLoader.GetValue <int>("saveLastOrdersFrame", saveLastOrdersFrame.Value.Value);
                    }

                    var saveSyncFrame = data.FirstOrDefault(n => n.Key == "SaveSyncFrame");
                    if (saveSyncFrame != null)
                    {
                        orderManager.GameSaveLastSyncFrame =
                            FieldLoader.GetValue <int>("SaveSyncFrame", saveSyncFrame.Value.Value);
                    }
                }
                else
                {
                    TextNotificationsManager.AddSystemLine("The game has started.");
                }

                Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, WorldType.Regular);
                break;
            }

            case "SaveTraitData":
            {
                var data       = MiniYaml.FromString(order.TargetString)[0];
                var traitIndex = int.Parse(data.Key);

                world?.AddGameSaveTraitData(traitIndex, data.Value);

                break;
            }

            case "GameSaved":
                if (!orderManager.World.IsReplay)
                {
                    TextNotificationsManager.AddSystemLine("Game saved");
                }

                foreach (var nsr in orderManager.World.WorldActor.TraitsImplementing <INotifyGameSaved>())
                {
                    nsr.GameSaved(orderManager.World);
                }
                break;

            case "PauseGame":
            {
                var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
                if (client != null)
                {
                    var pause = order.TargetString == "Pause";

                    // Prevent injected unpause orders from restarting a finished game
                    if (orderManager.World.PauseStateLocked && !pause)
                    {
                        break;
                    }

                    if (orderManager.World.Paused != pause && world != null && world.LobbyInfo.NonBotClients.Count() > 1)
                    {
                        var pausetext = $"The game is {(pause ? "paused" : "un-paused")} by {client.Name}";
                        TextNotificationsManager.AddSystemLine(pausetext);
                    }

                    orderManager.World.Paused          = pause;
                    orderManager.World.PredictedPaused = pause;
                }

                break;
            }

            case "HandshakeRequest":
            {
                // Switch to the server's mod if we need and are able to
                var mod     = Game.ModData.Manifest;
                var request = HandshakeRequest.Deserialize(order.TargetString);

                var externalKey = ExternalMod.MakeKey(request.Mod, request.Version);
                if ((request.Mod != mod.Id || request.Version != mod.Metadata.Version) &&
                    Game.ExternalMods.TryGetValue(externalKey, out var external))
                {
                    // The ConnectionFailedLogic will prompt the user to switch mods
                    CurrentServerSettings.ServerExternalMod = external;
                    orderManager.Connection.Dispose();
                    break;
                }

                Game.Settings.Player.Name = Settings.SanitizedPlayerName(Game.Settings.Player.Name);
                Game.Settings.Save();

                // Otherwise send the handshake with our current settings and let the server reject us
                var info = new Session.Client()
                {
                    Name           = Game.Settings.Player.Name,
                    PreferredColor = Game.Settings.Player.Color,
                    Color          = Game.Settings.Player.Color,
                    Faction        = "Random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.Invalid
                };

                var localProfile = Game.LocalPlayerProfile;
                var response     = new HandshakeResponse()
                {
                    Client         = info,
                    Mod            = mod.Id,
                    Version        = mod.Metadata.Version,
                    Password       = CurrentServerSettings.Password,
                    Fingerprint    = localProfile.Fingerprint,
                    OrdersProtocol = ProtocolVersion.Orders
                };

                if (request.AuthToken != null && response.Fingerprint != null)
                {
                    response.AuthSignature = localProfile.Sign(request.AuthToken);
                }

                orderManager.IssueOrder(new Order("HandshakeResponse", null, false)
                    {
                        Type         = OrderType.Handshake,
                        IsImmediate  = true,
                        TargetString = response.Serialize()
                    });

                break;
            }

            case "ServerError":
            {
                orderManager.ServerError          = order.TargetString;
                orderManager.AuthenticationFailed = false;
                break;
            }

            case "AuthenticationError":
            {
                // The ConnectionFailedLogic will prompt the user for the password
                orderManager.ServerError          = order.TargetString;
                orderManager.AuthenticationFailed = true;
                break;
            }

            case "SyncInfo":
            {
                orderManager.LobbyInfo = Session.Deserialize(order.TargetString);
                Game.SyncLobbyInfo();
                break;
            }

            case "SyncLobbyClients":
            {
                var clients = new List <Session.Client>();
                var nodes   = MiniYaml.FromString(order.TargetString);
                foreach (var node in nodes)
                {
                    var strings = node.Key.Split('@');
                    if (strings[0] == "Client")
                    {
                        clients.Add(Session.Client.Deserialize(node.Value));
                    }
                }

                orderManager.LobbyInfo.Clients = clients;
                Game.SyncLobbyInfo();
                break;
            }

            case "SyncLobbySlots":
            {
                var slots = new Dictionary <string, Session.Slot>();
                var nodes = MiniYaml.FromString(order.TargetString);
                foreach (var node in nodes)
                {
                    var strings = node.Key.Split('@');
                    if (strings[0] == "Slot")
                    {
                        var slot = Session.Slot.Deserialize(node.Value);
                        slots.Add(slot.PlayerReference, slot);
                    }
                }

                orderManager.LobbyInfo.Slots = slots;
                Game.SyncLobbyInfo();
                break;
            }

            case "SyncLobbyGlobalSettings":
            {
                var nodes = MiniYaml.FromString(order.TargetString);
                foreach (var node in nodes)
                {
                    var strings = node.Key.Split('@');
                    if (strings[0] == "GlobalSettings")
                    {
                        orderManager.LobbyInfo.GlobalSettings = Session.Global.Deserialize(node.Value);
                    }
                }

                Game.SyncLobbyInfo();
                break;
            }

            case "SyncConnectionQuality":
            {
                var nodes = MiniYaml.FromString(order.TargetString);
                foreach (var node in nodes)
                {
                    var strings = node.Key.Split('@');
                    if (strings[0] == "ConnectionQuality")
                    {
                        var client = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.Index == int.Parse(strings[1]));
                        if (client != null)
                        {
                            client.ConnectionQuality = FieldLoader.GetValue <Session.ConnectionQuality>("ConnectionQuality", node.Value.Value);
                        }
                    }
                }

                break;
            }

            default:
            {
                if (world == null)
                {
                    break;
                }

                if (order.GroupedActors == null)
                {
                    ResolveOrder(order, world, orderManager, clientId);
                }
                else
                {
                    foreach (var subject in order.GroupedActors)
                    {
                        ResolveOrder(Order.FromGroupedOrder(order, subject), world, orderManager, clientId);
                    }
                }

                break;
            }
            }
        }