Exemple #1
0
    public static void CallQueuedCommand(string user, [Group(1)] bool now, [Group(2)] string name)
    {
        name = (name?.Trim()) ?? "";
        var response = TwitchGame.Instance.CheckIfCall(false, now, user, name, out bool callChanged);

        if (response != TwitchGame.CallResponse.Success)
        {
            TwitchGame.Instance.SendCallResponse(user, name, response, callChanged);
            return;
        }
        if (callChanged)
        {
            IRCConnection.SendMessageFormat("@{0}, your call has been changed to {1}.", user, string.IsNullOrEmpty(name) ? "the next queued command" : name);
        }
        TwitchGame.Instance.CommandQueue.Remove(TwitchGame.Instance.callSend);
        TwitchGame.ModuleCameras?.SetNotes();
        IRCConnection.SendMessageFormat("{0} {1}: {2}", TwitchGame.Instance.callWaiting && string.IsNullOrEmpty(user)
                        ? "Call waiting, calling"
                        : now
                                ? "Bypassing the required number of calls, calling"
                                : TwitchGame.Instance.callsNeeded > 1
                                        ? "Required calls reached, calling"
                                        : "Calling", TwitchGame.Instance.callSend.Message.UserNickName, TwitchGame.Instance.callSend.Message.Text);
        DeleteCallInformation(true);
        IRCConnection.ReceiveMessage(TwitchGame.Instance.callSend.Message);
    }
Exemple #2
0
    public static void Unclaim(TwitchModule module, string user, [Group(1)] string cmd)
    {
        if (module.Solved)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadySolved, module.Code, module.PlayerName, user, module.HeaderText);
            return;
        }

        // If module is already unclaimed, just remove from claim queue
        if (module.PlayerName == null)
        {
            module.RemoveFromClaimQueue(user);
            return;
        }

        // Error if a non-mod tries to unclaim someone else’s module
        if (!UserAccess.HasAccess(user, AccessLevel.Mod, true) && module.PlayerName != user)
        {
            IRCConnection.SendMessage($"{user}, module {module.Code} ({module.HeaderText}) is not claimed by you.");
            return;
        }

        module.SetUnclaimed();
        if (cmd.Contains("v"))
        {
            TwitchGame.ModuleCameras?.UnviewModule(module);
        }
    }
Exemple #3
0
    public static void Mine(TwitchModule module, string user, bool isWhisper)
    {
        if (isWhisper)
        {
            IRCConnection.SendMessage($"@{user}, using mine on modules is not allowed in whispers.", user, false);
            return;
        }

        // The module belongs to this user and there’s a takeover attempt in progress: cancel the takeover attempt
        if (module.PlayerName == user && module.TakeInProgress != null)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.ModuleIsMine, module.PlayerName, module.Code, module.HeaderText);
            module.StopCoroutine(module.TakeInProgress);
            module.TakeInProgress = null;
            module.TakeUser       = null;
        }

        // The module isn’t claimed: just claim it
        else if (module.PlayerName == null)
        {
            IRCConnection.SendMessage(module.TryClaim(user).Message);
        }

        // Someone else has a claim on the module
        else if (module.PlayerName != user)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadyClaimed, module.Code, module.PlayerName, user, module.HeaderText);
        }

        // If the user has a claim on the module but there’s no takeover attempt, just ignore this command
    }
Exemple #4
0
    private IEnumerator EndTrainingModeBomb()
    {
        TrainingModeRemainingTime = TwitchPlaySettings.data.TrainingModeDetonationTime;
        if (TrainingModeRemainingTime < 1)
        {
            yield break;
        }
        while (true)
        {
            if (TrainingModeAlertTimes.Contains(TrainingModeRemainingTime))
            {
                if (alertSound != null)
                {
                    alertSound.Play();
                }
                IRCConnection.SendMessageFormat("Warning: This bomb will be automatically detonated in {0} minute{1}.", TrainingModeRemainingTime.ToString(), TrainingModeRemainingTime == 1 ? "" : "s");
            }
            yield return(new WaitForSecondsRealtime(60.0f));

            TrainingModeRemainingTime--;
            if (BombActive)
            {
                ModuleCameras.SetNotes();
            }
            if (TrainingModeRemainingTime < 1)
            {
                Bombs[0].CauseExplosionByTrainingModeTimeout();
            }
        }
    }
Exemple #5
0
 public static void BombTurnAround(TwitchModule module)
 {
     if (!module.Solver.TurnQueued)
     {
         module.Solver.TurnQueued = true;
         module.StartCoroutine(module.Solver.TurnBombOnSolve());
     }
     IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TurnBombOnSolve, module.Code, module.HeaderText);
 }
Exemple #6
0
 public static void DeleteCallInformation(bool silent)
 {
     TwitchGame.Instance.CallingPlayers.Clear();
     TwitchGame.Instance.callWaiting = false;
     if (!silent)
     {
         IRCConnection.SendMessageFormat("All call information cleared.");
     }
 }
Exemple #7
0
 public static void RemoveQueuedPlayer(string user)
 {
     if (!TwitchGame.Instance.CallingPlayers.Contains(user))
     {
         IRCConnection.SendMessageFormat("@{0}, you haven't called yet!", user);
         return;
     }
     TwitchGame.Instance.CallingPlayers.Remove(user);
     IRCConnection.SendMessageFormat("@{0}, your call has been removed.", user);
     CallCountCommand();
 }
Exemple #8
0
    private static IEnumerator RunModuleCommand(TwitchModule module, string user, string cmd)
    {
        if (module.Solver == null)
        {
            yield break;
        }

        if (module.Solved && !TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadySolved, module.Code, module.PlayerName, user, module.HeaderText);
            yield break;
        }

        if (module.Bomb.BackdoorComponent != null && module.Bomb.BackdoorComponent.GetValue <bool>("BeingHacked") && module.BombComponent.GetModuleDisplayName() != "Backdoor Hacking")
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.BackdoorHackingBlock, module.Code, user, module.HeaderText);
            yield break;
        }

        Transform tsLight = module.BombComponent.StatusLightParent?.transform.Find("statusLight(Clone)").Find("Component_LED_ERROR(Clone)");

        if (tsLight != null && tsLight.gameObject.activeSelf)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TechSupportBlock, module.Code, user, module.HeaderText);
            yield break;
        }

        // We’re allowed to interact with this module if either:
        if (
            // the module is unclaimed;
            module.PlayerName == null ||
            // the module is claimed by the player;
            module.PlayerName == user ||
            // anarchy mode is on;
            TwitchPlaySettings.data.AnarchyMode ||
            // there is less than X time left on the clock;
            module.Bomb.CurrentTimer <= TwitchPlaySettings.data.MinTimeLeftForClaims ||
            // there are only X unsolved modules left.
            TwitchGame.Instance.Modules.Count(x => !x.Solved && GameRoom.Instance.IsCurrentBomb(x.BombID)) < TwitchPlaySettings.data.MinUnsolvedModulesLeftForClaims
            )
        {
            var response = module.Solver.RespondToCommand(user, cmd);
            while (response.MoveNext())
            {
                yield return(response.Current);
            }

            module.Solver.EnableAnarchyStrike();
        }
        else
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadyClaimed, module.Code, module.PlayerName, user, module.HeaderText);
        }
    }
Exemple #9
0
    public static void CallSetCommand(string user, [Group(1)] int minimum)
    {
        if (minimum <= 0 || minimum >= 25)
        {
            IRCConnection.SendMessageFormat("@{0}, {1} is in invalid number of calls!", user, minimum);
            return;
        }

        TwitchGame.Instance.callsNeeded = minimum;
        TwitchGame.Instance.CallingPlayers.Clear();
        IRCConnection.SendMessageFormat("Set minimum calls to {0}.", minimum);
    }
Exemple #10
0
    public static void ListCalledPlayers(string user)
    {
        int totalCalls = TwitchGame.Instance.CallingPlayers.Count;

        if (totalCalls == 0)
        {
            IRCConnection.SendMessageFormat("@{0}, no calls have been made.", user);
            return;
        }
        string CallPlayers = string.Join(", @", TwitchGame.Instance.CallingPlayers.ToArray());

        IRCConnection.SendMessageFormat("These players have already called: @{0}", CallPlayers);
    }
    public void SendCallResponse(string user, string name, CallResponse response, bool callChanged)
    {
        bool unnamed = string.IsNullOrEmpty(name);

        if (response == CallResponse.AlreadyCalled)
        {
            IRCConnection.SendMessageFormat("@{0}, you already called!", user);
            return;
        }
        else if (response == CallResponse.NotEnoughCalls)
        {
            if (callChanged)
            {
                IRCConnection.SendMessageFormat("@{0}, your call has been updated to {1}.", user, unnamed ? "the next queued command" : name);
            }
            GameCommands.CallCountCommand();
            return;
        }
        else if (response == CallResponse.UncommonCalls)
        {
            if (callChanged)
            {
                IRCConnection.SendMessageFormat("@{0}, your call has been updated to {1}. Uncommon calls still present.", user, unnamed ? "the next queued command" : name);
            }
            else
            {
                IRCConnection.SendMessageFormat("Sorry, uncommon calls were made. Please either correct your call(s) or use “!callnow” followed by the correct command to call.");
                GameCommands.ListCalledPlayers();
            }
            return;
        }
        else if (response == CallResponse.DifferentName)
        {
            CommandQueueItem call = CommandQueue.Find(item => item.Message.Text.StartsWith(name));
            IRCConnection.SendMessageFormat("@{0}, module {1} is queued with the name “{2}”, please use “!call {2}” to call it.", user, name, call.Name);
            return;
        }
        else
        {
            unnamed = string.IsNullOrEmpty(commandToCall);
            if (callWaiting)
            {
                IRCConnection.SendMessageFormat("Waiting for {0} to be queued.", unnamed ? "the next unnamed queued command" : commandToCall.StartsWith("!") ? "module " + commandToCall : "the command named “" + commandToCall + "”");
            }
            else
            {
                IRCConnection.SendMessageFormat("No {0} in the queue. Calling {1} when it is queued.", unnamed ? "unnamed commands" : commandToCall.StartsWith("!") ? "command for module " + commandToCall : "command named “" + commandToCall + "”", unnamed ? "the next unnamed queued command" : commandToCall.StartsWith("!") ? "module " + commandToCall : "the command named “" + commandToCall + "”");
                callWaiting = true;
            }
        }
    }
Exemple #12
0
 public static void DeleteQueuedPlayer([Group(1)] string callUser, string user)
 {
     if (string.IsNullOrEmpty(callUser))
     {
         IRCConnection.SendMessageFormat("@{0}, please specify a call to remove!", user);
     }
     else if (!TwitchGame.Instance.CallingPlayers.Keys.Contains(user))
     {
         IRCConnection.SendMessageFormat("@{0}, @{1} has not called!", user, callUser);
     }
     else
     {
         TwitchGame.Instance.CallingPlayers.Remove(callUser);
         IRCConnection.SendMessageFormat("@{0}, removed @{1}'s call.", user, callUser);
         TwitchGame.Instance.CallUpdate(true);
     }
 }
Exemple #13
0
    public static void CallAllQueuedCommands(string user, bool isWhisper)
    {
        if (TwitchGame.Instance.CommandQueue.Count == 0)
        {
            IRCConnection.SendMessage($"{user}, the queue is empty.", user, !isWhisper);
            return;
        }

        // Take a copy of the list in case executing one of the commands modifies the command queue
        var allCommands = TwitchGame.Instance.CommandQueue.ToList();

        TwitchGame.Instance.CommandQueue.Clear();
        TwitchGame.ModuleCameras?.SetNotes();
        foreach (var call in allCommands)
        {
            IRCConnection.SendMessageFormat("Calling {0}: {1}", call.Message.UserNickName, call.Message.Text);
            IRCConnection.ReceiveMessage(call.Message);
        }
    }
Exemple #14
0
    public static void ListCalledPlayers()
    {
        int totalCalls = TwitchGame.Instance.CallingPlayers.Count;

        if (totalCalls == 0)
        {
            IRCConnection.SendMessageFormat("No calls have been made.");
            return;
        }
        string[] __calls       = TwitchGame.Instance.CallingPlayers.Values.ToArray();
        string[] __callPlayers = TwitchGame.Instance.CallingPlayers.Keys.ToArray();
        string   builder       = "";

        for (int j = 0; j < __calls.Length; j++)
        {
            builder = builder + ((j == 0) ? "@" : ", @") + __callPlayers[j] + ": " + (string.IsNullOrEmpty(__calls[j]) ? "Next queued command" : __calls[j]);
        }
        IRCConnection.SendMessageFormat("These players have already called: {0}", builder);
    }
Exemple #15
0
    public static void Take(TwitchModule module, string user, bool isWhisper)
    {
        if (isWhisper)
        {
            IRCConnection.SendMessageFormat("Sorry {0}, taking modules is not allowed in whispers.", user);
        }
        else if (TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessageFormat("Sorry {0}, taking modules is not allowed in anarchy mode.", user);
        }

        // Attempt to take over from another user
        else if (module.PlayerName != null && user != module.PlayerName)
        {
            module.AddToClaimQueue(user);
            if (module.TakeInProgress == null)
            {
                IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TakeModule, module.PlayerName, user, module.Code, module.HeaderText);
                module.TakeInProgress = module.TakeModule();
                module.StartCoroutine(module.TakeInProgress);
            }
            else
            {
                IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TakeInProgress, user, module.Code, module.HeaderText);
            }
        }

        // Module is already claimed by the same user
        else if (module.PlayerName != null)
        {
            if (!module.PlayerName.Equals(user))
            {
                module.AddToClaimQueue(user);
            }
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.ModuleAlreadyOwned, user, module.Code, module.HeaderText);
        }

        // Module is not claimed at all: just claim it
        else
        {
            IRCConnection.SendMessage(module.ClaimModule(user).Second);
        }
    }
Exemple #16
0
    public static void Assign(TwitchModule module, string user, [Group(1)] string targetUser)
    {
        if (TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessageFormat("Sorry {0}, assigning modules is not allowed in anarchy mode.", user);
            return;
        }

        if (module.TakeInProgress != null)
        {
            module.StopCoroutine(module.TakeInProgress);
            module.TakeInProgress = null;
        }

        module.PlayerName = targetUser;
        module.RemoveFromClaimQueue(user);
        module.CanClaimNow(user, true, true);
        module.SetBannerColor(module.ClaimedBackgroundColour);
        IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AssignModule, module.Code, module.PlayerName, user, module.HeaderText);
    }
Exemple #17
0
    private static IEnumerator RunModuleCommand(TwitchModule module, string user, string cmd, bool zoom)
    {
        if (module.Solver == null)
        {
            yield break;
        }

        if (module.Solved && !TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadySolved, module.Code, module.PlayerName, user, module.HeaderText);
            yield break;
        }

        // We’re allowed to interact with this module if either:
        if (
            // the module is unclaimed;
            module.PlayerName == null ||
            // the module is claimed by the player;
            module.PlayerName == user ||
            // anarchy mode is on;
            TwitchPlaySettings.data.AnarchyMode ||
            // there is less than X time left on the clock;
            module.Bomb.CurrentTimer <= TwitchPlaySettings.data.MinTimeLeftForClaims ||
            // there are only X unsolved modules left.
            TwitchGame.Instance.Modules.Count(x => !x.Solved && GameRoom.Instance.IsCurrentBomb(x.BombID)) < TwitchPlaySettings.data.MinUnsolvedModulesLeftForClaims
            )
        {
            yield return(new WaitForSeconds(0.1f));

            var response = module.Solver.RespondToCommand(user, cmd, zoom);
            while (response.MoveNext())
            {
                yield return(response.Current);
            }
            yield return(new WaitForSeconds(0.1f));
        }
        else
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadyClaimed, module.Code, module.PlayerName, user, module.HeaderText);
        }
    }
    public void CallUpdate(bool response)
    {
        var callResponse = CheckIfCall(true, false, "", commandToCall, out _);

        if (callResponse == CallResponse.Success)
        {
            GameCommands.CallQueuedCommand("", false, true, commandToCall);
        }
        else if (callResponse == CallResponse.NotPresent)
        {
            IRCConnection.SendMessageFormat("Waiting for {0} to be queued.", string.IsNullOrEmpty(commandToCall) ? "the next unnamed queued command" : commandToCall.StartsWith("!") ? "module " + commandToCall : "the command named “" + commandToCall + "”");
        }
        else
        {
            callWaiting = false;
        }
        if (response)
        {
            GameCommands.CallCountCommand();
        }
    }
Exemple #19
0
    public static void Take(TwitchModule module, string user, bool isWhisper)
    {
        if (isWhisper)
        {
            IRCConnection.SendMessage($"@{user}, taking modules is not allowed in whispers.");
        }
        else if (TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessage($"@{user}, taking modules is not allowed in anarchy mode.");
        }

        // Module is already claimed by the same user
        else if (module.PlayerName == user)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.ModuleAlreadyOwned, user, module.Code, module.HeaderText);
        }

        // Module is not claimed at all: just claim it
        else if (module.PlayerName == null)
        {
            IRCConnection.SendMessage(module.TryClaim(user).Message);
        }

        // Attempt to take over from another user
        else
        {
            module.AddToClaimQueue(user);
            if (module.TakeInProgress != null)
            {
                IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TakeInProgress, user, module.Code, module.HeaderText);
            }
            else
            {
                IRCConnection.SendMessageFormat(TwitchPlaySettings.data.TakeModule, module.PlayerName, user, module.Code, module.HeaderText);
                module.TakeUser       = user;
                module.TakeInProgress = module.StartCoroutine(module.ProcessTakeover());
            }
        }
    }
Exemple #20
0
    public static void Assign(TwitchModule module, string user, [Group(1)] string targetUser)
    {
        targetUser = targetUser.FormatUsername();
        if (module.PlayerName == targetUser)
        {
            IRCConnection.SendMessage($"{user}, the module is already assigned to {targetUser}.");
            return;
        }

        if (TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessage($"{user}, assigning modules is not allowed in anarchy mode.");
            return;
        }

        if (!UserAccess.HasAccess(user, AccessLevel.Mod, true))
        {
            if (module.PlayerName != user || !module.ClaimQueue.Any(q => q.UserNickname == targetUser))
            {
                IRCConnection.SendMessage($"{user}, {module.Code} can only be reassigned if you have it claimed and the other user is in its claim queue.");
                return;
            }
            if (TwitchGame.Instance.Modules.Count(md => !md.Solved && targetUser.EqualsIgnoreCase(md.PlayerName)) >= TwitchPlaySettings.data.ModuleClaimLimit)
            {
                IRCConnection.SendMessage($"{user}, {module.Code} cannot be reassigned because it would take the other user above their claim limit.");
                return;
            }
        }

        if (module.TakeInProgress != null)
        {
            module.StopCoroutine(module.TakeInProgress);
            module.TakeInProgress = null;
            module.TakeUser       = null;
        }

        module.SetClaimedBy(targetUser);
        IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AssignModule, module.Code, module.PlayerName, user, module.HeaderText);
    }
Exemple #21
0
 public static void Solved(TwitchModule module, string user)
 {
     module.SetBannerColor(module.SolvedBackgroundColor);
     module.PlayerName = null;
     IRCConnection.SendMessageFormat(TwitchPlaySettings.data.ModuleReady, module.Code, user, module.HeaderText);
 }
Exemple #22
0
 public void ReportState() => IRCConnection.SendMessageFormat("Elevator is {0}", GameplayState.GameplayRoomPrefabOverride == null ? (ElevatorRoomGameObject == null ? "not loaded" : "off") : "on");
Exemple #23
0
    private IEnumerator SetupRoomElevatorSwitch()
    {
        SetupRoom setupRoom = SceneManager.Instance.CurrentRoom as SetupRoom;

        if (setupRoom == null)
        {
            yield break;
        }
        try
        {
            ElevatorRoomGameObject = Resources.Load <GameObject>("PC/Prefabs/ElevatorRoom/ElevatorBombRoom");
        }
        catch (Exception ex)
        {
            DebugHelper.LogException(ex, "Can't load the Elevator room prefab.");
            gameObject.SetActive(false);
            yield break;
        }
        if (setupRoom.ElevatorSwitch == null)
        {
            ElevatorSwitch.OnInteract += OnInteract;
            ElevatorLEDOn.SetActive(IsON);
            ElevatorLEDOff.SetActive(!IsON);
            ElevatorSwitch.transform.localEulerAngles = new Vector3(IsON ? 55 : -55, 0, 0);
            yield break;
        }

        ElevatorSwitch elevatorSwitch = setupRoom.ElevatorSwitch;

        DebugHelper.Log("Found an Elevator switch, Activating it now");
        try
        {
            elevatorSwitch.GetComponentInChildren <Selectable>(true).SelectableArea.ActivateSelectableArea();
            elevatorSwitch.Switch.SetInitialState(GameplayState.GameplayRoomPrefabOverride != null);
            elevatorSwitch.LEDOn.SetActive(GameplayState.GameplayRoomPrefabOverride != null);
            elevatorSwitch.LEDOff.SetActive(GameplayState.GameplayRoomPrefabOverride == null);
            elevatorSwitch.Switch.OnToggle += toggleState =>
            {
                DebugHelper.Log($"Toggle State = {toggleState}");
                if (elevatorSwitch.On() && IRCConnection.Instance.State != IRCConnectionState.Connected)
                {
                    elevatorSwitch.Switch.Toggle();
                    Audio.PlaySound(KMSoundOverride.SoundEffect.Strike, elevatorSwitch.Switch.transform);
                    return;
                }

                GameplayState.GameplayRoomPrefabOverride = toggleState ? ElevatorRoomGameObject : null;
                IRCConnection.SendMessageFormat("Elevator is {0}", GameplayState.GameplayRoomPrefabOverride == null ? (ElevatorRoomGameObject == null ? "not loaded" : "off") : "on");
                elevatorSwitch.LEDOn.SetActive(GameplayState.GameplayRoomPrefabOverride != null);
                elevatorSwitch.LEDOff.SetActive(GameplayState.GameplayRoomPrefabOverride == null);
            };
        }
        catch (Exception ex)
        {
            DebugHelper.LogException(ex, "Could not activate elevator switch due to an exception:");
            yield break;
        }
        elevatorSwitch.gameObject.SetActive(true);
        yield return(null);

        yield return(null);

        elevatorSwitch.gameObject.SetActive(true);
        gameObject.SetActive(false);
    }
Exemple #24
0
 public void PostToChat(string analysisUrl, string format = "Analysis for this bomb: {0}", string emote = "copyThis") =>
 IRCConnection.SendMessageFormat($"{emote} {format}", analysisUrl);
    private bool AttemptInvokeCommand <TObj>(StaticCommand command, IRCMessage msg, string cmdStr, Match m, TObj extraObject)
    {
        if (command.HasAttribute <DebuggingOnlyAttribute>() && !TwitchPlaySettings.data.EnableDebuggingCommands)
        {
            return(false);
        }
        if (command.HasAttribute <ElevatorOnlyAttribute>() && !(GameRoom.Instance is ElevatorGameRoom))
        {
            return(false);
        }
        if (command.HasAttribute <ElevatorDisallowedAttribute>() && GameRoom.Instance is ElevatorGameRoom)
        {
            return(false);
        }

        if (!UserAccess.HasAccess(msg.UserNickName, TwitchPlaySettings.data.AnarchyMode ? command.Attr.AccessLevelAnarchy : command.Attr.AccessLevel, orHigher: true))
        {
            IRCConnection.SendMessageFormat("@{0}, you need {1} access to use that command{2}.",
                                            msg.UserNickName,
                                            UserAccess.LevelToString(TwitchPlaySettings.data.AnarchyMode ? command.Attr.AccessLevelAnarchy : command.Attr.AccessLevel),
                                            TwitchPlaySettings.data.AnarchyMode ? " in anarchy mode" : "");
            // Return true so that the command counts as processed
            return(true);
        }

        if (extraObject is TwitchModule mdl && mdl.Solved && !command.HasAttribute <SolvedAllowedAttribute>() && !TwitchPlaySettings.data.AnarchyMode)
        {
            IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AlreadySolved, mdl.Code, mdl.PlayerName, msg.UserNickName, mdl.BombComponent.GetModuleDisplayName());
            // Return true so that the command counts as processed (otherwise you get the above message multiple times)
            return(true);
        }

        Leaderboard.Instance.GetRank(msg.UserNickName, out Leaderboard.LeaderboardEntry entry);
        if (entry?.Team == null && extraObject is TwitchModule && OtherModes.VSModeOn)
        {
            IRCConnection.SendMessage($@"{msg.UserNickName}, you have not joined a team, and cannot solve modules in this mode until you do, please use !join evil or !join good.");
            // Return true so that the command counts as processed (otherwise you get the above message multiple times)
            return(true);
        }

        if (!TwitchGame.IsAuthorizedDefuser(msg.UserNickName, msg.IsWhisper))
        {
            return(true);
        }

        BanData ban = UserAccess.IsBanned(msg.UserNickName);

        if (ban != null)
        {
            if (double.IsPositiveInfinity(ban.BanExpiry))
            {
                IRCConnection.SendMessage($"Sorry @{msg.UserNickName}, You were banned permanently from Twitch Plays by {ban.BannedBy}{(string.IsNullOrEmpty(ban.BannedReason) ? "." : $", for the following reason: {ban.BannedReason}")}", msg.UserNickName, !msg.IsWhisper);
            }
            else
            {
                int secondsRemaining = (int)(ban.BanExpiry - DateTime.Now.TotalSeconds());

                int    daysRemaining    = secondsRemaining / 86400; secondsRemaining %= 86400;
                int    hoursRemaining   = secondsRemaining / 3600; secondsRemaining %= 3600;
                int    minutesRemaining = secondsRemaining / 60; secondsRemaining %= 60;
                string timeRemaining    = $"{secondsRemaining} seconds.";
                if (daysRemaining > 0)
                {
                    timeRemaining = $"{daysRemaining} days, {hoursRemaining} hours, {minutesRemaining} minutes, {secondsRemaining} seconds.";
                }
                else if (hoursRemaining > 0)
                {
                    timeRemaining = $"{hoursRemaining} hours, {minutesRemaining} minutes, {secondsRemaining} seconds.";
                }
                else if (minutesRemaining > 0)
                {
                    timeRemaining = $"{minutesRemaining} minutes, {secondsRemaining} seconds.";
                }

                IRCConnection.SendMessage($"Sorry @{msg.UserNickName}, You were timed out from Twitch Plays by {ban.BannedBy}{(string.IsNullOrEmpty(ban.BannedReason) ? "." : $", For the following reason: {ban.BannedReason}")} You can participate again in {timeRemaining}", msg.UserNickName, !msg.IsWhisper);
            }
            return(true);
        }

        var parameters = command.Method.GetParameters();
        var groupAttrs = parameters.Select(p => (GroupAttribute)p.GetCustomAttributes(typeof(GroupAttribute), false).FirstOrDefault()).ToArray();
        var arguments  = new object[parameters.Length];

        for (int i = 0; i < parameters.Length; i++)
        {
            // Capturing groups from the regular expression
            if (groupAttrs[i] != null && m != null)
            {
                var group = m.Groups[groupAttrs[i].GroupIndex];
                NumberParseResult result;

                // Helper function to parse numbers (ints, floats, doubles)
                NumberParseResult IsNumber <TNum>(TryParse <TNum> tryParse)
                {
                    var isNullable = parameters[i].ParameterType == typeof(Nullable <>).MakeGenericType(typeof(TNum));

                    if (parameters[i].ParameterType != typeof(TNum) && !isNullable)
                    {
                        return(NumberParseResult.NotOfDesiredType);
                    }

                    if (group.Success && tryParse(group.Value, out TNum rslt))
                    {
                        arguments[i] = rslt;
                        return(NumberParseResult.Success);
                    }
                    if (isNullable)
                    {
                        return(NumberParseResult.Success);
                    }
                    IRCConnection.SendMessage(group.Success ? "@{0}, “{1}” is not a valid number." : "@{0}, the command could not be parsed.", msg.UserNickName, !msg.IsWhisper, msg.UserNickName, group.Success ? group.Value : null);
                    return(NumberParseResult.Error);
                }

                // Strings
                if (parameters[i].ParameterType == typeof(string))
                {
                    arguments[i] = m.Success ? group.Value : null;
                }

                // Booleans — only specifies whether the group matched or not
                else if (parameters[i].ParameterType == typeof(bool))
                {
                    arguments[i] = group.Success;
                }

                // Numbers (int, float, double); includes nullables
                else if (
                    (result = IsNumber <int>(int.TryParse)) != NumberParseResult.NotOfDesiredType ||
                    (result = IsNumber <float>(float.TryParse)) != NumberParseResult.NotOfDesiredType ||
                    (result = IsNumber <double>(double.TryParse)) != NumberParseResult.NotOfDesiredType)
                {
                    if (result == NumberParseResult.Error)
                    {
                        return(true);
                    }
                }
            }

            // Built-in parameter names
            else if (parameters[i].ParameterType == typeof(string) && parameters[i].Name == "user")
            {
                arguments[i] = msg.UserNickName;
            }
            else if (parameters[i].ParameterType == typeof(string) && parameters[i].Name == "cmd")
            {
                arguments[i] = cmdStr;
            }
            else if (parameters[i].ParameterType == typeof(bool) && parameters[i].Name == "isWhisper")
            {
                arguments[i] = msg.IsWhisper;
            }
            else if (parameters[i].ParameterType == typeof(IRCMessage))
            {
                arguments[i] = msg;
            }
            else if (parameters[i].ParameterType == typeof(KMGameInfo))
            {
                arguments[i] = GetComponent <KMGameInfo>();
            }
            else if (parameters[i].ParameterType == typeof(KMGameInfo.State))
            {
                arguments[i] = CurrentState;
            }
            else if (parameters[i].ParameterType == typeof(FloatingHoldable) && extraObject is TwitchHoldable twitchHoldable)
            {
                arguments[i] = twitchHoldable.Holdable;
            }

            // Object we passed in (module, bomb, holdable)
            else if (parameters[i].ParameterType.IsAssignableFrom(typeof(TObj)))
            {
                arguments[i] = extraObject;
            }
            else if (parameters[i].IsOptional)
            {
                arguments[i] = parameters[i].DefaultValue;
            }
            else
            {
                IRCConnection.SendMessage("@{0}, this is a bug; please notify the devs. Error: the “{1}” command has an unrecognized parameter “{2}”. It expects a type of “{3}”, and the extraObject is of type “{4}”.", msg.UserNickName, !msg.IsWhisper, msg.UserNickName, command.Method.Name, parameters[i].Name, parameters[i].ParameterType.Name, extraObject?.GetType().Name);
                return(true);
            }
        }

        var invokeResult = command.Method.Invoke(null, arguments);

        if (invokeResult is bool invRes)
        {
            return(invRes);
        }
        else if (invokeResult is IEnumerator coroutine)
        {
            ProcessCommandCoroutine(coroutine, extraObject);
        }
        else if (invokeResult != null)
        {
            IRCConnection.SendMessage("@{0}, this is a bug; please notify the devs. Error: the “{1}” command returned something unrecognized.", msg.UserNickName, !msg.IsWhisper, msg.UserNickName, command.Method.Name);
        }

        if ((TwitchPlaySettings.data.AnarchyMode ? command.Attr.AccessLevelAnarchy : command.Attr.AccessLevel) > AccessLevel.Defuser)
        {
            AuditLog.Log(msg.UserNickName, UserAccess.HighestAccessLevel(msg.UserNickName), msg.Text);
        }
        return(true);
    }
Exemple #26
0
 public static void BombTurnAroundCancel(TwitchModule module)
 {
     module.Solver.TurnQueued = false;
     IRCConnection.SendMessageFormat(TwitchPlaySettings.data.CancelBombTurn, module.Code, module.HeaderText);
 }
Exemple #27
0
    public static void FindClaimView([Group(1)] string commands, [Group(2)] string queries, string user, bool isWhisper)
    {
        var claim = commands.ContainsIgnoreCase("claim");
        var view  = commands.ContainsIgnoreCase("view");

        var terms = queries.SplitFull(',', ';').Select(q => q.Trim()).Distinct().ToArray();

        if (terms.Length > TwitchPlaySettings.data.FindClaimTerms && claim && TwitchPlaySettings.data.FindClaimTerms != -1)
        {
            IRCConnection.SendMessageFormat("@{0}, please reduce the size of your list to {1} or fewer terms.", user, TwitchPlaySettings.data.FindClaimTerms);             // Prevents lists greater than length of 3 while using !claim
            return;
        }

        var modules = FindModules(terms).ToList();

        if (!modules.Any())
        {
            IRCConnection.SendMessage("No such modules.", user, !isWhisper);
            return;
        }

        if (claim)
        {
            if (!TwitchGame.Instance.FindClaimPlayers.ContainsKey(user))
            {
                TwitchGame.Instance.FindClaimPlayers.Add(user, 0);
            }

            var _prevClaims      = TwitchGame.Instance.FindClaimPlayers[user];
            var _allowedClaims   = TwitchGame.Instance.FindClaimUse;
            var _remainingClaims = _allowedClaims - _prevClaims;

            if (_remainingClaims < 1 && TwitchPlaySettings.data.FindClaimLimit != -1)
            {
                IRCConnection.SendMessageFormat("@{0}, you have no more findclaim uses.", user);
                return;
            }

            if (modules.Count > _remainingClaims && TwitchPlaySettings.data.FindClaimLimit != -1)
            {
                IRCConnection.SendMessageFormat("@{0}, that goes over your current findclaim limit of {1}. You will receive the first {2} claims.", user, _allowedClaims, _remainingClaims);
                ClaimViewPin(user, isWhisper, modules.Take(_remainingClaims), claim: claim, view: view);
            }
            else
            {
                ClaimViewPin(user, isWhisper, modules, claim: claim, view: view);
            }

            TwitchGame.Instance.FindClaimPlayers[user] = _prevClaims + modules.Count;
        }
        else if (view)
        {
            ClaimViewPin(user, isWhisper, modules, claim: claim, view: view);
        }
        else
        {
            // Neither claim nor view: just “find”, so output top 3 search results
            IRCConnection.SendMessage("{0}, modules ({2} total) are: {1}", user, !isWhisper, user,
                                      modules.Take(3).Select(handle => string.Format("{0} ({1}) - {2}", handle.HeaderText, handle.Code, handle.Solved ? "solved" : handle.PlayerName == null ? "unclaimed" : "claimed by " + handle.PlayerName)).Join(", "),
                                      modules.Count);
        }
    }
Exemple #28
0
    public static void CallQueuedCommand(string user, bool isWhisper, [Group(1)] bool now, [Group(2)] string name)
    {
        name = name?.Trim();

        if (TwitchGame.Instance.CallingPlayers.Contains(user))
        {
            IRCConnection.SendMessageFormat("@{0}, you already called!", user);
            return;
        }

        var _callsNeeded = TwitchGame.Instance.callsNeeded;
        var _callsTotal  = TwitchGame.Instance.CallingPlayers.Count;

        // Only call if there are enough calls.
        if (!(_callsTotal + 1 >= _callsNeeded) && !now)
        {
            TwitchGame.Instance.CallingPlayers.Add(user);
            CallCountCommand();
            return;
        }

        CommandQueueItem call = null;

        if (string.IsNullOrEmpty(name))
        {
            // Call the first unnamed item in the queue.
            call = TwitchGame.Instance.CommandQueue.Find(item => item.Name == null);

            if (call == null)
            {
                IRCConnection.SendMessage($"@{user}, no unnamed commands in the queue.", user, !isWhisper);
                return;
            }
        }
        else if (name.StartsWith("!"))
        {
            name += ' ';

            // Call an unnamed item in the queue for a specific module.
            call = TwitchGame.Instance.CommandQueue.Find(item => item.Message.Text.StartsWith(name) && item.Name == null);

            if (call == null)
            {
                // If a named command exists, and no unnamed commands exist, then show the name of that command (but don't call it).
                call = TwitchGame.Instance.CommandQueue.Find(item => item.Message.Text.StartsWith(name));

                if (call != null)
                {
                    IRCConnection.SendMessage($"@{user}, module {name} is queued with the name “{call.Name}”, please use “!call {call.Name}” to call it.", user, !isWhisper);
                }
                else
                {
                    IRCConnection.SendMessage($"@{user}, no commands for module {name} in the queue.", user, !isWhisper);
                }

                return;
            }
        }
        else
        {
            // Call a named item in the queue.
            call = TwitchGame.Instance.CommandQueue.FirstOrDefault(item => name.EqualsIgnoreCase(item.Name));

            if (call == null)
            {
                IRCConnection.SendMessage($"@{user}, no commands named “{name}” in the queue.", user, !isWhisper);
                return;
            }
        }
        TwitchGame.Instance.CallingPlayers.Clear();
        TwitchGame.Instance.CommandQueue.Remove(call);
        TwitchGame.ModuleCameras?.SetNotes();
        IRCConnection.SendMessageFormat("{0} {1}: {2}", now
                        ? "Bypassing the required number of calls, calling"
                        : TwitchGame.Instance.callsNeeded > 1
                                ? "Required calls reached, calling"
                                : "Calling", call.Message.UserNickName, call.Message.Text);
        IRCConnection.ReceiveMessage(call.Message);
    }
Exemple #29
0
    private void AwardStrikes(string userNickName, int strikeCount)
    {
        TwitchBomb bomb          = TwitchGame.Instance.Bombs[0];
        int        strikePenalty = -5;

        strikePenalty = TwitchPlaySettings.data.EnableRewardMultipleStrikes ? (strikeCount * strikePenalty) : (Math.Min(strikePenalty, strikeCount * strikePenalty));

        IRCConnection.SendMessageFormat(TwitchPlaySettings.data.AwardHoldableStrike,
                                        ID,
                                        strikeCount == 1 ? "a" : strikeCount.ToString(),
                                        strikeCount == 1 ? "" : "s",
                                        strikePenalty,
                                        userNickName,
                                        string.IsNullOrEmpty(StrikeMessage) ? "" : " caused by " + StrikeMessage);
        if (strikeCount <= 0)
        {
            return;
        }

        string recordMessageTone = $"Holdable ID: {ID} | Player: {userNickName} | Strike";

        TwitchPlaySettings.AppendToSolveStrikeLog(recordMessageTone, TwitchPlaySettings.data.EnableRewardMultipleStrikes ? strikeCount : 1);

        int originalReward = TwitchPlaySettings.GetRewardBonus();
        int currentReward  = Convert.ToInt32(originalReward * (1 - (1 - TwitchPlaySettings.data.AwardDropMultiplierOnStrike) * OtherModes.ScoreMultiplier));

        TwitchPlaySettings.AddRewardBonus(currentReward - originalReward);
        if (currentReward != originalReward)
        {
            IRCConnection.SendMessage($"Reward {(currentReward > 0 ? "reduced" : "increased")} to {currentReward} points.");
        }
        if (OtherModes.TimeModeOn)
        {
            bool   multiDropped = OtherModes.DropMultiplier();
            float  multiplier   = OtherModes.GetMultiplier();
            string tempMessage  = multiDropped
                                ? "Multiplier reduced to " + Math.Round(multiplier, 1) + " and time"
                                : $"Multiplier set at {TwitchPlaySettings.data.TimeModeMinMultiplier}, cannot be further reduced.  Time";
            if (bomb.CurrentTimer < (TwitchPlaySettings.data.TimeModeMinimumTimeLost / TwitchPlaySettings.data.TimeModeTimerStrikePenalty))
            {
                bomb.Bomb.GetTimer().TimeRemaining = bomb.CurrentTimer - TwitchPlaySettings.data.TimeModeMinimumTimeLost;
                tempMessage += $" reduced by {TwitchPlaySettings.data.TimeModeMinimumTimeLost} seconds.";
            }
            else
            {
                float  timeReducer = bomb.CurrentTimer * TwitchPlaySettings.data.TimeModeTimerStrikePenalty;
                double easyText    = Math.Round(timeReducer, 1);
                bomb.Bomb.GetTimer().TimeRemaining = bomb.CurrentTimer - timeReducer;
                tempMessage += $" reduced by {Math.Round(TwitchPlaySettings.data.TimeModeTimerStrikePenalty * 100, 1)}%. ({easyText} seconds)";
            }
            IRCConnection.SendMessage(tempMessage);
            bomb.StrikeCount = 0;
            if (TwitchGame.ModuleCameras != null)
            {
                TwitchGame.ModuleCameras.UpdateStrikes();
            }
        }

        Leaderboard.Instance?.AddScore(userNickName, strikePenalty);
        Leaderboard.Instance?.AddStrike(userNickName, strikeCount);
        StrikeMessage = string.Empty;
    }
Exemple #30
0
 public static void CallCountCommand() => IRCConnection.SendMessageFormat("{0} out of {1} calls needed.", TwitchGame.Instance.CallingPlayers.Count, TwitchGame.Instance.callsNeeded);