private MessageResponder GetActiveResponder(KMGameInfo.State state) { switch (state) { case KMGameInfo.State.Gameplay: DefaultCamera(); return(bombMessageResponder); case KMGameInfo.State.Setup: DefaultCamera(); _coroutinesToStart.Enqueue(VanillaRuleModifier.Refresh()); _coroutinesToStart.Enqueue(MultipleBombs.Refresh()); _coroutinesToStart.Enqueue(FactoryRoomAPI.Refresh()); _coroutinesToStart.Enqueue(CreateSolversForAllBombComponents()); return(missionMessageResponder); case KMGameInfo.State.PostGame: DefaultCamera(); return(postGameMessageResponder); case KMGameInfo.State.Transitioning: ModuleData.LoadDataFromFile(); TwitchPlaySettings.LoadDataFromFile(); return(null); default: return(null); } }
public string ManualFor(string module, string type = "html", bool useVanillaRuleModifier = false) { if (useVanillaRuleModifier && VanillaRuleModifier.GetRuleSeed() != 1) { return($"{Repository}manual/{Escape(module)}.html?VanillaRuleSeed={VanillaRuleModifier.GetRuleSeed()}"); } return(string.Format(Repository + "{0}/{1}.{2}", type.ToUpper(), Escape(module), type)); }
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; } }
public ButtonComponentSolver(BombCommander bombCommander, ButtonComponent bombComponent) : base(bombCommander, bombComponent) { ModuleInformation buttonInfo = ComponentSolverFactory.GetModuleInfo("ButtonComponentSolver", "!{0} tap [tap the button] | !{0} hold [hold the button] | !{0} release 7 [release when the digit shows 7]"); ModuleInformation buttonInfoModified = ComponentSolverFactory.GetModuleInfo("ButtonComponentModifiedSolver", "Click the button with !{0} tap. Click the button at time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30."); bombComponent.GetComponent <Selectable>().OnCancel += bombComponent.OnButtonCancel; _button = bombComponent.button; modInfo = VanillaRuleModifier.IsSeedVanilla() ? buttonInfo : buttonInfoModified; }
public ButtonComponentSolver(TwitchModule module) : base(module) { ModuleInformation buttonInfo = ComponentSolverFactory.GetModuleInfo("ButtonComponentSolver", "!{0} tap [tap the button] | !{0} hold [hold the button] | !{0} release 7 [release when the digit shows 7]"); ModuleInformation buttonInfoModified = ComponentSolverFactory.GetModuleInfo("ButtonComponentModifiedSolver", "Click the button with !{0} tap. Click the button at a time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30."); var buttonModule = (ButtonComponent)module.BombComponent; buttonModule.GetComponent <Selectable>().OnCancel += buttonModule.OnButtonCancel; _button = buttonModule.button; ModInfo = VanillaRuleModifier.IsSeedVanilla() ? buttonInfo : buttonInfoModified; }
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; } }
public ButtonComponentSolver(BombCommander bombCommander, ButtonComponent bombComponent, IRCConnection ircConnection, CoroutineCanceller canceller) : base(bombCommander, bombComponent, ircConnection, canceller) { ModuleInformation buttonInfo = ComponentSolverFactory.GetModuleInfo("ButtonComponentSolver"); ModuleInformation squarebuttonInfo = ComponentSolverFactory.GetModuleInfo("ButtonV2"); bombComponent.GetComponent <Selectable>().OnCancel += bombComponent.OnButtonCancel; _button = bombComponent.button; modInfo = new ModuleInformation { builtIntoTwitchPlays = buttonInfo.builtIntoTwitchPlays, CameraPinningAlwaysAllowed = buttonInfo.CameraPinningAlwaysAllowed, helpText = VanillaRuleModifier.IsSeedVanilla() ? buttonInfo.helpText : squarebuttonInfo.helpText, manualCode = buttonInfo.manualCode, moduleDisplayName = buttonInfo.moduleDisplayName, moduleID = buttonInfo.moduleID, moduleScore = VanillaRuleModifier.IsSeedVanilla() ? buttonInfo.moduleScore : squarebuttonInfo.moduleScore }; }
private MessageResponder GetActiveResponder(KMGameInfo.State state) { switch (state) { case KMGameInfo.State.Gameplay: return(bombMessageResponder); case KMGameInfo.State.Setup: StartCoroutine(VanillaRuleModifier.Refresh()); StartCoroutine(MultipleBombs.Refresh()); return(missionMessageResponder); case KMGameInfo.State.PostGame: return(postGameMessageResponder); case KMGameInfo.State.Transitioning: ModuleData.LoadDataFromFile(); TwitchPlaySettings.LoadDataFromFile(); return(null); default: return(null); } }
public static void Help(TwitchModule module, [Group(1)] bool pdf) { string manualType = pdf ? "pdf" : "html"; string manualText = (Repository.GetManual(module.BombComponent.GetModuleID()) ?? module.BombComponent.GetModuleDisplayName()) + TranslatedModuleHelper.GetManualCodeAddOn(module.Solver.LanguageCode); string helpText = string.IsNullOrEmpty(module.Solver.HelpMessage) ? string.Empty : string.Format(module.Solver.HelpMessage, module.Code, module.HeaderText); IRCConnection.SendMessage($"{module.HeaderText} : {helpText} : {UrlHelper.ManualFor(manualText, manualType, VanillaRuleModifier.GetModuleRuleSeed(module.Solver.ModInfo.moduleID) != 1)}"); }
protected internal override IEnumerator RespondToCommandInternal(string inputCommand) { bool isModdedSeed = VanillaRuleModifier.IsSeedModded(); inputCommand = inputCommand.ToLowerInvariant().Trim(); if (!_held && inputCommand.EqualsAny("tap", "click")) { yield return("tap"); yield return(DoInteractionClick(_button)); } if (!_held && (inputCommand.StartsWith("tap ") || inputCommand.StartsWith("click "))) { if (!isModdedSeed) { yield break; } yield return("tap2"); IEnumerator releaseCoroutine = ReleaseCoroutineModded(inputCommand.Substring(inputCommand.IndexOf(' '))); while (releaseCoroutine.MoveNext()) { yield return(releaseCoroutine.Current); } } else if (!_held && inputCommand.Equals("hold")) { yield return("hold"); _held = true; DoInteractionStart(_button); yield return(new WaitForSeconds(2.0f)); } else if (_held) { string[] commandParts = inputCommand.Split(' '); if (commandParts.Length != 2 || !commandParts[0].Equals("release")) { yield break; } IEnumerator releaseCoroutine; if (!isModdedSeed) { if (!int.TryParse(commandParts[1], out int second)) { yield break; } if (second >= 0 && second <= 9) { releaseCoroutine = ReleaseCoroutineVanilla(second); } else { yield break; } } else { releaseCoroutine = ReleaseCoroutineModded(inputCommand.Substring(inputCommand.IndexOf(' '))); } while (releaseCoroutine.MoveNext()) { yield return(releaseCoroutine.Current); } } }
public static void Help(TwitchModule module, [Group(1)] bool pdf) { string manualType = pdf ? "pdf" : "html"; string manualText = string.IsNullOrEmpty(module.Solver.ManualCode) ? module.HeaderText : module.Solver.ManualCode; string helpText = string.IsNullOrEmpty(module.Solver.HelpMessage) ? string.Empty : string.Format(module.Solver.HelpMessage, module.Code, module.HeaderText); IRCConnection.SendMessage(Regex.IsMatch(manualText, @"^https?://", RegexOptions.IgnoreCase) ? $"{module.HeaderText} : {helpText} : {manualText}" : $"{module.HeaderText} : {helpText} : {UrlHelper.Instance.ManualFor(manualText, manualType, VanillaRuleModifier.GetModuleRuleSeed(module.Solver.ModInfo.moduleID) != 1)}"); }
public static string ManualFor(string module, string type = "html", bool useVanillaRuleModifier = false) => string.Format(TwitchPlaySettings.data.RepositoryUrl + "{0}/{1}.{2}{3}", type.ToUpper(), NameToUrl(module), type, (useVanillaRuleModifier && type.Equals("html")) ? $"#{VanillaRuleModifier.GetRuleSeed()}" : "");
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; } }
private IEnumerator ReleaseCoroutineModded(string second) { bool longwait = false; string[] list = second.Split(' '); List <int> sortedTimes = new List <int>(); foreach (string value in list) { if (!int.TryParse(value, out int time)) { int pos = value.LastIndexOf(':'); if (pos == -1) { continue; } int hour = 0; if (!int.TryParse(value.Substring(0, pos), out int min)) { int pos2 = value.IndexOf(":"); if ((pos2 == -1) || (pos == pos2)) { continue; } if (!int.TryParse(value.Substring(0, pos2), out hour)) { continue; } if (!int.TryParse(value.Substring(pos2 + 1, pos - pos2 - 1), out min)) { continue; } } if (!int.TryParse(value.Substring(pos + 1), out int sec)) { continue; } time = (hour * 3600) + (min * 60) + sec; } sortedTimes.Add(time); } sortedTimes.Sort(); sortedTimes.Reverse(); if (sortedTimes.Count == 0) { yield break; } yield return("release"); TimerComponent timerComponent = BombCommander.Bomb.GetTimer(); int timeTarget = sortedTimes[0]; sortedTimes.RemoveAt(0); int waitTime = (int)(timerComponent.TimeRemaining + 0.25f); waitTime -= timeTarget; if (waitTime >= 30) { yield return("elevator music"); if (waitTime >= 120) { yield return(string.Format("sendtochat !!!WARNING!!! - you might want to do a !cancel right about now, as you will be waiting for {0} minutes and {1} seconds for button release. Seed #{2} applies to this button.", waitTime / 60, waitTime % 60, VanillaRuleModifier.GetRuleSeed())); yield return(string.Format("sendtochat Click the button with !{0} tap. Click the button at time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30.", Code)); longwait = true; } } float timeRemaining = float.PositiveInfinity; while (timeRemaining > 0.0f) { if (Canceller.ShouldCancel) { Canceller.ResetCancel(); if (timeTarget < 10) { yield return(string.Format("sendtochat The button was not {0} due to a request to cancel. Remember that the rule set that applies is seed #{1}", _held ? "released" : "tapped", VanillaRuleModifier.GetRuleSeed())); } else { yield return(string.Format("sendtochat The button was not {0} due to a request to cancel.", _held ? "released" : "tapped")); } yield break; } timeRemaining = (int)(timerComponent.TimeRemaining + 0.25f); if (timeRemaining < timeTarget) { if (sortedTimes.Count == 0) { yield return(string.Format("sendtochaterror The button was not {0} because all of your specfied times are greater than the time remaining.", _held ? "released" : "tapped")); yield break; } timeTarget = sortedTimes[0]; sortedTimes.RemoveAt(0); waitTime = (int)timeRemaining; waitTime -= timeTarget; if (waitTime >= 30) { yield return("elevator music"); if (waitTime >= 120 && !longwait) { yield return(string.Format("sendtochat !!!WARNING!!! - you might want to do a !cancel right about now, as you will be waiting for {0} minutes and {1} seconds for button release. Seed #{2} applies to this button.", waitTime / 60, waitTime % 60, VanillaRuleModifier.GetRuleSeed())); yield return(string.Format("sendtochat Click the button with !{0} tap. Click the button at time with !{0} tap 8:55 8:44 8:33. Hold the button with !{0} hold. Release the button with !{0} release 9:58 9:49 9:30.", Code)); } longwait = true; } continue; } if (Math.Abs(timeRemaining - timeTarget) < 0.1f) { if (!_held) { DoInteractionStart(_button); yield return(new WaitForSeconds(0.1f)); } DoInteractionEnd(_button); _held = false; yield break; } yield return(null); } }