Exemplo n.º 1
0
    public static void InitializeGameModes(bool lightsOn)
    {
        if (!lightsOn)
        {
            return;
        }
        if (OtherModes.TimeModeOn)
        {
            OtherModes.SetMultiplier(TwitchPlaySettings.data.TimeModeStartingMultiplier);
        }

        List <TwitchBomb> bombHandles = TwitchGame.Instance.Bombs;

        foreach (TwitchBomb bomb in bombHandles)
        {
            if (OtherModes.TimeModeOn)
            {
                bomb.CurrentTimer = TwitchPlaySettings.data.TimeModeStartingTime * 60;
            }
            else if (OtherModes.ZenModeOn)
            {
                bomb.CurrentTimer = 1;
            }
        }
    }
Exemplo n.º 2
0
    public void InitializeGameModes(bool lightsOn)
    {
        if (!lightsOn)
        {
            return;
        }
        if (OtherModes.TimeModeOn)
        {
            OtherModes.SetMultiplier(TwitchPlaySettings.data.TimeModeStartingMultiplier);
        }

        List <TwitchBombHandle> bombHandles = BombMessageResponder.Instance.BombHandles;

        foreach (TwitchBombHandle handle in bombHandles)
        {
            if (OtherModes.TimeModeOn)
            {
                handle.bombCommander.timerComponent.TimeRemaining = TwitchPlaySettings.data.TimeModeStartingTime * 60;
            }
            else if (OtherModes.ZenModeOn)
            {
                handle.bombCommander.timerComponent.TimeRemaining = 1;
            }
        }
    }
 public void RunMission(KMMission mission)
 {
     if (CurrentState == KMGameInfo.State.Setup)
     {
         GetComponent <KMGameCommands>().StartMission(mission, "-1");
         OtherModes.RefreshModes(KMGameInfo.State.Transitioning);
     }
 }
Exemplo n.º 4
0
    private void OnStateChange(KMGameInfo.State state)
    {
        CurrentState = state;
        if (!transform.gameObject.activeInHierarchy)
        {
            return;
        }

        StartCoroutine(StopEveryCoroutine());

        if (state != KMGameInfo.State.PostGame && _leaderboardDisplay != null)
        {
            DestroyObject(_leaderboardDisplay);
            _leaderboardDisplay = null;
        }

        twitchGame?.gameObject.SetActive(state == KMGameInfo.State.Gameplay);

        OtherModes.RefreshModes(state);

        // Automatically check for updates after a round is finished or when entering the setup state but never more than once per hour.
        bool hourPassed = DateTime.Now.Subtract(Updater.LastCheck).TotalHours >= 1;

        if ((state == KMGameInfo.State.PostGame || state == KMGameInfo.State.Setup) && hourPassed && !Updater.UpdateAvailable)
        {
            _coroutinesToStart.Enqueue(AutomaticUpdateCheck());
        }

        switch (state)
        {
        case KMGameInfo.State.Gameplay:
            DefaultCamera();
            break;

        case KMGameInfo.State.Setup:
            DefaultCamera();
            _coroutinesToStart.Enqueue(VanillaRuleModifier.Refresh());
            _coroutinesToStart.Enqueue(MultipleBombs.Refresh());
            _coroutinesToStart.Enqueue(FactoryRoomAPI.Refresh());
            _coroutinesToStart.Enqueue(FindSupportedModules());
            break;

        case KMGameInfo.State.PostGame:
            DefaultCamera();
            if (_leaderboardDisplay == null)
            {
                _leaderboardDisplay = Instantiate(TwitchLeaderboardPrefab);
            }
            Leaderboard.Instance.SaveDataToFile();
            break;

        case KMGameInfo.State.Transitioning:
            ModuleData.LoadDataFromFile();
            TwitchPlaySettings.LoadDataFromFile();
            break;
        }
    }
Exemplo n.º 5
0
 public static void Setup()
 {
     ModdedAPI.AddProperty("Mode", () => OtherModes.currentMode, value => OtherModes.Set((TwitchPlaysMode)value));
     ModdedAPI.AddProperty("TimeMode", () => OtherModes.TimeModeOn, value => OtherModes.Set(TwitchPlaysMode.Time, (bool)value));
     ModdedAPI.AddProperty("ZenMode", () => OtherModes.Unexplodable, value => OtherModes.Set(TwitchPlaysMode.Zen, (bool)value));
     ModdedAPI.AddProperty("TimeModeStartingTime", () => TwitchPlaySettings.data.TimeModeStartingTime, value => TwitchPlaySettings.data.TimeModeStartingTime = (int)value);
     ModdedAPI.AddProperty("ExplodeBomb", null, value =>
     {
         if (value is string stringValue)
         {
             TwitchGame.Instance.Bombs[0].CauseStrikesToExplosion(stringValue);
         }
     });
 }
Exemplo n.º 6
0
    private void OnStateChange(KMGameInfo.State state)
    {
        CurrentState = state;
        if (!transform.gameObject.activeInHierarchy)
        {
            return;
        }

        StartCoroutine(StopEveryCoroutine());

        if (state != KMGameInfo.State.PostGame && _leaderboardDisplay != null)
        {
            DestroyObject(_leaderboardDisplay);
            _leaderboardDisplay = null;
        }

        twitchGame?.gameObject.SetActive(state == KMGameInfo.State.Gameplay);

        OtherModes.RefreshModes(state);

        switch (state)
        {
        case KMGameInfo.State.Gameplay:
            DefaultCamera();
            break;

        case KMGameInfo.State.Setup:
            DefaultCamera();
            _coroutinesToStart.Enqueue(VanillaRuleModifier.Refresh());
            _coroutinesToStart.Enqueue(MultipleBombs.Refresh());
            _coroutinesToStart.Enqueue(FactoryRoomAPI.Refresh());
            _coroutinesToStart.Enqueue(FindSupportedModules());
            break;

        case KMGameInfo.State.PostGame:
            DefaultCamera();
            if (_leaderboardDisplay == null)
            {
                _leaderboardDisplay = Instantiate(TwitchLeaderboardPrefab);
            }
            Leaderboard.Instance.SaveDataToFile();
            break;

        case KMGameInfo.State.Transitioning:
            ModuleData.LoadDataFromFile();
            TwitchPlaySettings.LoadDataFromFile();
            break;
        }
    }
    private void OnEnable()
    {
        BombActive = true;
        EnableDisableInput();
        leaderboard.ClearSolo();
        TwitchPlaysService.logUploader.Clear();

        bool bombStarted = false;

        parentService.GetComponent <KMGameInfo>().OnLightsChange += delegate(bool on)
        {
            if (bombStarted || !on)
            {
                return;
            }
            bombStarted = true;

            if (TwitchPlaySettings.data.BombLiveMessageDelay > 0)
            {
                System.Threading.Thread.Sleep(TwitchPlaySettings.data.BombLiveMessageDelay * 1000);
            }

            if (_bombCommanders.Count == 1)
            {
                _ircConnection.SendMessage(TwitchPlaySettings.data.BombLiveMessage);
            }
            else
            {
                _ircConnection.SendMessage(TwitchPlaySettings.data.MultiBombLiveMessage);
            }

            if (TwitchPlaySettings.data.EnableAutomaticEdgework)
            {
                foreach (var commander in _bombCommanders)
                {
                    commander.FillEdgework(commander.twitchBombHandle.bombID != _currentBomb);
                }
            }
            OtherModes.setMultiplier(9);
        };

        StartCoroutine(CheckForBomb());
    }
Exemplo n.º 8
0
 private void AwardSolve(string userNickName, int ComponentValue)
 {
     if (OtherModes.ZenModeOn)
     {
         ComponentValue = (int)Math.Ceiling(ComponentValue * 0.20f);
     }
     if (userNickName == null)
     {
         TwitchPlaySettings.AddRewardBonus(ComponentValue);
     }
     else
     {
         string headerText = UnsupportedModule ? modInfo.moduleDisplayName : BombComponent.GetModuleDisplayName();
         IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.AwardSolve, Code, userNickName, ComponentValue, headerText);
         string RecordMessageTone = $"Module ID: {Code} | Player: {userNickName} | Module Name: {headerText} | Value: {ComponentValue}";
         Leaderboard.Instance?.AddSolve(userNickName);
         if (!UserAccess.HasAccess(userNickName, AccessLevel.NoPoints))
         {
             Leaderboard.Instance?.AddScore(userNickName, ComponentValue);
         }
         else
         {
             TwitchPlaySettings.AddRewardBonus(ComponentValue);
         }
         TwitchPlaySettings.AppendToSolveStrikeLog(RecordMessageTone);
         TwitchPlaySettings.AppendToPlayerLog(userNickName);
     }
     if (OtherModes.TimeModeOn)
     {
         float time = OtherModes.GetAdjustedMultiplier() * ComponentValue;
         if (time < TwitchPlaySettings.data.TimeModeMinimumTimeGained)
         {
             BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer + TwitchPlaySettings.data.TimeModeMinimumTimeGained;
             IRCConnection.Instance.SendMessage("Bomb time increased by the minimum {0} seconds!", TwitchPlaySettings.data.TimeModeMinimumTimeGained);
         }
         else
         {
             BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer + time;
             IRCConnection.Instance.SendMessage("Bomb time increased by {0} seconds!", Math.Round(time, 1));
         }
         OtherModes.SetMultiplier(OtherModes.GetMultiplier() + TwitchPlaySettings.data.TimeModeSolveBonus);
     }
 }
    private void OnDisable()
    {
        _hideBombs = false;
        BombActive = false;
        EnableDisableInput();
        TwitchComponentHandle.ClaimedList.Clear();
        TwitchComponentHandle.ClearUnsupportedModules();
        StopAllCoroutines();
        Leaderboard.Instance.BombsAttempted++;
        parentService.GetComponent <KMGameInfo>().OnLightsChange -= OnLightsChange;

        LogUploader.Instance.Post();
        parentService.StartCoroutine(SendDelayedMessage(1.0f, GetBombResult(), SendAnalysisLink));

        moduleCameras?.gameObject.SetActive(false);

        foreach (TwitchBombHandle handle in BombHandles)
        {
            if (handle != null)
            {
                Destroy(handle.gameObject, 2.0f);
            }
        }
        BombHandles.Clear();
        BombCommanders.Clear();

        DestroyComponentHandles();

        MusicPlayer.StopAllMusic();

        GameRoom.Instance?.OnDisable();
        OtherModes.RefreshModes();

        try
        {
            string path = Path.Combine(Application.persistentDataPath, "TwitchPlaysLastClaimed.json");
            File.WriteAllText(path, SettingsConverter.Serialize(LastClaimedModule));
        }
        catch (Exception ex)
        {
            DebugHelper.LogException(ex, "Couldn't Write TwitchPlaysLastClaimed.json:");
        }
    }
Exemplo n.º 10
0
    public static void Status(TwitchBomb bomb, string user, bool isWhisper)
    {
        int currentReward = TwitchPlaySettings.GetRewardBonus();

        if (OtherModes.TimeModeOn)
        {
            IRCConnection.SendMessage(string.Format(TwitchPlaySettings.data.BombStatusTimeMode, bomb.GetFullFormattedTime, bomb.GetFullStartingTime,
                                                    OtherModes.GetAdjustedMultiplier(), bomb.BombSolvedModules, bomb.BombSolvableModules, currentReward), user, !isWhisper);
        }
        else if (OtherModes.VSModeOn)
        {
            IRCConnection.SendMessage(string.Format(TwitchPlaySettings.data.BombStatusVsMode, bomb.GetFullFormattedTime,
                                                    bomb.GetFullStartingTime, OtherModes.goodHealth, OtherModes.evilHealth, currentReward), user, !isWhisper);
        }
        else
        {
            IRCConnection.SendMessage(string.Format(TwitchPlaySettings.data.BombStatus, bomb.GetFullFormattedTime, bomb.GetFullStartingTime,
                                                    bomb.StrikeCount, bomb.StrikeLimit, bomb.BombSolvedModules, bomb.BombSolvableModules, currentReward), user, !isWhisper);
        }
    }
Exemplo n.º 11
0
 public void UpdateConfidence()
 {
     if (OtherModes.TimeModeOn)
     {
         float timedMultiplier = OtherModes.GetAdjustedMultiplier();
         ConfidencePrefab.color = Color.yellow;
         string conf = "x" + $"{timedMultiplier:0.0}";
         string pts  = "+" + $"{TwitchPlaySettings.GetRewardBonus():0}";
         ConfidencePrefab.text = pts;
         StrikesPrefab.color   = Color.yellow;
         StrikesPrefab.text    = conf;
     }
     else if (OtherModes.ZenModeOn)
     {
         ConfidencePrefab.color = Color.yellow;
         string pts = "+" + $"{TwitchPlaySettings.GetRewardBonus():0}";
         ConfidencePrefab.text = pts;
         StrikesPrefab.color   = Color.red;
         if (_currentBomb != null)
         {
             StrikesPrefab.text = _currentBomb.StrikeCount.ToString();
         }
     }
     else if (OtherModes.VSModeOn)
     {
         int bossHealth = OtherModes.GetEvilHealth();
         int teamHealth = OtherModes.GetGoodHealth();
         StrikesPrefab.color    = Color.cyan;
         ConfidencePrefab.color = Color.red;
         StrikesPrefab.text     = $"{teamHealth} HP";
         ConfidencePrefab.text  = $"{bossHealth} HP";
     }
     else
     {
         ConfidencePrefab.color = Color.yellow;
         string pts = $"+{TwitchPlaySettings.GetRewardBonus():0}";
         ConfidencePrefab.text = pts;
     }
 }
Exemplo n.º 12
0
    private void AwardSolve(string userNickName, ICommandResponseNotifier responseNotifier, int ComponentValue)
    {
        string headerText = UnsupportedModule ? modInfo.moduleDisplayName : BombComponent.GetModuleDisplayName();

        IRCConnection.SendMessage(TwitchPlaySettings.data.AwardSolve, Code, userNickName, ComponentValue, headerText);
        string RecordMessageTone = $"Module ID: {Code} | Player: {userNickName} | Module Name: {headerText} | Value: {ComponentValue}";

        responseNotifier.ProcessResponse(CommandResponse.EndComplete, ComponentValue);
        TwitchPlaySettings.AppendToSolveStrikeLog(RecordMessageTone);
        TwitchPlaySettings.AppendToPlayerLog(userNickName);
        if (OtherModes.timedModeOn)
        {
            float multiplier = OtherModes.getMultiplier();
            float time       = multiplier * ComponentValue;
            BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer + time;
            IRCConnection.SendMessage("Bomb time increased by {0} seconds!", Math.Round(time, 1));
            if (multiplier < 10)
            {
                multiplier = multiplier + 0.1f;
                OtherModes.setMultiplier(multiplier);
            }
        }
    }
Exemplo n.º 13
0
    private void AwardStrikes(string userNickName, ICommandResponseNotifier responseNotifier, int strikeCount)
    {
        string headerText    = BombComponent.GetModuleDisplayName();
        int    strikePenalty = modInfo.strikePenalty * (TwitchPlaySettings.data.EnableRewardMultipleStrikes ? strikeCount : 1);

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

        string RecordMessageTone = $"Module ID: {Code} | Player: {userNickName} | Module Name: {headerText} | Strike";

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

        int currentReward = TwitchPlaySettings.GetRewardBonus();

        currentReward = Convert.ToInt32(currentReward * .80);
        TwitchPlaySettings.SetRewardBonus(currentReward);
        IRCConnection.SendMessage("Reward reduced to " + currentReward + " points.");
        if (OtherModes.timedModeOn)
        {
            bool   multiDropped = OtherModes.dropMultiplier();
            float  multiplier   = OtherModes.getMultiplier();
            string tempMessage;
            if (multiDropped)
            {
                tempMessage = "Multiplier reduced to " + Math.Round(multiplier, 1) + " and time";
            }
            else
            {
                tempMessage = "Mutliplier set at 1, cannot be further reduced.  Time";
            }
            if (BombCommander.CurrentTimer < 60)
            {
                BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer - 15;
                tempMessage = tempMessage + " reduced by 15 seconds.";
            }
            else
            {
                float  timeReducer = BombCommander.CurrentTimer * .25f;
                double easyText    = Math.Round(timeReducer, 1);
                BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer - timeReducer;
                tempMessage = tempMessage + " reduced by 25%. (" + easyText + " seconds)";
            }
            IRCConnection.SendMessage(tempMessage);
        }
        if (responseNotifier != null)
        {
            responseNotifier.ProcessResponse(CommandResponse.EndErrorSubtractScore, strikePenalty);
            responseNotifier.ProcessResponse(CommandResponse.EndError, strikeCount);
        }
        else
        {
            ComponentHandle.leaderboard.AddScore(userNickName, strikePenalty);
            ComponentHandle.leaderboard.AddStrike(userNickName, strikeCount);
        }
        if (OtherModes.timedModeOn)
        {
            BombCommander.StrikeCount = 0;
            BombMessageResponder.moduleCameras.UpdateStrikes();
        }
        StrikeMessage = string.Empty;
    }
    protected override void OnMessageReceived(string userNickName, string userColorCode, string text)
    {
        if (!text.StartsWith("!") || text.Equals("!"))
        {
            return;
        }
        text = text.Substring(1);

        string[] split     = text.ToLowerInvariant().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        string   textAfter = split.Skip(1).Join();

        if (text.Equals("cancel", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            _coroutineCanceller.SetCancel();
            return;
        }
        else if (text.Equals("stop", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            _coroutineCanceller.SetCancel();
            _coroutineQueue.CancelFutureSubcoroutines();
            return;
        }
        else if (text.Equals("manual", StringComparison.InvariantCultureIgnoreCase) ||
                 text.Equals("help", StringComparison.InvariantCultureIgnoreCase))
        {
            _ircConnection.SendMessage("!{0} manual [link to module {0}'s manual] | Go to {1} to get the vanilla manual for KTaNE", UnityEngine.Random.Range(1, 100), TwitchPlaysService.urlHelper.VanillaManual);
            _ircConnection.SendMessage("!{0} help [commands for module {0}] | Go to {1} to get the command reference for TP:KTaNE (multiple pages, see the menu on the right)", UnityEngine.Random.Range(1, 100), TwitchPlaysService.urlHelper.CommandReference);
            return;
        }
        else if (text.StartsWith("bonusscore", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            if (split.Length < 3)
            {
                return;
            }
            string playerrewarded = split[1];
            if (!int.TryParse(split[2], out int scorerewarded))
            {
                return;
            }
            if (UserAccess.HasAccess(userNickName, AccessLevel.SuperUser, true))
            {
                _ircConnection.SendMessage(TwitchPlaySettings.data.GiveBonusPoints, split[1], split[2], userNickName);
                Color usedColor = new Color(.31f, .31f, .31f);
                leaderboard.AddScore(playerrewarded, usedColor, scorerewarded);
            }
            return;
        }
        else if (text.StartsWith("reward", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            if (UserAccess.HasAccess(userNickName, AccessLevel.SuperUser, true))
            {
                moduleCountBonus = Int32.Parse(split[1]);
                TwitchPlaySettings.SetRewardBonus(moduleCountBonus);
            }
        }
        else if (text.Equals("timemode", StringComparison.InvariantCultureIgnoreCase))
        {
            if (UserAccess.HasAccess(userNickName, AccessLevel.Mod, true))
            {
                OtherModes.toggleTimedMode();
                _ircConnection.SendMessage(OtherModes.timedModeCheck() ? "Time Mode Enabled" : "Time Mode Disabled");
            }
        }
        else if (text.StartsWith("rank", StringComparison.InvariantCultureIgnoreCase))
        {
            Leaderboard.LeaderboardEntry entry = null;
            if (split.Length > 1)
            {
                int desiredRank;
                switch (split.Length)
                {
                case 3 when split[1].Equals("solo", StringComparison.InvariantCultureIgnoreCase) && int.TryParse(split[2], out desiredRank):
    private void OnStateChange(KMGameInfo.State state)
    {
        CurrentState = state;

        if (!transform.gameObject.activeInHierarchy)
        {
            return;
        }

        StartCoroutine(StopEveryCoroutine());
        CheckSupport.Cleanup();
        Votes.Clear();

        if (state != KMGameInfo.State.PostGame && _leaderboardDisplay != null)
        {
            DestroyObject(_leaderboardDisplay);
            _leaderboardDisplay = null;
        }

        twitchGame?.gameObject.SetActive(state == KMGameInfo.State.Gameplay);

        OtherModes.RefreshModes(state);

        // Automatically check for updates after a round is finished or when entering the setup state but never more than once per hour.
        bool hourPassed = DateTime.Now.Subtract(Updater.LastCheck).TotalHours >= 1;

        if ((state == KMGameInfo.State.PostGame || state == KMGameInfo.State.Setup) && hourPassed && !Updater.UpdateAvailable)
        {
            _coroutinesToStart.Enqueue(AutomaticUpdateCheck());
        }

        switch (state)
        {
        case KMGameInfo.State.Gameplay:
            DefaultCamera();
            break;

        case KMGameInfo.State.Setup:
            DefaultCamera();
            _coroutinesToStart.Enqueue(VanillaRuleModifier.Refresh());
            _coroutinesToStart.Enqueue(MultipleBombs.Refresh());
            _coroutinesToStart.Enqueue(FactoryRoomAPI.Refresh());

            if (!initialLoad)
            {
                initialLoad = true;
                _coroutinesToStart.Enqueue(ComponentSolverFactory.LoadDefaultInformation(true));
                if (!TwitchPlaySettings.data.TwitchPlaysDebugEnabled)
                {
                    _coroutinesToStart.Enqueue(CheckSupport.FindSupportedModules());
                }
            }

            // Clear out the retry reward if we return to the setup room since the retry button doesn't return to setup.
            // A post game run command would set the retry bonus and then return to the setup room to start the mission, so we don't want to clear that.
            if (TwitchPlaySettings.GetRewardBonus() == 0)
            {
                TwitchPlaySettings.ClearRetryReward();
            }
            break;

        case KMGameInfo.State.PostGame:
            DefaultCamera();
            if (_leaderboardDisplay == null)
            {
                _leaderboardDisplay = Instantiate(TwitchLeaderboardPrefab);
            }
            Leaderboard.Instance.SaveDataToFile();
            break;

        case KMGameInfo.State.Transitioning:
            ModuleData.LoadDataFromFile();
            TwitchPlaySettings.LoadDataFromFile();

            var pageManager = SceneManager.Instance?.SetupState?.Room.GetComponent <SetupRoom>().BombBinder.MissionTableOfContentsPageManager;
            if (pageManager != null)
            {
                var tableOfContentsList = pageManager.GetValue <List <Assets.Scripts.BombBinder.MissionTableOfContents> >("tableOfContentsList");
                if (tableOfContentsList[SetupState.LastBombBinderTOCIndex].ToCID == "toc_tp_search")
                {
                    SetupState.LastBombBinderTOCIndex = 0;
                    SetupState.LastBombBinderTOCPage  = 0;
                }
            }

            break;
        }
    }
Exemplo n.º 16
0
    public IEnumerator OnMessageReceived(string userNickName, string userColor, string text)
    {
        string internalCommand;
        Match  match = Regex.Match(text, string.Format("^{0} (.+)", _code), RegexOptions.IgnoreCase);

        if (!match.Success)
        {
            match = Regex.Match(text, string.Format("^{0}(?> (.+))?", _edgeworkCode), RegexOptions.IgnoreCase);
            if (match.Success)
            {
                internalCommand = match.Groups[1].Value;
                if (!string.IsNullOrEmpty(internalCommand))
                {
                    if (!IsAuthorizedDefuser(userNickName))
                    {
                        return(null);
                    }
                    edgeworkText.text = internalCommand;
                }
                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombEdgework, edgeworkText.text);
            }
            return(null);
        }

        internalCommand = match.Groups[1].Value;

        TwitchMessage message = Instantiate <TwitchMessage>(messagePrefab, messageScrollContents.transform, false);

        message.SetMessage(string.IsNullOrEmpty(userColor)
                        ? string.Format("<b>{0}</b>: {1}", userNickName, internalCommand)
                        : string.Format("<b><color={2}>{0}</color></b>: {1}", userNickName, internalCommand, userColor));

        string internalCommandLower = internalCommand.ToLowerInvariant();

        string[] split = internalCommandLower.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);

        //Respond instantly to these commands without dropping "The Bomb", should the command be for "The Other Bomb" and vice versa.
        ICommandResponseNotifier notifier = message;

        if (internalCommandLower.EqualsAny("timestamp", "date"))
        {
            //Some modules depend on the date/time the bomb, and therefore that Module instance has spawned, in the bomb defusers timezone.

            notifier.ProcessResponse(CommandResponse.Start);
            IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombTimeStamp, bombCommander.BombTimeStamp);
            notifier.ProcessResponse(CommandResponse.EndNotComplete);
        }
        else if (internalCommandLower.Equals("help"))
        {
            notifier.ProcessResponse(CommandResponse.Start);

            IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombHelp);

            notifier.ProcessResponse(CommandResponse.EndNotComplete);
        }
        else if (internalCommandLower.EqualsAny("time", "timer", "clock"))
        {
            notifier.ProcessResponse(CommandResponse.Start);
            IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombTimeRemaining, bombCommander.GetFullFormattedTime, bombCommander.GetFullStartingTime);
            notifier.ProcessResponse(CommandResponse.EndNotComplete);
        }
        else if (internalCommandLower.EqualsAny("explode", "detonate", "endzenmode"))
        {
            if (UserAccess.HasAccess(userNickName, AccessLevel.Mod, true) || (OtherModes.ZenModeOn && internalCommandLower.Equals("endzenmode")))
            {
                return(DelayBombExplosionCoroutine(notifier));
            }

            return(null);
        }
        else if (internalCommandLower.Equals("status") || internalCommandLower.Equals("info"))
        {
            int currentReward = TwitchPlaySettings.GetRewardBonus();
            if (OtherModes.TimeModeOn)
            {
                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombStatusTimeMode, bombCommander.GetFullFormattedTime, bombCommander.GetFullStartingTime,
                                                   OtherModes.GetAdjustedMultiplier(), bombCommander.bombSolvedModules, bombCommander.bombSolvableModules, currentReward);
            }
            else if (OtherModes.VSModeOn)
            {
                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombStatusVsMode, bombCommander.GetFullFormattedTime,
                                                   bombCommander.GetFullStartingTime, OtherModes.teamHealth, OtherModes.bossHealth, currentReward);
            }
            else
            {
                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombStatus, bombCommander.GetFullFormattedTime, bombCommander.GetFullStartingTime,
                                                   bombCommander.StrikeCount, bombCommander.StrikeLimit, bombCommander.bombSolvedModules, bombCommander.bombSolvableModules, currentReward);
            }
        }
        else if (split[0].EqualsAny("add", "increase", "change", "subtract", "decrease", "remove", "set"))
        {
            if (UserAccess.HasAccess(userNickName, AccessLevel.Admin, true))
            {
                bool negitive = split[0].EqualsAny("subtract", "decrease", "remove");
                bool direct   = split[0].EqualsAny("set");
                switch (split[1])
                {
                case "time":
                case "t":
                    float time = 0;
                    Dictionary <string, float> timeLengths = new Dictionary <string, float>()
                    {
                        { "ms", 0.001f },
                        { "s", 1 },
                        { "m", 60 },
                        { "h", 3600 },
                        { "d", 86400 },
                        { "w", 604800 },
                        { "y", 31536000 },
                    };

                    foreach (string part in split.Skip(2))
                    {
                        bool valid = false;
                        foreach (string unit in timeLengths.Keys)
                        {
                            if (!part.EndsWith(unit) || !float.TryParse(part.Substring(0, part.Length - unit.Length), out float length))
                            {
                                continue;
                            }
                            time += length * timeLengths[unit];
                            valid = true;
                            break;
                        }

                        if (!valid)
                        {
                            return(null);
                        }
                    }

                    time = (float)Math.Round((decimal)time, 2, MidpointRounding.AwayFromZero);
                    if (!direct && Math.Abs(time) == 0)
                    {
                        break;
                    }
                    if (negitive)
                    {
                        time = -time;
                    }

                    if (direct)
                    {
                        bombCommander.timerComponent.TimeRemaining = time;
                    }
                    else
                    {
                        bombCommander.timerComponent.TimeRemaining = bombCommander.CurrentTimer + time;
                    }

                    if (direct)
                    {
                        IRCConnection.Instance.SendMessage("Set the bomb's timer to {0}.", Math.Abs(time < 0 ? 0 : time).FormatTime());
                    }
                    else
                    {
                        IRCConnection.Instance.SendMessage("{0} {1} {2} the timer.", time > 0 ? "Added" : "Subtracted", Math.Abs(time).FormatTime(), time > 0 ? "to" : "from");
                    }
                    break;

                case "strikes":
                case "strike":
                case "s":
                    if (int.TryParse(split[2], out int strikes) && (strikes != 0 || direct))
                    {
                        if (negitive)
                        {
                            strikes = -strikes;
                        }

                        if (direct && strikes < 0)
                        {
                            strikes = 0;
                        }
                        else if (!direct && (bombCommander.StrikeCount + strikes) < 0)
                        {
                            strikes = -bombCommander.StrikeCount;                                       //Minimum of zero strikes. (Simon says is unsolvable with negative strikes.)
                        }

                        if (direct)
                        {
                            bombCommander.StrikeCount = strikes;
                        }
                        else
                        {
                            bombCommander.StrikeCount += strikes;
                        }

                        if (direct)
                        {
                            IRCConnection.Instance.SendMessage("Set the bomb's strike count to {0} {1}.", Math.Abs(strikes), Math.Abs(strikes) != 1 ? "strikes" : "strike");
                        }
                        else
                        {
                            IRCConnection.Instance.SendMessage("{0} {1} {2} {3} the bomb.", strikes > 0 ? "Added" : "Subtracted", Math.Abs(strikes), Math.Abs(strikes) != 1 ? "strikes" : "strike", strikes > 0 ? "to" : "from");
                        }
                        BombMessageResponder.moduleCameras.UpdateStrikes();
                    }
                    break;

                case "strikelimit":
                case "sl":
                case "maxstrikes":
                case "ms":
                    if (int.TryParse(split[2], out int maxStrikes) && (maxStrikes != 0 || direct))
                    {
                        if (negitive)
                        {
                            maxStrikes = -maxStrikes;
                        }

                        if (direct && maxStrikes < 0)
                        {
                            maxStrikes = 0;
                        }
                        else if (!direct && (bombCommander.StrikeLimit + maxStrikes) < 0)
                        {
                            maxStrikes = -bombCommander.StrikeLimit;
                        }

                        if (direct)
                        {
                            bombCommander.StrikeLimit = maxStrikes;
                        }
                        else
                        {
                            bombCommander.StrikeLimit += maxStrikes;
                        }

                        if (direct)
                        {
                            IRCConnection.Instance.SendMessage("Set the bomb's strike limit to {0} {1}.", Math.Abs(maxStrikes), Math.Abs(maxStrikes) != 1 ? "strikes" : "strike");
                        }
                        else
                        {
                            IRCConnection.Instance.SendMessage("{0} {1} {2} {3} the strike limit.", maxStrikes > 0 ? "Added" : "Subtracted", Math.Abs(maxStrikes), Math.Abs(maxStrikes) > 1 ? "strikes" : "strike", maxStrikes > 0 ? "to" : "from");
                        }
                        BombMessageResponder.moduleCameras.UpdateStrikes();
                        BombMessageResponder.moduleCameras.UpdateStrikeLimit();
                    }
                    break;
                }
            }

            return(null);
        }
        else if (!IsAuthorizedDefuser(userNickName))
        {
            return(null);
        }
        else
        {
            return(RespondToCommandCoroutine(userNickName, internalCommand, message));
        }

        return(null);
    }
Exemplo n.º 17
0
    private void AwardStrikes(string userNickName, int strikeCount)
    {
        BombCommander BombCommander = BombMessageResponder.Instance.BombCommanders[0];
        int           strikePenalty = -5;

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

        IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.AwardHoldableStrike,
                                           HoldableCommander.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: {HoldableCommander.ID} | Player: {userNickName} | Strike";

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

        int originalReward = TwitchPlaySettings.GetRewardBonus();
        int currentReward  = Convert.ToInt32(originalReward * TwitchPlaySettings.data.AwardDropMultiplierOnStrike);

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

        Leaderboard.Instance?.AddScore(userNickName, strikePenalty);
        Leaderboard.Instance?.AddStrike(userNickName, strikeCount);
        StrikeMessage = string.Empty;
    }
Exemplo n.º 18
0
    private void AwardStrikes(string userNickName, int strikeCount)
    {
        string headerText    = UnsupportedModule ? modInfo.moduleDisplayName : BombComponent.GetModuleDisplayName();
        int    strikePenalty = modInfo.strikePenalty * (TwitchPlaySettings.data.EnableRewardMultipleStrikes ? strikeCount : 1);

        if (OtherModes.ZenModeOn)
        {
            strikePenalty = (int)(strikePenalty * 0.20f);
        }
        IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.AwardStrike, Code, strikeCount == 1 ? "a" : strikeCount.ToString(), strikeCount == 1 ? "" : "s", 0, userNickName, string.IsNullOrEmpty(StrikeMessage) ? "" : " caused by " + StrikeMessage, headerText, strikePenalty);
        if (strikeCount <= 0)
        {
            return;
        }

        string RecordMessageTone = $"Module ID: {Code} | Player: {userNickName} | Module Name: {headerText} | Strike";

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

        int originalReward = TwitchPlaySettings.GetRewardBonus();
        int currentReward  = Convert.ToInt32(originalReward * TwitchPlaySettings.data.AwardDropMultiplierOnStrike);

        TwitchPlaySettings.SetRewardBonus(currentReward);
        if (currentReward != originalReward)
        {
            IRCConnection.Instance.SendMessage($"Reward {(currentReward > 0 ? "reduced" : "increased")} to {currentReward} points.");
        }
        if (OtherModes.TimeModeOn)
        {
            float  originalMultiplier = OtherModes.GetAdjustedMultiplier();
            bool   multiDropped       = OtherModes.DropMultiplier();
            float  multiplier         = OtherModes.GetAdjustedMultiplier();
            string tempMessage;
            if (multiDropped)
            {
                if (Mathf.Abs(originalMultiplier - multiplier) >= 0.1)
                {
                    tempMessage = "Multiplier reduced to " + Math.Round(multiplier, 1) + " and time";
                }
                else
                {
                    tempMessage = "Time";
                }
            }
            else
            {
                tempMessage = $"Multiplier set at {TwitchPlaySettings.data.TimeModeMinMultiplier}, cannot be further reduced.  Time";
            }
            if (BombCommander.CurrentTimer < (TwitchPlaySettings.data.TimeModeMinimumTimeLost / TwitchPlaySettings.data.TimeModeTimerStrikePenalty))
            {
                BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer - TwitchPlaySettings.data.TimeModeMinimumTimeLost;
                tempMessage = tempMessage + $" reduced by {TwitchPlaySettings.data.TimeModeMinimumTimeLost} seconds.";
            }
            else
            {
                float  timeReducer = BombCommander.CurrentTimer * TwitchPlaySettings.data.TimeModeTimerStrikePenalty;
                double easyText    = Math.Round(timeReducer, 1);
                BombCommander.timerComponent.TimeRemaining = BombCommander.CurrentTimer - timeReducer;
                tempMessage = tempMessage + $" reduced by {Math.Round(TwitchPlaySettings.data.TimeModeTimerStrikePenalty * 100, 1)}%. ({easyText} seconds)";
            }
            IRCConnection.Instance.SendMessage(tempMessage);
            BombCommander.StrikeCount = 0;
            BombMessageResponder.moduleCameras.UpdateStrikes();
        }
        if (OtherModes.ZenModeOn)
        {
            BombCommander.StrikeLimit += strikeCount;
        }

        Leaderboard.Instance.AddScore(userNickName, strikePenalty);
        Leaderboard.Instance.AddStrike(userNickName, strikeCount);
        StrikeMessage = string.Empty;
    }
    protected override void OnMessageReceived(string userNickName, string userColorCode, string text)
    {
        if (text.EqualsAny("!notes1", "!notes2", "!notes3", "!notes4"))
        {
            int index = "1234".IndexOf(text.Substring(6, 1), StringComparison.Ordinal);
            _ircConnection.SendMessage(TwitchPlaySettings.data.Notes, index + 1, _notes[index]);
            return;
        }

        if (text.StartsWith("!notes1 ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!notes2 ", StringComparison.InvariantCultureIgnoreCase) ||
            text.StartsWith("!notes3 ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!notes4 ", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            int    index = "1234".IndexOf(text.Substring(6, 1), StringComparison.Ordinal);
            string notes = text.Substring(8);
            if (notes == "")
            {
                return;
            }

            _ircConnection.SendMessage(TwitchPlaySettings.data.NotesTaken, index + 1, notes);

            _notes[index] = notes;
            moduleCameras?.SetNotes(index, notes);
            return;
        }

        if (text.StartsWith("!appendnotes1 ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!appendnotes2 ", StringComparison.InvariantCultureIgnoreCase) ||
            text.StartsWith("!appendnotes3 ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!appendnotes4 ", StringComparison.InvariantCultureIgnoreCase))
        {
            text = text.Substring(0, 1) + text.Substring(7, 6) + text.Substring(1, 6) + text.Substring(13);
        }

        if (text.StartsWith("!notes1append ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!notes2append ", StringComparison.InvariantCultureIgnoreCase) ||
            text.StartsWith("!notes3append ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!notes4append ", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            int    index = "1234".IndexOf(text.Substring(6, 1), StringComparison.Ordinal);
            string notes = text.Substring(14);
            if (notes == "")
            {
                return;
            }

            _ircConnection.SendMessage(TwitchPlaySettings.data.NotesAppended, index + 1, notes);

            _notes[index] += " " + notes;
            moduleCameras?.AppendNotes(index, notes);
            return;
        }

        if (text.EqualsAny("!clearnotes1", "!clearnotes2", "!clearnotes3", "!clearnotes4"))
        {
            text = text.Substring(0, 1) + text.Substring(6, 6) + text.Substring(1, 5);
        }

        if (text.EqualsAny("!notes1clear", "!notes2clear", "!notes3clear", "!notes4clear"))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            int index = "1234".IndexOf(text.Substring(6, 1), StringComparison.Ordinal);
            _notes[index] = TwitchPlaySettings.data.NotesSpaceFree;
            _ircConnection.SendMessage(TwitchPlaySettings.data.NoteSlotCleared, index + 1);

            moduleCameras?.SetNotes(index, TwitchPlaySettings.data.NotesSpaceFree);
            return;
        }

        if (text.Equals("!snooze", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            if (TwitchPlaySettings.data.AllowSnoozeOnly)
            {
                alarmClock.TurnOff();
            }
            else
            {
                alarmClock.ButtonDown(0);
            }
            return;
        }

        if (text.Equals("!stop", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName, true))
            {
                return;
            }
            _currentBomb = _coroutineQueue.CurrentBombID;
            return;
        }

        if (text.Equals("!modules", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            moduleCameras?.AttachToModules(_componentHandles);
            return;
        }

        if (text.StartsWith("!claims ", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            userNickName = text.Substring(8);
            text         = "!claims";
            if (userNickName == "")
            {
                return;
            }
        }

        if (text.Equals("!claims", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }
            List <string> claimed = (from handle in _componentHandles where handle.PlayerName != null && handle.PlayerName.Equals(userNickName, StringComparison.InvariantCultureIgnoreCase) && !handle.Solved select string.Format(TwitchPlaySettings.data.OwnedModule, handle.idText.text.Replace("!", ""), handle.headerText.text)).ToList();
            if (claimed.Count > 0)
            {
                string message = string.Format(TwitchPlaySettings.data.OwnedModuleList, userNickName, string.Join(", ", claimed.ToArray(), 0, Math.Min(claimed.Count, 5)));
                if (claimed.Count > 5)
                {
                    message += "...";
                }
                _ircConnection.SendMessage(message);
            }
            else
            {
                _ircConnection.SendMessage(TwitchPlaySettings.data.NoOwnedModules, userNickName);
            }
            return;
        }

        if (text.StartsWith("!claim ", StringComparison.InvariantCultureIgnoreCase))
        {
            var split = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var claim in split.Skip(1))
            {
                TwitchComponentHandle handle = _componentHandles.FirstOrDefault(x => x.Code.Equals(claim));
                if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                {
                    continue;
                }
                handle.OnMessageReceived(userNickName, userColorCode, string.Format("!{0} claim", claim));
            }
            return;
        }

        if (text.EqualsAny("!unclaim all", "!release all", "!unclaimall", "!releaseall"))
        {
            string[] moduleIDs = _componentHandles.Where(x => x.PlayerName != null && x.PlayerName.Equals(userNickName, StringComparison.InvariantCultureIgnoreCase))
                                 .Select(x => x.Code).ToArray();
            text = string.Format("!unclaim {0}", string.Join(" ", moduleIDs));
        }

        if (text.StartsWith("!unclaim ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!release ", StringComparison.InvariantCultureIgnoreCase))
        {
            var split = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var claim in split.Skip(1))
            {
                TwitchComponentHandle handle = _componentHandles.FirstOrDefault(x => x.Code.Equals(claim));
                if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                {
                    continue;
                }
                handle.OnMessageReceived(userNickName, userColorCode, string.Format("!{0} unclaim", claim));
            }
            return;
        }



        if (text.Equals("!unclaimed", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }

            IEnumerable <string> unclaimed = _componentHandles.Where(handle => !handle.claimed && !handle.Solved && GameRoom.Instance.IsCurrentBomb(handle.bombID)).Shuffle().Take(3)
                                             .Select(handle => string.Format("{0} ({1})", handle.headerText.text, handle.Code)).ToList();

            if (unclaimed.Any())
            {
                _ircConnection.SendMessage("Unclaimed Modules: {0}", unclaimed.Join(", "));
            }
            else
            {
                _ircConnection.SendMessage("There are no more unclaimed modules.");
            }

            return;
        }

        if (text.StartsWith("!find ", StringComparison.InvariantCultureIgnoreCase) || text.StartsWith("!search ", StringComparison.InvariantCultureIgnoreCase))
        {
            if (!IsAuthorizedDefuser(userNickName))
            {
                return;
            }

            var    split = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            string query = split.Skip(1).Join(" ");
            IEnumerable <string> modules = _componentHandles.Where(handle => handle.headerText.text.ContainsIgnoreCase(query) && GameRoom.Instance.IsCurrentBomb(handle.bombID))
                                           .OrderByDescending(handle => handle.headerText.text.EqualsIgnoreCase(query)).ThenBy(handle => handle.Solved).ThenBy(handle => handle.PlayerName != null).Take(3)
                                           .Select(handle => string.Format("{0} ({1}) - {2}", handle.headerText.text, handle.Code,
                                                                           handle.Solved ? "Solved" : (handle.PlayerName == null ? "Unclaimed" : "Claimed by " + handle.PlayerName)
                                                                           )).ToList();

            if (modules.Any())
            {
                _ircConnection.SendMessage("Modules: {0}", modules.Join(", "));
            }
            else
            {
                _ircConnection.SendMessage("Couldn't find any modules containing \"{0}\".", query);
            }

            return;
        }

        if (text.Equals("!filledgework", StringComparison.InvariantCultureIgnoreCase) && UserAccess.HasAccess(userNickName, AccessLevel.Mod, true))
        {
            foreach (var commander in _bombCommanders)
            {
                commander.FillEdgework(_currentBomb != commander.twitchBombHandle.bombID);
            }
            return;
        }

        if (text.StartsWith("!setmultiplier", StringComparison.InvariantCultureIgnoreCase) && UserAccess.HasAccess(userNickName, AccessLevel.SuperUser, true))
        {
            float tempNumber = float.Parse(text.Substring(15));
            OtherModes.setMultiplier(tempNumber);
        }

        if (text.Equals("!solvebomb", StringComparison.InvariantCultureIgnoreCase) && UserAccess.HasAccess(userNickName, AccessLevel.SuperUser, true))
        {
            foreach (var handle in _componentHandles.Where(x => GameRoom.Instance.IsCurrentBomb(x.bombID)))
            {
                if (!handle.Solved)
                {
                    handle.SolveSilently();
                }
            }
            return;
        }

        GameRoom.Instance.RefreshBombID(ref _currentBomb);

        if (_currentBomb > -1)
        {
            //Check for !bomb messages, and pass them off to the currently held bomb.
            Match match = Regex.Match(text, "^!bomb (.+)", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                string internalCommand = match.Groups[1].Value;
                text = string.Format("!bomb{0} {1}", _currentBomb + 1, internalCommand);
            }

            match = Regex.Match(text, "^!edgework$");
            if (match.Success)
            {
                text = string.Format("!edgework{0}", _currentBomb + 1);
            }
            else
            {
                match = Regex.Match(text, "^!edgework (.+)");
                if (match.Success)
                {
                    string internalCommand = match.Groups[1].Value;
                    text = string.Format("!edgework{0} {1}", _currentBomb + 1, internalCommand);
                }
            }
        }

        foreach (TwitchBombHandle handle in _bombHandles)
        {
            if (handle == null)
            {
                continue;
            }
            IEnumerator onMessageReceived = handle.OnMessageReceived(userNickName, userColorCode, text);
            if (onMessageReceived == null)
            {
                continue;
            }

            if (_currentBomb != handle.bombID)
            {
                if (!GameRoom.Instance.IsCurrentBomb(handle.bombID))
                {
                    continue;
                }

                _coroutineQueue.AddToQueue(_bombHandles[_currentBomb].HideMainUIWindow(), handle.bombID);
                _coroutineQueue.AddToQueue(handle.ShowMainUIWindow(), handle.bombID);
                _coroutineQueue.AddToQueue(_bombCommanders[_currentBomb].LetGoBomb(), handle.bombID);

                _currentBomb = handle.bombID;
            }
            _coroutineQueue.AddToQueue(onMessageReceived, handle.bombID);
        }

        foreach (TwitchComponentHandle componentHandle in _componentHandles)
        {
            if (!GameRoom.Instance.IsCurrentBomb(componentHandle.bombID))
            {
                continue;
            }
            IEnumerator onMessageReceived = componentHandle.OnMessageReceived(userNickName, userColorCode, text);
            if (onMessageReceived == null)
            {
                continue;
            }

            if (_currentBomb != componentHandle.bombID)
            {
                _coroutineQueue.AddToQueue(_bombHandles[_currentBomb].HideMainUIWindow(), componentHandle.bombID);
                _coroutineQueue.AddToQueue(_bombHandles[componentHandle.bombID].ShowMainUIWindow(), componentHandle.bombID);
                _coroutineQueue.AddToQueue(_bombCommanders[_currentBomb].LetGoBomb(), componentHandle.bombID);
                _currentBomb = componentHandle.bombID;
            }
            _coroutineQueue.AddToQueue(onMessageReceived, componentHandle.bombID);
        }
    }
    protected override void OnMessageReceived(string userNickName, string userColorCode, string text)
    {
        Match match;
        int   index;

        if (!text.StartsWith("!") || text.Equals("!"))
        {
            return;
        }
        text = text.Substring(1);

        if (IsAuthorizedDefuser(userNickName))
        {
            if (text.RegexMatch(out match, "^notes(-?[0-9]+) (.+)$") && int.TryParse(match.Groups[1].Value, out index))
            {
                string notes = match.Groups[2].Value;

                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.NotesTaken, index--, notes);

                _notesDictionary[index] = notes;
                moduleCameras?.SetNotes(index, notes);
                return;
            }

            if (text.RegexMatch(out match, "^notes(-?[0-9]+)append (.+)", "^appendnotes(-?[0-9]+) (.+)") && int.TryParse(match.Groups[1].Value, out index))
            {
                string notes = match.Groups[2].Value;

                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.NotesAppended, index--, notes);
                if (!_notesDictionary.ContainsKey(index))
                {
                    _notesDictionary[index] = TwitchPlaySettings.data.NotesSpaceFree;
                }

                _notesDictionary[index] += " " + notes;
                moduleCameras?.AppendNotes(index, notes);
                return;
            }

            if (text.RegexMatch(out match, "^clearnotes(-?[0-9]+)$", "^notes(-?[0-9]+)clear$") && int.TryParse(match.Groups[1].Value, out index))
            {
                IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.NoteSlotCleared, index--);

                _notesDictionary[index] = (OtherModes.ZenModeOn && index == 3) ? TwitchPlaySettings.data.ZenModeFreeSpace : TwitchPlaySettings.data.NotesSpaceFree;
                moduleCameras?.SetNotes(index, _notesDictionary[index]);
                return;
            }

            if (text.Equals("snooze", StringComparison.InvariantCultureIgnoreCase))
            {
                if (GameRoom.Instance is ElevatorGameRoom)
                {
                    return;                                                         //There is no alarm clock in the elevator room.
                }
                DropCurrentBomb();
                _coroutineQueue.AddToQueue(AlarmClockHoldableHandler.Instance.RespondToCommand(userNickName, "alarmclock snooze"));
                return;
            }

            if (text.Equals("modules", StringComparison.InvariantCultureIgnoreCase))
            {
                moduleCameras?.AttachToModules(ComponentHandles);
                return;
            }

            if (text.RegexMatch(out match, "^claims (.+)"))
            {
                OnMessageReceived(match.Groups[1].Value, userColorCode, "!claims");
                return;
            }

            if (text.Equals("claims", StringComparison.InvariantCultureIgnoreCase))
            {
                List <string> claimed = (
                    from handle in ComponentHandles
                    where handle.PlayerName != null && handle.PlayerName.Equals(userNickName, StringComparison.InvariantCultureIgnoreCase) && !handle.Solved
                    select string.Format(TwitchPlaySettings.data.OwnedModule, handle.Code, handle.HeaderText)).ToList();
                if (claimed.Count > 0)
                {
                    string message = string.Format(TwitchPlaySettings.data.OwnedModuleList, userNickName, string.Join(", ", claimed.ToArray(), 0, Math.Min(claimed.Count, 5)));
                    if (claimed.Count > 5)
                    {
                        message += "...";
                    }
                    IRCConnection.Instance.SendMessage(message);
                }
                else
                {
                    IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.NoOwnedModules, userNickName);
                }
                return;
            }


            if (text.RegexMatch("^(?:claim ?|view ?|all ?){2,3}$"))
            {
                if (text.Contains("claim") && text.Contains("all"))
                {
                    foreach (var handle in ComponentHandles)
                    {
                        if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                        {
                            continue;
                        }
                        handle.AddToClaimQueue(userNickName, text.Contains("view"));
                    }
                    return;
                }
            }

            if (text.StartsWith("claim ", StringComparison.InvariantCultureIgnoreCase))
            {
                var split = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var claim in split.Skip(1))
                {
                    TwitchComponentHandle handle = ComponentHandles.FirstOrDefault(x => x.Code.Equals(claim, StringComparison.InvariantCultureIgnoreCase));
                    if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                    {
                        continue;
                    }
                    handle.AddToClaimQueue(userNickName);
                }
                return;
            }

            if (text.RegexMatch("^(unclaim|release) ?all$"))
            {
                foreach (TwitchComponentHandle handle in ComponentHandles)
                {
                    handle.RemoveFromClaimQueue(userNickName);
                }
                string[] moduleIDs = ComponentHandles.Where(x => !x.Solved && x.PlayerName != null && x.PlayerName.Equals(userNickName, StringComparison.InvariantCultureIgnoreCase))
                                     .Select(x => x.Code).ToArray();
                text = string.Format("unclaim {0}", string.Join(" ", moduleIDs));
            }

            if (text.RegexMatch(out match, "^(?:unclaim|release) (.+)"))
            {
                var split = match.Groups[1].Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var claim in split)
                {
                    TwitchComponentHandle handle = ComponentHandles.FirstOrDefault(x => x.Code.Equals(claim));
                    if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                    {
                        continue;
                    }
                    handle.OnMessageReceived(userNickName, userColorCode, "unclaim");
                }
                return;
            }

            if (text.Equals("unclaimed", StringComparison.InvariantCultureIgnoreCase))
            {
                IEnumerable <string> unclaimed = ComponentHandles.Where(handle => !handle.Claimed && !handle.Solved && GameRoom.Instance.IsCurrentBomb(handle.bombID)).Shuffle().Take(3)
                                                 .Select(handle => string.Format($"{handle.HeaderText} ({handle.Code})")).ToList();

                if (unclaimed.Any())
                {
                    IRCConnection.Instance.SendMessage("Unclaimed Modules: {0}", unclaimed.Join(", "));
                }
                else
                {
                    IRCConnection.Instance.SendMessage("There are no more unclaimed modules.");
                }

                return;
            }

            if (text.Equals("unsolved", StringComparison.InvariantCultureIgnoreCase))
            {
                IEnumerable <string> unsolved = ComponentHandles.Where(handle => !handle.Solved && GameRoom.Instance.IsCurrentBomb(handle.bombID)).Shuffle().Take(3)
                                                .Select(handle => string.Format("{0} ({1}) - {2}", handle.HeaderText, handle.Code,
                                                                                handle.PlayerName == null ? "Unclaimed" : "Claimed by " + handle.PlayerName)).ToList();
                if (unsolved.Any())
                {
                    IRCConnection.Instance.SendMessage("Unsolved Modules: {0}", unsolved.Join(", "));
                }
                else
                {
                    IRCConnection.Instance.SendMessage("There are no unsolved modules, something went wrong as this message should never be displayed.");                  //this should never happen
                }
                return;
            }

            if (text.RegexMatch(out match, "^(?:find|search) (.+)"))
            {
                string[] queries = match.Groups[1].Value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

                foreach (string query in queries)
                {
                    string trimmed = query.Trim();
                    IEnumerable <string> modules = ComponentHandles.Where(handle => handle.HeaderText.ContainsIgnoreCase(trimmed) && GameRoom.Instance.IsCurrentBomb(handle.bombID))
                                                   .OrderByDescending(handle => handle.HeaderText.EqualsIgnoreCase(trimmed)).ThenBy(handle => handle.Solved).ThenBy(handle => handle.PlayerName != null).Take(3)
                                                   .Select(handle => string.Format("{0} ({1}) - {2}", handle.HeaderText, handle.Code,
                                                                                   handle.Solved ? "Solved" : (handle.PlayerName == null ? "Unclaimed" : "Claimed by " + handle.PlayerName)
                                                                                   )).ToList();

                    if (modules.Any())
                    {
                        IRCConnection.Instance.SendMessage("Modules: {0}", modules.Join(", "));
                    }
                    else
                    {
                        IRCConnection.Instance.SendMessage($"Couldn't find any modules containing \"{trimmed}\".");
                    }
                }

                return;
            }

            if (text.RegexMatch(out match, "^(?:findplayer|playerfind|searchplayer|playersearch) (.+)"))
            {
                string[] queries = match.Groups[1].Value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToArray();
                foreach (string query in queries)
                {
                    string trimmed = query.Trim();
                    IEnumerable <TwitchComponentHandle> modules = ComponentHandles.Where(handle => handle.HeaderText.ContainsIgnoreCase(trimmed) && GameRoom.Instance.IsCurrentBomb(handle.bombID))
                                                                  .OrderByDescending(handle => handle.HeaderText.EqualsIgnoreCase(trimmed)).ThenBy(handle => handle.Solved).ToList();
                    IEnumerable <string> playerModules = modules.Where(handle => handle.PlayerName != null).OrderByDescending(handle => handle.HeaderText.EqualsIgnoreCase(trimmed))
                                                         .Select(handle => string.Format($"{handle.HeaderText} ({handle.Code}) - Claimed by {handle.PlayerName}")).ToList();
                    if (modules.Any())
                    {
                        if (playerModules.Any())
                        {
                            IRCConnection.Instance.SendMessage("Modules: {0}", playerModules.Join(", "));
                        }
                        else
                        {
                            IRCConnection.Instance.SendMessage("None of the specified modules are claimed/have been solved.");
                        }
                    }
                    else
                    {
                        IRCConnection.Instance.SendMessage($"Could not find any modules containing \"{trimmed}\".");
                    }
                }
            }

            if (text.RegexMatch(out match, "^(claim ?(?:any|van|mod) ?(?:view)?|view ?claim ?(?:any|van|mod))"))
            {
                var vanilla = match.Groups[1].Value.Contains("van");
                var modded  = match.Groups[1].Value.Contains("mod");
                var view    = match.Groups[1].Value.Contains("view");
                var avoid   = new[] { "Souvenir", "Forget Me Not", "Turn The Key", "Turn The Keys", "The Swan", "Forget Everything" };

                var unclaimed = ComponentHandles
                                .Where(handle => (vanilla ? !handle.IsMod : modded ? handle.IsMod : true) && !handle.Claimed && !handle.Solved && !avoid.Contains(handle.HeaderText) && GameRoom.Instance.IsCurrentBomb(handle.bombID))
                                .Shuffle().FirstOrDefault();

                if (unclaimed != null)
                {
                    text = unclaimed.Code + (view ? " claimview" : " claim");
                }
                else
                {
                    IRCConnection.Instance.SendMessage(string.Format("There are no more unclaimed{0} modules.", vanilla ? " vanilla" : modded ? " modded" : null));
                }
            }

            if (text.RegexMatch(out match, "^(?:findsolved|solvedfind|searchsolved|solvedsearch) (.+)"))
            {
                string[] queries = match.Groups[1].Value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToArray();
                foreach (string query in queries)
                {
                    string trimmed = query.Trim();
                    IEnumerable <BombCommander>         commanders = BombCommanders.Where(handle => handle.SolvedModules.Keys.ToArray().Any(x => x.ContainsIgnoreCase(trimmed))).ToList();
                    IEnumerable <TwitchComponentHandle> modules    = commanders.SelectMany(x => x.SolvedModules.Where(y => y.Key.ContainsIgnoreCase(trimmed)))
                                                                     .OrderByDescending(x => x.Key.EqualsIgnoreCase(trimmed)).SelectMany(x => x.Value).ToList();
                    IEnumerable <string> playerModules = modules.Where(handle => handle.PlayerName != null)
                                                         .Select(handle => string.Format($"{handle.HeaderText} ({handle.Code}) - Claimed by {handle.PlayerName}", handle.HeaderText, handle.Code, "Claimed by " + handle.PlayerName)).ToList();
                    if (commanders.Any())
                    {
                        if (playerModules.Any())
                        {
                            IRCConnection.Instance.SendMessage("Modules: {0}", playerModules.Join(", "));
                        }
                        else
                        {
                            IRCConnection.Instance.SendMessage("None of the specified modules have been solved.");
                        }
                    }
                    else
                    {
                        IRCConnection.Instance.SendMessage($"Could not find any modules containing \"{trimmed}\".");
                    }
                }
            }

            if (text.RegexMatch(out match, "^((?:(?:find|search)|claim|view|all){2,4}) (.+)"))
            {
                bool validFind  = match.Groups[1].Value.Contains("find") || match.Groups[1].Value.Contains("search");
                bool validClaim = match.Groups[1].Value.Contains("claim");
                if (!validFind || !validClaim)
                {
                    return;
                }

                bool validView = match.Groups[1].Value.Contains("view");
                bool validAll  = match.Groups[1].Value.Contains("all");

                string[] queries = match.Groups[2].Value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                int      counter = 0;

                foreach (string query in queries)
                {
                    if (counter == 2)
                    {
                        return;
                    }
                    string trimmed = query.Trim();
                    IEnumerable <string> modules = ComponentHandles.Where(handle => handle.HeaderText.ContainsIgnoreCase(trimmed) && GameRoom.Instance.IsCurrentBomb(handle.bombID) && !handle.Solved && !handle.Claimed)
                                                   .OrderByDescending(handle => handle.HeaderText.EqualsIgnoreCase(trimmed)).Select(handle => $"{handle.Code}").ToList();
                    if (modules.Any())
                    {
                        if (!validAll)
                        {
                            modules = modules.Take(1);
                        }
                        foreach (string module in modules)
                        {
                            TwitchComponentHandle handle = ComponentHandles.FirstOrDefault(x => x.Code.Equals(module));
                            if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                            {
                                continue;
                            }
                            handle.AddToClaimQueue(userNickName, validView);
                        }
                        if (validAll)
                        {
                            counter++;
                        }
                    }
                    else
                    {
                        IRCConnection.Instance.SendMessage($"Couldn't find any modules containing \"{trimmed}\".");
                    }
                }
                return;
            }

            if (text.Equals("newbomb", StringComparison.InvariantCultureIgnoreCase) && OtherModes.ZenModeOn)
            {
                TwitchPlaySettings.SetRewardBonus(0);
                foreach (var handle in ComponentHandles.Where(x => GameRoom.Instance.IsCurrentBomb(x.bombID)))
                {
                    if (!handle.Solved)
                    {
                        handle.SolveSilently();
                    }
                }
                return;
            }
        }

        if (text.RegexMatch(out match, "^notes(-?[0-9]+)$") && int.TryParse(match.Groups[1].Value, out index))
        {
            if (!_notesDictionary.ContainsKey(index - 1))
            {
                _notesDictionary[index - 1] = TwitchPlaySettings.data.NotesSpaceFree;
            }
            IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.Notes, index, _notesDictionary[index - 1]);
            return;
        }

        switch (UserAccess.HighestAccessLevel(userNickName))
        {
        case AccessLevel.Streamer:
        case AccessLevel.SuperUser:
            if (text.RegexMatch(out match, @"^setmultiplier ([0-9]+(?:\.[0-9]+)*)$"))
            {
                OtherModes.SetMultiplier(float.Parse(match.Groups[1].Value));
                return;
            }

            if (text.Equals("solvebomb", StringComparison.InvariantCultureIgnoreCase))
            {
                foreach (var handle in ComponentHandles.Where(x => GameRoom.Instance.IsCurrentBomb(x.bombID)))
                {
                    if (!handle.Solved)
                    {
                        handle.SolveSilently();
                    }
                }
                return;
            }
            goto case AccessLevel.Admin;

        case AccessLevel.Admin:
            if (text.Equals("enablecamerawall", StringComparison.InvariantCultureIgnoreCase) || text.Equals("enablemodulewall", StringComparison.InvariantCultureIgnoreCase))
            {
                moduleCameras.EnableWallOfCameras();
                StartCoroutine(HideBombs());
            }

            if (text.Equals("disablecamerawall", StringComparison.InvariantCultureIgnoreCase) || text.Equals("disablemodulewall", StringComparison.InvariantCultureIgnoreCase))
            {
                moduleCameras.DisableWallOfCameras();
                _hideBombs = false;
            }
            goto case AccessLevel.Mod;

        case AccessLevel.Mod:
            if (text.RegexMatch(out match, @"^assign (\S+) (.+)"))
            {
                var split = match.Groups[2].Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var assign in split)
                {
                    TwitchComponentHandle handle = ComponentHandles.FirstOrDefault(x => x.Code.Equals(assign));
                    if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                    {
                        continue;
                    }
                    handle.OnMessageReceived(userNickName, userColorCode, string.Format("assign {0}", match.Groups[1].Value));
                }
                return;
            }

            if (text.RegexMatch("^bot ?unclaim( ?all)?$"))
            {
                userNickName = IRCConnection.Instance.UserNickName;
                foreach (TwitchComponentHandle handle in ComponentHandles)
                {
                    handle.RemoveFromClaimQueue(userNickName);
                }
                string[] moduleIDs = ComponentHandles.Where(x => !x.Solved && x.PlayerName != null && x.PlayerName.Equals(userNickName, StringComparison.InvariantCultureIgnoreCase))
                                     .Select(x => x.Code).ToArray();
                foreach (var claim in moduleIDs)
                {
                    TwitchComponentHandle handle = ComponentHandles.FirstOrDefault(x => x.Code.Equals(claim));
                    if (handle == null || !GameRoom.Instance.IsCurrentBomb(handle.bombID))
                    {
                        continue;
                    }
                    handle.OnMessageReceived(userNickName, userColorCode, "unclaim");
                }
                return;
            }

            if (text.Equals("filledgework", StringComparison.InvariantCultureIgnoreCase))
            {
                foreach (var commander in BombCommanders)
                {
                    commander.FillEdgework(_currentBomb != commander.twitchBombHandle.bombID);
                }
                return;
            }
            break;
        }

        GameRoom.Instance.RefreshBombID(ref _currentBomb);

        if (_currentBomb > -1)
        {
            //Check for !bomb messages, and pass them off to the currently held bomb.
            if (text.RegexMatch(out match, "^bomb (.+)"))
            {
                string internalCommand = match.Groups[1].Value;
                text = string.Format("bomb{0} {1}", _currentBomb + 1, internalCommand);
            }

            if (text.RegexMatch(out match, "^edgework$"))
            {
                text = string.Format("edgework{0}", _currentBomb + 1);
            }
            else
            {
                if (text.RegexMatch(out match, "^edgework (.+)"))
                {
                    string internalCommand = match.Groups[1].Value;
                    text = string.Format("edgework{0} {1}", _currentBomb + 1, internalCommand);
                }
            }
        }

        foreach (TwitchBombHandle handle in BombHandles)
        {
            if (handle == null)
            {
                continue;
            }
            IEnumerator onMessageReceived = handle.OnMessageReceived(userNickName, userColorCode, text);
            if (onMessageReceived == null)
            {
                continue;
            }

            if (_currentBomb != handle.bombID)
            {
                if (!GameRoom.Instance.IsCurrentBomb(handle.bombID))
                {
                    continue;
                }

                _coroutineQueue.AddToQueue(BombHandles[_currentBomb].HideMainUIWindow(), handle.bombID);
                _coroutineQueue.AddToQueue(handle.ShowMainUIWindow(), handle.bombID);
                _coroutineQueue.AddToQueue(BombCommanders[_currentBomb].LetGoBomb(), handle.bombID);

                _currentBomb = handle.bombID;
            }
            _coroutineQueue.AddToQueue(onMessageReceived, handle.bombID);
        }

        foreach (TwitchComponentHandle componentHandle in ComponentHandles)
        {
            if (!GameRoom.Instance.IsCurrentBomb(componentHandle.bombID))
            {
                continue;
            }
            if (!text.StartsWith(componentHandle.Code + " "))
            {
                continue;
            }
            IEnumerator onMessageReceived = componentHandle.OnMessageReceived(userNickName, userColorCode, text.Substring(componentHandle.Code.Length + 1));
            if (onMessageReceived == null)
            {
                continue;
            }

            if (_currentBomb != componentHandle.bombID)
            {
                _coroutineQueue.AddToQueue(BombHandles[_currentBomb].HideMainUIWindow(), componentHandle.bombID);
                _coroutineQueue.AddToQueue(BombHandles[componentHandle.bombID].ShowMainUIWindow(), componentHandle.bombID);
                _coroutineQueue.AddToQueue(BombCommanders[_currentBomb].LetGoBomb(), componentHandle.bombID);
                _currentBomb = componentHandle.bombID;
            }
            _coroutineQueue.AddToQueue(onMessageReceived, componentHandle.bombID);
        }

        if (TwitchPlaySettings.data.BombCustomMessages.ContainsKey(text.ToLowerInvariant()))
        {
            IRCConnection.Instance.SendMessage(TwitchPlaySettings.data.BombCustomMessages[text.ToLowerInvariant()]);
        }
    }
Exemplo n.º 21
0
    public string GetBombResult(bool lastBomb = true)
    {
        bool   hasDetonated           = false;
        bool   hasBeenSolved          = true;
        float  timeStarting           = float.MaxValue;
        float  timeRemaining          = float.MaxValue;
        string timeRemainingFormatted = "";

        foreach (TwitchBomb bomb in Bombs)
        {
            if (bomb == null)
            {
                continue;
            }

            hasDetonated  |= bomb.Bomb.HasDetonated;
            hasBeenSolved &= bomb.IsSolved;
            if (timeRemaining > bomb.CurrentTimer)
            {
                timeStarting  = bomb.BombStartingTimer;
                timeRemaining = bomb.CurrentTimer;
            }

            if (!string.IsNullOrEmpty(timeRemainingFormatted))
            {
                timeRemainingFormatted += ", " + bomb.GetFullFormattedTime;
            }
            else
            {
                timeRemainingFormatted = bomb.GetFullFormattedTime;
            }
        }

        string bombMessage = "";

        if (OtherModes.VSModeOn && (hasDetonated || hasBeenSolved))
        {
            OtherModes.Team winner = OtherModes.Team.Good;
            if (OtherModes.GetGoodHealth() == 0)
            {
                winner      = OtherModes.Team.Evil;
                bombMessage = TwitchPlaySettings.data.VersusEvilHeader;
            }
            else if (OtherModes.GetEvilHealth() == 0)
            {
                winner      = OtherModes.Team.Good;
                bombMessage = TwitchPlaySettings.data.VersusGoodHeader;
            }

            bombMessage += string.Format(TwitchPlaySettings.data.VersusEndMessage,
                                         winner == OtherModes.Team.Good ? "good" : "evil", timeRemainingFormatted);
            bombMessage += TwitchPlaySettings.GiveBonusPoints();

            if (winner == OtherModes.Team.Good)
            {
                bombMessage += TwitchPlaySettings.data.VersusGoodFooter;
            }
            else if (winner == OtherModes.Team.Evil)
            {
                bombMessage += TwitchPlaySettings.data.VersusEvilFooter;
            }

            if (lastBomb && hasBeenSolved)
            {
                Leaderboard.Instance.Success = true;
            }
        }
        else if (hasDetonated)
        {
            bombMessage = string.Format(TwitchPlaySettings.data.BombExplodedMessage, timeRemainingFormatted);
            Leaderboard.Instance.BombsExploded += Bombs.Count;
            if (!lastBomb)
            {
                return(bombMessage);
            }

            Leaderboard.Instance.Success = false;
            TwitchPlaySettings.ClearPlayerLog();
        }
        else if (hasBeenSolved)
        {
            bombMessage = string.Format(TwitchPlaySettings.data.BombDefusedMessage, timeRemainingFormatted);

            Leaderboard.Instance.BombsCleared += Bombs.Count;
            bombMessage += TwitchPlaySettings.GiveBonusPoints();

            if (lastBomb)
            {
                Leaderboard.Instance.Success = true;
            }

            if (Leaderboard.Instance.CurrentSolvers.Count != 1)
            {
                return(bombMessage);
            }

            float  elapsedTime = timeStarting - timeRemaining;
            string userName    = "";
            foreach (string uName in Leaderboard.Instance.CurrentSolvers.Keys)
            {
                userName = uName;
                break;
            }
            if (Leaderboard.Instance.CurrentSolvers[userName] == Leaderboard.RequiredSoloSolves * Bombs.Count && OtherModes.currentMode == TwitchPlaysMode.Normal)
            {
                Leaderboard.Instance.AddSoloClear(userName, elapsedTime, out float previousRecord);
                if (TwitchPlaySettings.data.EnableSoloPlayMode)
                {
                    //Still record solo information, should the defuser be the only one to actually defuse a 11 * bomb-count bomb, but display normal leaderboards instead if
                    //solo play is disabled.
                    TimeSpan elapsedTimeSpan = TimeSpan.FromSeconds(elapsedTime);
                    string   soloMessage     = string.Format(TwitchPlaySettings.data.BombSoloDefusalMessage, Leaderboard.Instance.SoloSolver.UserName, (int)elapsedTimeSpan.TotalMinutes, elapsedTimeSpan.Seconds);
                    if (elapsedTime < previousRecord)
                    {
                        TimeSpan previousTimeSpan = TimeSpan.FromSeconds(previousRecord);
                        soloMessage += string.Format(TwitchPlaySettings.data.BombSoloDefusalNewRecordMessage, (int)previousTimeSpan.TotalMinutes, previousTimeSpan.Seconds);
                    }
                    soloMessage += TwitchPlaySettings.data.BombSoloDefusalFooter;
                    ParentService.StartCoroutine(SendDelayedMessage(1.0f, soloMessage));
                }
                else
                {
                    Leaderboard.Instance.ClearSolo();
                }
            }
            else
            {
                Leaderboard.Instance.ClearSolo();
            }
        }
        else
        {
            bombMessage = string.Format(TwitchPlaySettings.data.BombAbortedMessage, timeRemainingFormatted);
            Leaderboard.Instance.Success = false;
            TwitchPlaySettings.ClearPlayerLog();
        }
        return(bombMessage);
    }
Exemplo n.º 22
0
 public static void SetMultiplier([Group(1)] float multiplier) => OtherModes.SetMultiplier(multiplier);
Exemplo n.º 23
0
 public void UpdateConfidence()
 {
     if (OtherModes.timedModeOn)
     {
         float timedMultiplier = OtherModes.getMultiplier();
         confidencePrefab.color = Color.yellow;
         string conf = "x" + String.Format("{0:0.0}", timedMultiplier);
         string pts  = "+" + String.Format("{0:0}", TwitchPlaySettings.GetRewardBonus());
         confidencePrefab.text   = pts;
         strikesPrefab.color     = Color.yellow;
         strikeLimitPrefab.color = Color.yellow;
         strikesPrefab.text      = conf;
         strikeLimitPrefab.text  = "";
     }
     //     if (OtherModes.vsModeOn)
     //     {
     //         int bossHealth = OtherModes.getBossHealth();
     //         int teamHealth = OtherModes.getTeamHealth();
     //
     //     }
     else
     {
         confidencePrefab.color = Color.yellow;
         string pts = "+" + String.Format("{0:0}", TwitchPlaySettings.GetRewardBonus());
         confidencePrefab.text = pts;
         //    int previousSuccess = (int)(currentSuccess * 100);
         //    currentSuccess = PlayerSuccessRating;
         //
         //    if (previousSuccess != (int)(currentSuccess * 100))
         //    {
         //        float minHue = 0.0f; // red (0deg)
         //        float maxHue = (float)1 / 3; // green (120deg)
         //        float minBeforeValueDown = 0.25f;
         //        float maxBeforeSaturationDown = 0.75f;
         //        float minValue = 0.25f;
         //        float minSaturation = 0.0f;
         //        float lowSuccessDesaturationSpeed = 3.0f;
         //
         //        float hueSuccessRange = maxBeforeSaturationDown - minBeforeValueDown;
         //        float hueRange = maxHue - minHue;
         //        float valueRange = 1.0f - minValue;
         //        float saturationRange = 1.0f - minSaturation;
         //
         //        float hue, pointOnScale;
         //        float saturation = 1.0f;
         //        float value = 1.0f;
         //
         //        if (currentSuccess < minBeforeValueDown)
         //        {
         //            // At very low ratings, move from red to dark grey
         //            hue = minHue;
         //            pointOnScale = (currentSuccess - (minBeforeValueDown / lowSuccessDesaturationSpeed)) * lowSuccessDesaturationSpeed;
         //            pointOnScale = Math.Max(pointOnScale, 0.0f) / minBeforeValueDown;
         //            saturation = minSaturation + (saturationRange * pointOnScale);
         //            pointOnScale = currentSuccess / maxBeforeSaturationDown;
         //            value = minValue + (valueRange * pointOnScale);
         //        }
         //        else if (currentSuccess > maxBeforeSaturationDown)
         //        {
         //            // At very high ratings, move from green to white
         //            hue = maxHue;
         //            pointOnScale = ((1.0f - currentSuccess) / (1.0f - maxBeforeSaturationDown));
         //            saturation = minSaturation + (saturationRange * pointOnScale);
         //        }
         //        else
         //        {
         //            // At moderate ratings, move between red and green
         //            pointOnScale = ((currentSuccess - minBeforeValueDown) / hueSuccessRange);
         //            hue = minHue + (hueRange * pointOnScale);
         //        }
         //
         //        confidencePrefab.color = Color.HSVToRGB(hue, saturation, value);
         //    }
         //
         //
         //    string conf = string.Format("{0:00}%", currentSuccess * 100);
         //    confidencePrefab.text = conf;
     }
 }