private IEnumerator CheckForBomb()
    {
        yield return(new WaitUntil(() => SceneManager.Instance.GameplayState.Bombs != null && SceneManager.Instance.GameplayState.Bombs.Count > 0));

        yield return(new WaitForSeconds(2.0f));

        Bombs.AddRange(SceneManager.Instance.GameplayState.Bombs);
        int i = 0;

        string[] keyModules =
        {
            "SouvenirModule", "MemoryV2", "TurnTheKey", "TurnTheKeyAdvanced", "theSwan", "HexiEvilFMN", "taxReturns"
        };
        foreach (Bomb bomb in Bombs)
        {
            BombCommanders.Add(new BombCommander(bomb, i));
            foreach (BombComponent bombComponent in bomb.BombComponents)
            {
                ComponentTypeEnum componentType = bombComponent.ComponentType;
                bool   keyModule  = false;
                string moduleName = string.Empty;

                switch (componentType)
                {
                case ComponentTypeEnum.Empty:
                case ComponentTypeEnum.Timer:
                    continue;

                case ComponentTypeEnum.NeedyCapacitor:
                case ComponentTypeEnum.NeedyKnob:
                case ComponentTypeEnum.NeedyVentGas:
                case ComponentTypeEnum.NeedyMod:
                    moduleName = bombComponent.GetModuleDisplayName();
                    keyModule  = true;
                    break;

                case ComponentTypeEnum.Mod:
                    KMBombModule KMModule = bombComponent.GetComponent <KMBombModule>();
                    keyModule = keyModules.Contains(KMModule.ModuleType);
                    goto default;

                default:
                    moduleName = bombComponent.GetModuleDisplayName();
                    break;
                }
                Module module = new Module(bombComponent, i)
                {
                    ComponentType = componentType,
                    IsKeyModule   = keyModule,
                    ModuleName    = moduleName
                };

                Modules.Add(module);
            }
            i++;
        }
        BombActive = true;
    }
    private Module GetFocusedModule()
    {
        Module focused = null;

        foreach (Module module in Modules)
        {
            if (module.IsHeld())
            {
                focused = module;
            }
        }
        return(focused);
    }
Exemplo n.º 3
0
 private void SolveModule(Module module)
 {
     if (!Leaderboardoff)
     {
         ChangeLeaderboard(true);
         Debug.Log("[Command Line] Disabling leaderboard.");
     }
     try
     {
         CommonReflectedTypeInfo.HandlePassMethod.Invoke(module.BombComponent, null);
         foreach (MonoBehaviour behavior in module.BombComponent.GetComponentsInChildren <MonoBehaviour>(true))
         {
             behavior.StopAllCoroutines();
         }
     }
     catch (Exception ex)
     {
         Log($"Exception while force solving module: {ex}");
     }
 }
 private void SolveModule(Module module)
 {
     Debug.LogFormat("[Command Line] Solving module: {0}", module.ModuleName);
     if (!Leaderboardoff)
     {
         ChangeLeaderboard(true);
         Debug.Log("[Command Line] Disabling leaderboard.");
     }
     try
     {
         const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
         foreach (MonoBehaviour mb in module.BombComponent.GetComponentsInChildren <MonoBehaviour>())
         {
             MethodInfo method = mb.GetType().GetMethod("TwitchHandleForcedSolve", Flags);
             if (method == null)
             {
                 continue;
             }
             if (method.ReturnType == typeof(void))
             {
                 try { method.Invoke(mb, null); } catch { continue; }
             }
             if (method.ReturnType == typeof(IEnumerator))
             {
                 try
                 {
                     IEnumerator e = (IEnumerator)method.Invoke(mb, null);
                     SolveMethods.Enqueue(e);
                     SolveMethodsModules.Enqueue(module);
                     if (!IsSolving)
                     {
                         IsSolving = true;
                     }
                 }
                 catch { }
             }
         }
         if (IsSolving && !IsCoroutineStarted)
         {
             StartCoroutine(SolveBomb());
             IsSolving = false;
         }
         else
         {
             throw new Exception();
         }
     }
     catch
     {
         try
         {
             CommonReflectedTypeInfo.HandlePassMethod.Invoke(module.BombComponent, null);
             foreach (MonoBehaviour behavior in module.BombComponent.GetComponentsInChildren <MonoBehaviour>(true))
             {
                 behavior.StopAllCoroutines();
             }
         }
         catch (Exception ex)
         {
             Log($"Exception while force solving module: {ex}");
         }
     }
 }
    private void ProcessCommand(string command)
    {
        string        commandTrimmed = command.Trim().ToLowerInvariant();
        List <string> part           = commandTrimmed.Split(new[] { ' ' }).ToList();

        if (part == null || part.Count == 0)
        {
            part.Add(commandTrimmed);
        }

        if (commandTrimmed.StartsWith("!") && TwitchPlaysAvailable && _isDebug)
        {
            Log($"Twitch Plays command send: {command}");
            HandleTwitchPlays(command);
        }
        else if (commandTrimmed == "exit")
        {
            Overlay.gameObject.SetActive(!Overlay.gameObject.activeSelf);
            InputField.text = string.Empty;
        }
        else if (commandTrimmed == "clear")
        {
            List <GameObject> children = new List <GameObject>();
            foreach (Transform child in Content.transform)
            {
                children.Add(child.gameObject);
            }

            children.ForEach(child => Destroy(child));
        }
        else if (commandTrimmed == "checkactive" && _isDebug)
        {
            Log(BombActive ? $"Bomb active: number {Bombs.Count}." : "Bomb not detected.");
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                Log($"Currently held Bomb: {(heldBombCommander != null ? $"ID: {heldBombCommander.Id}" : "None")}");
                Module focusedModule = GetFocusedModule();
                Log($"Currently focused Module: {(focusedModule != null ? $"Name: {focusedModule.ModuleName}" : "None")}");
                Log($"Infinite mode active: {Infinite}");
            }
        }
        else if (part[0] == "detonate")
        {
            if (BombActive)
            {
                BombCommander heldBombCommader = GetHeldBomb();
                string        reason           = "Detonate Command";
                if (part.Count > 1)
                {
                    reason = command.Substring(9);
                }
                if (heldBombCommader != null)
                {
                    Log($"Detonating{(part.Count > 1 ? $" with reason {command.Substring(9)}" : "")}");
                    Debug.Log("[Command Line] Detonating bomb.");
                    heldBombCommader.Detonate(reason);
                }
                else
                {
                    Log("Please hold the bomb you wish to detonate");
                }
            }
            else
            {
                Log("Bomb not active, cannot detonate");
            }
        }
        else if (part[0] == "causestrike")
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                string        reason            = "Strike Command";
                if (part.Count > 1)
                {
                    reason = command.Substring(12);
                }
                if (heldBombCommander != null)
                {
                    Log($"Causing strike{(part.Count > 1 ? $" with reason {command.Substring(12)}" : "")}");
                    Debug.Log("[Command Line] Causing strike.");
                    heldBombCommander.CauseStrike(reason);
                }
                else
                {
                    Log("Please hold the bomb you wish to cause a strike on");
                }
            }
            else
            {
                Log("Bomb not active, cannot cause a strike");
            }
        }
        else if (part[0].EqualsAny("time", "t") && part.Count > 1 && part[1].EqualsAny("add", "increase", "change", "subtract", "decrease", "remove", "set"))
        {
            if (BombActive)
            {
                bool          negative          = part[1].EqualsAny("subtract", "decrease", "remove");
                bool          direct            = part[1].EqualsAny("set");
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    float time         = 0;
                    float originalTime = heldBombCommander.TimerComponent.TimeRemaining;
                    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 split in part.Skip(2))
                    {
                        bool valid = false;
                        foreach (string unit in timeLengths.Keys)
                        {
                            if (!split.EndsWith(unit) || !float.TryParse(split.Substring(0, split.Length - unit.Length), out float length))
                            {
                                continue;
                            }
                            time += length * timeLengths[unit];
                            valid = true;
                            break;
                        }

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

                            if (direct)
                            {
                                heldBombCommander.TimerComponent.TimeRemaining = time;
                            }
                            else
                            {
                                heldBombCommander.TimerComponent.TimeRemaining = heldBombCommander.CurrentTimer + time;
                            }

                            if (originalTime < heldBombCommander.TimerComponent.TimeRemaining && !Leaderboardoff)
                            {
                                ChangeLeaderboard(true);
                                Debug.Log("[Command Line] Disabling leaderboard.");
                            }

                            if (direct)
                            {
                                Log($"Setting the timer to {Math.Abs(time < 0 ? 0 : time).FormatTime()}");
                                Debug.Log("[Command Line] Set bomb time.");
                            }
                            else
                            {
                                Log($"{(time > 0 ? "Added" : "Subtracted")} {Math.Abs(time).FormatTime()} {(time > 0 ? "to" : "from")} the timer");
                                Debug.Log("[Command Line] Changed bomb time.");
                            }
                            break;
                        }
                        else
                        {
                            Log("Time not valid");
                            break;
                        }
                    }
                }
                else
                {
                    Log("Please hold the bomb you wish to change the time on");
                }
            }
            else
            {
                Log("Bomb not active, cannot change time");
            }
        }
        else if (part[0].EqualsAny("strikes", "strike", "s") && part.Count > 1 && part[1].EqualsAny("add", "increase", "change", "subtract", "decrease", "remove", "set"))
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    bool negative = part[1].EqualsAny("subtract", "decrease", "remove");
                    bool direct   = part[1].EqualsAny("set");
                    if (int.TryParse(part[2], out int strikes) && (strikes != 0 || direct))
                    {
                        int originalStrikes = heldBombCommander.StrikeCount;
                        if (negative)
                        {
                            strikes = -strikes;
                        }

                        if (direct && strikes < 0)
                        {
                            strikes = 0;
                        }
                        else if (!direct && (heldBombCommander.StrikeCount + strikes) < 0)
                        {
                            strikes = -heldBombCommander.StrikeCount;
                        }

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

                        if (heldBombCommander.StrikeCount < originalStrikes && !Leaderboardoff)
                        {
                            ChangeLeaderboard(true);
                            Debug.Log("[Command Line] Disabling leaderboard.");
                        }

                        if (direct)
                        {
                            Log($"Setting the strike count to {Math.Abs(strikes)} {(Math.Abs(strikes) != 1 ? "strikes" : "strike")}");
                            Debug.Log("[Command Line] Set bomb strike count.");
                        }
                        else
                        {
                            Log($"{(strikes > 0 ? "Added" : "Subtracted")} {Math.Abs(strikes)} {(Math.Abs(strikes) != 1 ? "strikes" : "strike")} {(strikes > 0 ? "to" : "from")} the bomb");
                            Debug.Log("[Command Line] Changed bomb strike count.");
                        }
                    }
                }
                else
                {
                    Log("Please hold the bomb you wish to change the strikes on");
                }
            }
            else
            {
                Log("Bomb not active, cannot change strikes");
            }
        }
        else if (part[0].EqualsAny("ms", "maxstrikes", "sl", "strikelimit") && part.Count > 1 && part[1].EqualsAny("add", "increase", "change", "subtract", "decrease", "remove", "set"))
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    bool negative = part[1].EqualsAny("subtract", "decrease", "remove");
                    bool direct   = part[1].EqualsAny("set");
                    if (int.TryParse(part[2], out int maxStrikes) && (maxStrikes != 0 || direct))
                    {
                        int originalStrikeLimit = heldBombCommander.StrikeLimit;
                        if (negative)
                        {
                            maxStrikes = -maxStrikes;
                        }

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

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

                        if (originalStrikeLimit < heldBombCommander.StrikeLimit && !Leaderboardoff)
                        {
                            ChangeLeaderboard(true);
                            Debug.Log("[Command Line] Disabling leaderboard.");
                        }

                        if (direct)
                        {
                            Log($"Setting the strike limit to {Math.Abs(maxStrikes)} {(Math.Abs(maxStrikes) != 1 ? "strikes" : "strike")}");
                            Debug.Log("[Command Line] Set bomb strike limit.");
                        }
                        else
                        {
                            Log($"{(maxStrikes > 0 ? "Added" : "Subtracted")} {Math.Abs(maxStrikes)} {(Math.Abs(maxStrikes) > 1 ? "strikes" : "strike")} {(maxStrikes > 0 ? "to" : "from")} the strike limit");
                            Debug.Log("[Command Line] Changed bomb strike limit.");
                        }
                    }
                }
                else
                {
                    Log("Please hold the bomb you wish to change the strike limit on");
                }
            }
            else
            {
                Log("Bomb not active, cannot change strike limit");
            }
        }
        else if (commandTrimmed == "solve")
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    Module module = GetFocusedModule();
                    if (module != null)
                    {
                        if (!module.IsSolved)
                        {
                            switch (module.ComponentType)
                            {
                            case ComponentTypeEnum.NeedyCapacitor:
                            case ComponentTypeEnum.NeedyKnob:
                            case ComponentTypeEnum.NeedyMod:
                            case ComponentTypeEnum.NeedyVentGas:
                                Log("You cannot solve a needy module");
                                break;

                            case ComponentTypeEnum.Empty:
                                Log("You cannot solve an empty module slot!");
                                break;

                            case ComponentTypeEnum.Timer:
                                Log("You cannot solve the timer!");
                                break;

                            default:
                                SolveModule(module);
                                Log($"Solving module: {module.ModuleName}");
                                Debug.Log($"[Command Line] Solved module: {module.ModuleName}");
                                break;
                            }
                        }
                        else
                        {
                            Log("You cannot solve a module that's already been solved");
                        }
                    }
                    else
                    {
                        Log("Please focus on the module that you wish to solve");
                    }
                }
                else
                {
                    Log("Please hold the bomb that contains the module you wish to solve");
                }
            }
            else
            {
                Log("Bomb not active, cannot solve a module");
            }
        }
        else if (commandTrimmed == "solvebomb")
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    if (!Leaderboardoff)
                    {
                        ChangeLeaderboard(true);
                        Debug.Log("[Command Line] Disabling leaderboard.");
                    }
                    foreach (Module module in Modules.Where(x => x.BombId == heldBombCommander.Id && x.IsSolvable && x.ComponentType != ComponentTypeEnum.Empty && x.ComponentType != ComponentTypeEnum.Timer))
                    {
                        if (!module.IsSolved)
                        {
                            SolveModule(module);
                        }
                    }
                }
                else
                {
                    Log("Please hold the bomb that you wish to solve");
                }
            }
            else
            {
                Log("Bomb not active, cannot solve a bomb");
            }
        }
        else if (commandTrimmed == "pause")
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    if (heldBombCommander.TimerComponent.IsUpdating)
                    {
                        if (!Leaderboardoff)
                        {
                            ChangeLeaderboard(true);
                            Debug.Log("[Command Line] Disabling leaderboard.");
                        }
                        heldBombCommander.TimerComponent.StopTimer();
                        Debug.Log("[Command Line] Paused the bomb timer.");
                    }
                    else
                    {
                        Log("The held bomb is already paused");
                    }
                }
                else
                {
                    Log("Please hold the bomb that you wish to pause");
                }
            }
            else
            {
                Log("Bomb not active, cannot pause a bomb");
            }
        }
        else if (commandTrimmed == "unpause")
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    if (!heldBombCommander.TimerComponent.IsUpdating)
                    {
                        heldBombCommander.TimerComponent.StartTimer();
                        Debug.Log("[Command Line] Unpaused the bomb timer.");
                    }
                    else
                    {
                        Log("The held bomb is not paused");
                    }
                }
                else
                {
                    Log("Please hold the bomb you wish to pause");
                }
            }
            else
            {
                Log("Bomb not active, cannot unpause a bomb");
            }
        }
        else if (part[0].Trim().ToLowerInvariant().EqualsAny("turn", "rotate", "flip"))
        {
            if (BombActive)
            {
                BombCommander heldBombCommander = GetHeldBomb();
                if (heldBombCommander != null)
                {
                    StartCoroutine(heldBombCommander.TurnBombCoroutine());
                }
                else
                {
                    Log("Please hold the bomb you wish to turn");
                }
            }
            else
            {
                Log("Bomb not active, cannot turn bomb");
            }
        }
        else if (commandTrimmed == "help")
        {
            Log("Command reference:");
            Log("\"Detonate [reason]\" - detonate the currently held bomb, with an optional reason");
            Log("\"CauseStrike [reason]\" - cause a strike on the currently held bomb, with an optional reason");
            Log("\"Time (set|add|subtract) (time)(s|m|h)\" - changes the time on the currently held bomb (NOTE: this will disable leaderboards if you use it to achieve a faster time)");
            Log("\"Strikes (set|add|subtract) (number)\" - changes the strikes on the currently held bomb (NOTE: this will disable leaderboards if you use it to achieve a faster time)");
            Log("\"StrikeLimit (set|add|subtract) (number)\" - changes the strike limit on the currently held bomb (NOTE: this will disable leaderboards if you add a higher strike limit)");
            Log("\"Solve\" - solves the currently focused module (NOTE: this will disable leaderboards)");
            Log("\"SolveBomb\" - solves the currently held bomb (NOTE: this will disable leaderboards)");
            Log("\"Pause\" - pauses the timer on the currently held bomb (NOTE: this will disable leaderboards)");
            Log("\"Unpause\" - unpauses the timer on the currently held bomb");
            Log("\"Turn\" - turns the bomb to the opposite face");
            if (_isDebug)
            {
                Log("\"CheckActive\" - returns debugging info about the current bomb");
            }
        }
        else
        {
            Log("Command not valid");
        }
    }