diff --git a/Components/LiveSplit.HollowKnight.Updates.xml b/Components/LiveSplit.HollowKnight.Updates.xml index 5c06af6..0a23552 100644 --- a/Components/LiveSplit.HollowKnight.Updates.xml +++ b/Components/LiveSplit.HollowKnight.Updates.xml @@ -1,5 +1,32 @@  + + + + + + Major autosplitter update: + Splits saved in this version of the autosplitter will not be compatible with previous versions. It is strongly recommended to backup your saves before saving them in this version + All splits are now ordered, and have start-triggering and end-triggering autosplits which are integrated into the regular splits list + Splits for previously implicit start and end conditions now exist, and have automatically been added to your splits where applicable. + It is preferred for you to edit your splits to use start/end point splits specific for the category you are running. + + New and updated splits: + Added starting splits for start new game, start pantheon (Mayo) + Added Individual splits for all endings (Mayo) + Added Absolute Radiance Ending split for Pantheon of Hallownest (AlexKnauth) + Added Menu splits for Mothwing Cloak, Dashmaster, Dream Nail, Dream Gate, Void Heart and 3 Dreamers (Mayo) + Added Soul Sanctum Hallownest Seal split (Mayo) + Added Stag Position Updated split (Mayo) + Added City Toll Bench Room Transition split (Mayo) + Added Transition excluding discontinuities split (AlexKnauth) + Fixed Credits Roll Ending split to not split on finishing any of Pantheon 1-4 (AlexKnauth) + Fixed Main Menu splits to be more reliable (Mayo) + Fixed Has Shade Soul Transition split to be room-dupe-safe (Python) + Fixed Enter Troupe Master Grimm Transition split to require Grimmchild equipped (AlexKnauth) + Fixed Pure Snail split to allow a full focus at full health (AlexKnauth) + + @@ -61,7 +88,7 @@ New transition autosplits: `Has Shade Soul`, `Grimm Flame 1-3`, `Beast Den` New menu autosplit: `Main Menu w/ Shade Soul` - New fun split: `Stinky`> + New fun split: `Stinky` diff --git a/Components/LiveSplit.HollowKnight.dll b/Components/LiveSplit.HollowKnight.dll index c4b3170..bcf80b5 100644 Binary files a/Components/LiveSplit.HollowKnight.dll and b/Components/LiveSplit.HollowKnight.dll differ diff --git a/HollowKnightComponent.cs b/HollowKnightComponent.cs index b13d644..1582ba2 100644 --- a/HollowKnightComponent.cs +++ b/HollowKnightComponent.cs @@ -37,13 +37,10 @@ public class HollowKnightComponent { "LookFor" }; private HollowKnightMemory mem; - private int currentSplit = -1, state = 0, lastLogCheck = 0; + private int currentSplitIndex = 0, state = 0, lastLogCheck = 0; private bool hasLog = false; private Dictionary currentValues = new Dictionary(); private HollowKnightSettings settings; - private HashSet splitsDone = new HashSet(); - private List failedValues = new List(); - private SplitName lastSplitDone; private static string LOGFILE = "_HollowKnight.log"; private PlayerData pdata = new PlayerData(); private GameState lastGameState; @@ -129,76 +126,77 @@ public void GetValues() { } #if !Info private void HandleSplits() { - SplitterAction action = SplitterAction.Pass; - string nextScene = mem.NextSceneName(); - string sceneName = mem.SceneName(); - - if (currentSplit == -1) { - if (settings.AutosplitStartRuns != null) { - action = CheckSplit(settings.AutosplitStartRuns.Value, nextScene, sceneName); - } else { - action = ((nextScene.Equals("Tutorial_01", StringComparison.OrdinalIgnoreCase) && - mem.GameState() == GameState.ENTERING_LEVEL) || - nextScene is "GG_Vengefly_V" or "GG_Boss_Door_Entrance" or "GG_Entrance_Cutscene") ? SplitterAction.Split : SplitterAction.Pass; - } - } else if (Model.CurrentState.CurrentPhase == TimerPhase.Running && settings.Splits.Count > 0) { - GameState gameState = mem.GameState(); - UIState uIState = mem.UIState(); - //SplitName finalSplit = settings.Splits[settings.Splits.Count - 1]; - - if (!settings.AutosplitEndRuns) { - if (currentSplit + 1 < Model.CurrentState.Run.Count) { - if (!settings.Ordered) { - action = NotOrderedSplits(gameState, uIState, nextScene, sceneName); - - } else if (currentSplit < settings.Splits.Count) { - action = OrderedSplits(gameState, uIState, nextScene, sceneName); - } - } else { - action = (nextScene.StartsWith("Cinematic_Ending", StringComparison.OrdinalIgnoreCase) || nextScene == "GG_End_Sequence") ? SplitterAction.Split : SplitterAction.Pass; - } - } else { - if (currentSplit < Model.CurrentState.Run.Count) { - if (currentSplit + 1 == Model.CurrentState.Run.Count) { - action = (nextScene.StartsWith("Cinematic_Ending", StringComparison.OrdinalIgnoreCase) || nextScene == "GG_End_Sequence") ? SplitterAction.Split : SplitterAction.Pass; - } - if (action == SplitterAction.Pass) { - if (!settings.Ordered) { - action = NotOrderedSplits(gameState, uIState, nextScene, sceneName); // unordered splits not compatible with Skip splits - } else if (currentSplit < settings.Splits.Count) { - action = OrderedSplits(gameState, uIState, nextScene, sceneName); - } - } - } - } - LoadRemoval(gameState, uIState, nextScene, sceneName); + + var action = SplitterAction.Pass; + string sceneNext = mem.NextSceneName(); + string sceneCurr = mem.SceneName(); + GameState gameState = mem.GameState(); + UIState uiState = mem.UIState(); + + var _GetCurrentSplit = () => { + SplitName s; + try { s = settings.Splits[currentSplitIndex]; } // gets the current split + catch { s = SplitName.ForgottenCrossroads; } // default split + return s; + }; + + var split = _GetCurrentSplit(); + + if ( + settings.Splits.Count > 0 // there are splits + && (Model.CurrentState.CurrentPhase == TimerPhase.Running // timer is running + || currentSplitIndex == 0) // current split is the start + ) { + action = GetAction(split, sceneNext, sceneCurr); // check for split + } + + // log if the split is not a pass and the game is not inactive or in the main menu + if ( + action != SplitterAction.Pass + && !((gameState == GameState.INACTIVE && uiState == UIState.INACTIVE) || gameState == GameState.MAIN_MENU) + && (hasLog || !Console.IsOutputRedirected) + ) { + WriteLogWithTime($"{action.ToString()}: " + split); } store.Update(); - HandleSplit(action); + + LoadRemoval(gameState, uiState, sceneNext, sceneCurr); + + DoAction(action); + + return; } private void LoadRemoval(GameState gameState, UIState uIState, string nextScene, string sceneName) { + + // only remove loads if timer is running + if (Model.CurrentState.CurrentPhase != TimerPhase.Running) return; + uIState = mem.UIState(); + bool loadingMenu = (sceneName != "Menu_Title" && string.IsNullOrEmpty(nextScene)) || (sceneName != "Menu_Title" && nextScene == "Menu_Title" - || (sceneName == "Quit_To_Menu")); + || (sceneName == "Quit_To_Menu") + ); + + bool teleporting = mem.CameraTeleporting(); + if (gameState == GameState.PLAYING && lastGameState == GameState.MAIN_MENU) { lookForTeleporting = true; } - bool teleporting = mem.CameraTeleporting(); if (lookForTeleporting && (teleporting || (gameState != GameState.PLAYING && gameState != GameState.ENTERING_LEVEL))) { lookForTeleporting = false; } - // TODO: look into Current Patch quitout issues. + // TODO: look into Current Patch quitout issues. // might have been fixed? cerpin you broke them in a way that made them work, right? Model.CurrentState.IsGameTimePaused = (gameState == GameState.PLAYING && teleporting && !mem.HazardRespawning()) - || lookForTeleporting + || (lookForTeleporting) || ((gameState is GameState.PLAYING or GameState.ENTERING_LEVEL) && uIState != UIState.PLAYING) || (gameState != GameState.PLAYING && !mem.AcceptingInput()) - || gameState is GameState.EXITING_LEVEL or GameState.LOADING - || mem.HeroTransitionState() == HeroTransitionState.WAITING_TO_ENTER_LEVEL + || (gameState is GameState.EXITING_LEVEL or GameState.LOADING) + || (mem.HeroTransitionState() == HeroTransitionState.WAITING_TO_ENTER_LEVEL) || (uIState != UIState.PLAYING && (loadingMenu || (uIState != UIState.PAUSED && (!string.IsNullOrEmpty(nextScene) || sceneName == "_test_charms"))) && nextScene != sceneName) @@ -209,93 +207,17 @@ private void LoadRemoval(GameState gameState, UIState uIState, string nextScene, || (mem.MenuState() == MainMenuState.LOGO && mem.GameState() == GameState.INACTIVE && uIState == UIState.INACTIVE) */ ; - lastGameState = gameState; - } - private SplitterAction NotOrderedSplits(GameState gameState, UIState uIState, string nextScene, string sceneName) { - - foreach (SplitName Split in settings.Splits) { - if (splitsDone.Contains(Split)) { - continue; - } else if (Split.ToString().StartsWith("Menu")) { - if (!menuSplitHelper) - menuSplitHelper = Split == SplitName.Menu || - CheckSplit(Split, nextScene, sceneName) == SplitterAction.Split && !((gameState == GameState.INACTIVE && uIState == UIState.INACTIVE) || (gameState == GameState.MAIN_MENU)); - if (menuSplitHelper) { - if (CheckSplit(SplitName.Menu, nextScene, sceneName) == SplitterAction.Split) { - splitsDone.Add(Split); - lastSplitDone = Split; - menuSplitHelper = false; - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Split: " + Split); - return SplitterAction.Split; - } - } - } else if (!((gameState == GameState.INACTIVE && uIState == UIState.INACTIVE) || (gameState == GameState.MAIN_MENU))) { - if (CheckSplit(Split, nextScene, sceneName) == SplitterAction.Split) { - splitsDone.Add(Split); - lastSplitDone = Split; - menuSplitHelper = false; - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Split: " + Split); - return SplitterAction.Split; - } - } - } - return SplitterAction.Pass; - } - - private SplitterAction OrderedSplits(GameState gameState, UIState uIState, string nextScene, string sceneName) { - SplitName Split = settings.Splits[currentSplit]; - - if (Split.ToString().StartsWith("Menu")) { - if (!menuSplitHelper) menuSplitHelper = Split == SplitName.Menu || CheckSplit(Split, nextScene, sceneName) != SplitterAction.Pass; - if (menuSplitHelper) { - if (CheckSplit(SplitName.Menu, nextScene, sceneName) == SplitterAction.Split) { - menuSplitHelper = false; - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Split: " + Split); - return SplitterAction.Split; - } else if (CheckSplit(SplitName.Menu, nextScene, sceneName) == SplitterAction.Skip) { - menuSplitHelper = false; - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Skip: " + Split); - return SplitterAction.Skip; - } - } - } else { - if (CheckSplit(Split, nextScene, sceneName) == SplitterAction.Split - && !((gameState == GameState.INACTIVE && uIState == UIState.INACTIVE) || (gameState == GameState.MAIN_MENU))) { - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Split: " + Split); - return SplitterAction.Split; - } else if (CheckSplit(Split, nextScene, sceneName) == SplitterAction.Skip - && !((gameState == GameState.INACTIVE && uIState == UIState.INACTIVE) || (gameState == GameState.MAIN_MENU))) { - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Skip: " + Split); - return SplitterAction.Skip; - } else if (CheckSplit(Split, nextScene, sceneName) == SplitterAction.Reset - && !((gameState == GameState.INACTIVE && uIState == UIState.INACTIVE) || (gameState == GameState.MAIN_MENU))) { - if (hasLog || !Console.IsOutputRedirected) WriteLogWithTime("Reset: " + Split); - return SplitterAction.Reset; - } - } - return SplitterAction.Pass; - } + lastGameState = gameState; - private bool shouldSplitTransition(string nextScene, string sceneName) { - if (nextScene != sceneName && !store.SplitThisTransition) { - return !( - string.IsNullOrEmpty(sceneName) || - string.IsNullOrEmpty(nextScene) || - menuingSceneNames.Contains(sceneName) || - menuingSceneNames.Contains(nextScene) - ); - } - return false; } - private SplitterAction CheckSplit(SplitName split, string nextScene, string sceneName) { - string currScene = sceneName; + private SplitterAction GetAction(SplitName split, string nextScene, string currScene) { bool shouldSplit = false; bool shouldSkip = false; bool shouldReset = false; - SplitterAction action; + SplitterAction action = SplitterAction.Pass; switch (split) { @@ -1322,59 +1244,83 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen #endregion Benches - case SplitName.ColosseumBronze: shouldSplit = mem.PlayerData(Offset.colosseumBronzeCompleted); break; - case SplitName.ColosseumGold: shouldSplit = mem.PlayerData(Offset.colosseumGoldCompleted); break; - case SplitName.ColosseumSilver: shouldSplit = mem.PlayerData(Offset.colosseumSilverCompleted); break; - case SplitName.MaskFragment1: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 1; break; - case SplitName.MaskFragment2: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 2; break; - case SplitName.MaskFragment3: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 3; break; - case SplitName.Mask1: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 6; break; - case SplitName.MaskFragment5: shouldSplit = mem.PlayerData(Offset.heartPieces) == 5 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 1); break; - case SplitName.MaskFragment6: shouldSplit = mem.PlayerData(Offset.heartPieces) == 6 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 2); break; - case SplitName.MaskFragment7: shouldSplit = mem.PlayerData(Offset.heartPieces) == 7 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 3); break; - case SplitName.Mask2: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 7; break; - case SplitName.MaskFragment9: shouldSplit = mem.PlayerData(Offset.heartPieces) == 9 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 1); break; - case SplitName.MaskFragment10: shouldSplit = mem.PlayerData(Offset.heartPieces) == 10 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 2); break; - case SplitName.MaskFragment11: shouldSplit = mem.PlayerData(Offset.heartPieces) == 11 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 3); break; - case SplitName.Mask3: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 8; break; - case SplitName.MaskFragment13: shouldSplit = mem.PlayerData(Offset.heartPieces) == 13 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 1); break; - case SplitName.MaskFragment14: shouldSplit = mem.PlayerData(Offset.heartPieces) == 14 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 2); break; - case SplitName.MaskFragment15: shouldSplit = mem.PlayerData(Offset.heartPieces) == 15 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 3); break; - case SplitName.Mask4: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 9; break; - case SplitName.VesselFragment1: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 0 && mem.PlayerData(Offset.vesselFragments) == 1; break; - case SplitName.VesselFragment2: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 0 && mem.PlayerData(Offset.vesselFragments) == 2; break; - case SplitName.Vessel1: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 33; break; - case SplitName.VesselFragment4: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 4 || (mem.PlayerData(Offset.MPReserveMax) == 33 && mem.PlayerData(Offset.vesselFragments) == 1); break; - case SplitName.VesselFragment5: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 5 || (mem.PlayerData(Offset.MPReserveMax) == 33 && mem.PlayerData(Offset.vesselFragments) == 2); break; - case SplitName.Vessel2: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 66; break; - case SplitName.VesselFragment7: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 7 || (mem.PlayerData(Offset.MPReserveMax) == 66 && mem.PlayerData(Offset.vesselFragments) == 1); break; - case SplitName.VesselFragment8: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 8 || (mem.PlayerData(Offset.MPReserveMax) == 66 && mem.PlayerData(Offset.vesselFragments) == 2); break; - case SplitName.Vessel3: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 99; break; + #region Main Menu + + // this case is used for all main menu splits, be careful if you modify it + case SplitName.Menu: + shouldSplit = (currScene == "Menu_Title") && (nextScene != currScene); + menuSplitHelper = !shouldSplit && mem.UIState() != UIState.PLAYING; + break; + + // menuSplitHelper is set to true in case SplitName.Menu, and is only set back to false once it splits + // playerdata doesn't exist when you quit out or something so it can't check any additional conditions + // menuSplitHelper basically just remembers that you've met the conditions and lets you pass on to the + // SplitName.Menu case. + + case SplitName.MenuCloak: if (menuSplitHelper || mem.PlayerData(Offset.hasDash)) { goto case SplitName.Menu; } break; + case SplitName.MenuClaw: if (menuSplitHelper || mem.PlayerData(Offset.hasWallJump)) { goto case SplitName.Menu; } break; + case SplitName.MenuDashmaster: if (menuSplitHelper || mem.PlayerData(Offset.gotCharm_31)) { goto case SplitName.Menu; } break; + case SplitName.MenuGorgeousHusk: if (menuSplitHelper || mem.PlayerData(Offset.killedGorgeousHusk)) { goto case SplitName.Menu; } break; + case SplitName.MenuDreamNail: if (menuSplitHelper || mem.PlayerData(Offset.hasDreamNail)) { goto case SplitName.Menu; } break; + case SplitName.MenuDreamGate: if (menuSplitHelper || mem.PlayerData(Offset.hasDreamGate)) { goto case SplitName.Menu; } break; + case SplitName.MenuDreamer3: if (menuSplitHelper || mem.PlayerData(Offset.guardiansDefeated) == 3) { goto case SplitName.Menu; } break; + case SplitName.MenuVoidHeart: if (menuSplitHelper || mem.PlayerData(Offset.gotShadeCharm)) { goto case SplitName.Menu; } break; + case SplitName.MenuIsmasTear: if (menuSplitHelper || mem.PlayerData(Offset.hasAcidArmour)) { goto case SplitName.Menu; }; break; + case SplitName.MenuShadeSoul: if (menuSplitHelper || mem.PlayerData(Offset.fireballLevel) == 2) { goto case SplitName.Menu; }; break; /* - case SplitName.NailsmithSpared: shouldSplit = mem.PlayerData(Offset.nailsmithSpared); break; - case SplitName.MageDoor: shouldSplit = mem.PlayerData(Offset.openedMageDoor); break; - case SplitName.MageWindow: shouldSplit = mem.PlayerData(Offset.brokenMageWindow); break; - case SplitName.MageLordEncountered: shouldSplit = mem.PlayerData(Offset.mageLordEncountered); break; - case SplitName.MageDoor2: shouldSplit = mem.PlayerData(Offset.openedMageDoor_v2); break; - case SplitName.MageWindowGlass: shouldSplit = mem.PlayerData(Offset.brokenMageWindowGlass); break; - case SplitName.MageLordEncountered2: shouldSplit = mem.PlayerData(Offset.mageLordEncountered_2); break; - */ - //case SplitName.NotchSly1: shouldSplit = mem.PlayerData(Offset.slyNotch1); break; - //case SplitName.NotchSly2: shouldSplit = mem.PlayerData(Offset.slyNotch2); break; + case SplitName.MenuCloak: + if (mem.PlayerData(Offset.hasDash)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; + + case SplitName.MenuClaw: + if (mem.PlayerData(Offset.hasWallJump)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; - //case SplitName.Al2ba: shouldSplit = mem.PlayerData(Offset.killsLazyFlyer) == 2; break; - //case SplitName.Revek: shouldSplit = mem.PlayerData(Offset.gladeGhostsKilled) == 19; break; - //case SplitName.EquippedFragileHealth: shouldSplit = mem.PlayerData(Offset.equippedCharm_23); break; + case SplitName.MenuDashmaster: + if (mem.PlayerData(Offset.gotCharm_31)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; + + case SplitName.MenuGorgeousHusk: + if (mem.PlayerData(Offset.killedGorgeousHusk)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; + + case SplitName.MenuDreamNail: + if (mem.PlayerData(Offset.hasDreamNail)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; - //case SplitName.AreaTestingSanctum: shouldSplit = mem.PlayerData(Offset.currentArea) == (int)MapZone.SOUL_SOCIETY; break; - //case SplitName.AreaTestingSanctumUpper: shouldSplit = mem.PlayerData(Offset.currentArea) == (int)MapZone.MAGE_TOWER; break; + case SplitName.MenuDreamGate: + if (mem.PlayerData(Offset.hasDreamGate)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; + + case SplitName.MenuDreamer3: + if (mem.PlayerData(Offset.guardiansDefeated) == 3) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; - case SplitName.Menu: shouldSplit = sceneName == "Menu_Title"; break; - case SplitName.MenuClaw: shouldSplit = mem.PlayerData(Offset.hasWallJump); break; - case SplitName.MenuGorgeousHusk: shouldSplit = mem.PlayerData(Offset.killedGorgeousHusk); break; - case SplitName.MenuIsmasTear: shouldSplit = mem.PlayerData(Offset.hasAcidArmour); break; - case SplitName.MenuShadeSoul: shouldSplit = mem.PlayerData(Offset.fireballLevel) == 2; break; + case SplitName.MenuVoidHeart: + if (mem.PlayerData(Offset.gotShadeCharm)) menuSplitHelper = true; + if (menuSplitHelper) goto case SplitName.Menu; + shouldSplit = false; + break; + */ + + #endregion Main Menu + + #region Maps case SplitName.mapDirtmouth: shouldSplit = mem.PlayerData(Offset.mapDirtmouth); break; case SplitName.mapCrossroads: shouldSplit = mem.PlayerData(Offset.mapCrossroads); break; @@ -1391,72 +1337,129 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen case SplitName.mapRestingGrounds: shouldSplit = mem.PlayerData(Offset.mapRestingGrounds); break; case SplitName.mapAbyss: shouldSplit = mem.PlayerData(Offset.mapAbyss); break; + #endregion Maps + + #region Overworld Ghosts + case SplitName.OnObtainGhostMarissa: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Ruins_Bathhouse"; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Ruins_Bathhouse"; break; case SplitName.OnObtainGhostCaelifFera: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Fungus1_24"; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Fungus1_24"; break; case SplitName.OnObtainGhostPoggy: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Ruins_Elevator"; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Ruins_Elevator"; break; case SplitName.OnObtainGhostGravedigger: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Town"; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Town"; break; case SplitName.OnObtainGhostJoni: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Cliffs_05"; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Cliffs_05"; break; case SplitName.OnObtainGhostCloth: - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Fungus3_23" && store.TraitorLordDeadOnEntry; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Fungus3_23" && store.TraitorLordDeadOnEntry; break; case SplitName.OnObtainGhostVespa: // UsesSceneTransitionRoutine is true on patches where Hive Knight exists bool hiveKnightBeenDead = !mem.UsesSceneTransitionRoutine() || store.CheckBeenTrue(Offset.killedHiveKnight); - shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && sceneName == "Hive_05" && hiveKnightBeenDead; + shouldSplit = store.CheckIncremented(Offset.dreamOrbs) && currScene == "Hive_05" && hiveKnightBeenDead; break; case SplitName.OnObtainGhostRevek: - if (sceneName == "RestingGrounds_08") { + if (currScene == "RestingGrounds_08") { shouldSplit = store.GladeEssence == 19 || store.GladeEssence == 18 && store.CheckIncremented(Offset.dreamOrbs); } break; - case SplitName.MaskShardMawlek: if (sceneName == "Crossroads_09") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardGrubfather: if (sceneName == "Crossroads_38") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardBretta: if (sceneName == "Room_Bretta") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardQueensStation: if (sceneName == "Fungus2_01") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardEnragedGuardian: if (sceneName == "Mines_32") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardSeer: if (sceneName == "RestingGrounds_07") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardGoam: if (sceneName == "Crossroads_13") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardStoneSanctuary: if (sceneName == "Fungus1_36") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardWaterways: if (sceneName == "Waterways_04b") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardFungalCore: if (sceneName == "Fungus2_25") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardHive: if (sceneName == "Hive_04") { goto case SplitName.OnObtainMaskShard; } break; - case SplitName.MaskShardFlower: if (sceneName == "Room_Mansion") { goto case SplitName.OnObtainMaskShard; } break; - - case SplitName.VesselFragGreenpath: if (sceneName == "Fungus1_13") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragCrossroadsLift: if (sceneName == "Crossroads_37") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragKingsStation: if (sceneName == "Ruins2_09") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragGarpedes: if (sceneName == "Deepnest_38") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragStagNest: if (sceneName == "Cliffs_03") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragSeer: if (sceneName == "RestingGrounds_07") { goto case SplitName.OnObtainVesselFragment; } break; - case SplitName.VesselFragFountain: if (sceneName == "Abyss_04") { goto case SplitName.OnObtainVesselFragment; } break; + #endregion Overworld Ghosts + + #region Mask Shards case SplitName.OnObtainMaskShard: - shouldSplit = store.CheckIncremented(Offset.maxHealthBase) || (store.CheckIncremented(Offset.heartPieces) && mem.PlayerData(Offset.heartPieces) < 4); - break; + shouldSplit = + store.CheckIncremented(Offset.maxHealthBase) // && mem.UIState() != UIState.PLAYING + || store.CheckIncremented(Offset.heartPieces) && mem.PlayerData(Offset.heartPieces) < 4; + break; + + case SplitName.MaskShardMawlek: if (currScene == "Crossroads_09") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardGrubfather: if (currScene == "Crossroads_38") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardBretta: if (currScene == "Room_Bretta") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardQueensStation: if (currScene == "Fungus2_01") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardEnragedGuardian: if (currScene == "Mines_32") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardSeer: if (currScene == "RestingGrounds_07") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardGoam: if (currScene == "Crossroads_13") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardStoneSanctuary: if (currScene == "Fungus1_36") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardWaterways: if (currScene == "Waterways_04b") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardFungalCore: if (currScene == "Fungus2_25") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardHive: if (currScene == "Hive_04") { goto case SplitName.OnObtainMaskShard; } break; + case SplitName.MaskShardFlower: if (currScene == "Room_Mansion") { goto case SplitName.OnObtainMaskShard; } break; + + case SplitName.MaskFragment1: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 1; break; + case SplitName.MaskFragment2: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 2; break; + case SplitName.MaskFragment3: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 5 && mem.PlayerData(Offset.heartPieces) == 3; break; + case SplitName.Mask1: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 6; break; + + case SplitName.MaskFragment5: shouldSplit = mem.PlayerData(Offset.heartPieces) == 5 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 1); break; + case SplitName.MaskFragment6: shouldSplit = mem.PlayerData(Offset.heartPieces) == 6 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 2); break; + case SplitName.MaskFragment7: shouldSplit = mem.PlayerData(Offset.heartPieces) == 7 || (mem.PlayerData(Offset.maxHealthBase) == 6 && mem.PlayerData(Offset.heartPieces) == 3); break; + case SplitName.Mask2: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 7; break; + + case SplitName.MaskFragment9: shouldSplit = mem.PlayerData(Offset.heartPieces) == 9 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 1); break; + case SplitName.MaskFragment10: shouldSplit = mem.PlayerData(Offset.heartPieces) == 10 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 2); break; + case SplitName.MaskFragment11: shouldSplit = mem.PlayerData(Offset.heartPieces) == 11 || (mem.PlayerData(Offset.maxHealthBase) == 7 && mem.PlayerData(Offset.heartPieces) == 3); break; + case SplitName.Mask3: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 8; break; + + case SplitName.MaskFragment13: shouldSplit = mem.PlayerData(Offset.heartPieces) == 13 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 1); break; + case SplitName.MaskFragment14: shouldSplit = mem.PlayerData(Offset.heartPieces) == 14 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 2); break; + case SplitName.MaskFragment15: shouldSplit = mem.PlayerData(Offset.heartPieces) == 15 || (mem.PlayerData(Offset.maxHealthBase) == 8 && mem.PlayerData(Offset.heartPieces) == 3); break; + case SplitName.Mask4: shouldSplit = mem.PlayerData(Offset.maxHealthBase) == 9; break; + + #endregion Mask Shards + + #region Vessel Fragments + case SplitName.OnObtainVesselFragment: - shouldSplit = store.CheckIncreasedBy(Offset.MPReserveMax, 33) || (store.CheckIncremented(Offset.vesselFragments) && mem.PlayerData(Offset.vesselFragments) < 3); + shouldSplit = + store.CheckIncreasedBy(Offset.MPReserveMax, 33) // && mem.UIState() != UIState.PLAYING + || (store.CheckIncremented(Offset.vesselFragments) && mem.PlayerData(Offset.vesselFragments) < 3); break; + case SplitName.VesselFragGreenpath: if (currScene == "Fungus1_13") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragCrossroadsLift: if (currScene == "Crossroads_37") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragKingsStation: if (currScene == "Ruins2_09") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragGarpedes: if (currScene == "Deepnest_38") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragStagNest: if (currScene == "Cliffs_03") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragSeer: if (currScene == "RestingGrounds_07") { goto case SplitName.OnObtainVesselFragment; } break; + case SplitName.VesselFragFountain: if (currScene == "Abyss_04") { goto case SplitName.OnObtainVesselFragment; } break; + + case SplitName.VesselFragment1: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 0 && mem.PlayerData(Offset.vesselFragments) == 1; break; + case SplitName.VesselFragment2: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 0 && mem.PlayerData(Offset.vesselFragments) == 2; break; + case SplitName.Vessel1: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 33; break; + + case SplitName.VesselFragment4: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 4 || (mem.PlayerData(Offset.MPReserveMax) == 33 && mem.PlayerData(Offset.vesselFragments) == 1); break; + case SplitName.VesselFragment5: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 5 || (mem.PlayerData(Offset.MPReserveMax) == 33 && mem.PlayerData(Offset.vesselFragments) == 2); break; + case SplitName.Vessel2: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 66; break; + + case SplitName.VesselFragment7: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 7 || (mem.PlayerData(Offset.MPReserveMax) == 66 && mem.PlayerData(Offset.vesselFragments) == 1); break; + case SplitName.VesselFragment8: shouldSplit = mem.PlayerData(Offset.vesselFragments) == 8 || (mem.PlayerData(Offset.MPReserveMax) == 66 && mem.PlayerData(Offset.vesselFragments) == 2); break; + case SplitName.Vessel3: shouldSplit = mem.PlayerData(Offset.MPReserveMax) == 99; break; + + #endregion Vessel Fragments + + #region Colosseum + + // Little Fool under NPC Interactions #region + case SplitName.ColosseumBronze: shouldSplit = mem.PlayerData(Offset.colosseumBronzeCompleted); break; + case SplitName.ColosseumGold: shouldSplit = mem.PlayerData(Offset.colosseumGoldCompleted); break; + case SplitName.ColosseumSilver: shouldSplit = mem.PlayerData(Offset.colosseumSilverCompleted); break; case SplitName.ColosseumBronzeUnlocked: shouldSplit = mem.PlayerData(Offset.colosseumBronzeOpened); break; case SplitName.ColosseumSilverUnlocked: shouldSplit = mem.PlayerData(Offset.colosseumSilverOpened); break; case SplitName.ColosseumGoldUnlocked: shouldSplit = mem.PlayerData(Offset.colosseumGoldOpened); break; - case SplitName.ColosseumBronzeEntry: shouldSplit = sceneName == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Bronze"; break; - case SplitName.ColosseumSilverEntry: shouldSplit = sceneName == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Silver"; break; - case SplitName.ColosseumGoldEntry: shouldSplit = sceneName == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Gold"; break; - case SplitName.ColosseumBronzeExit: shouldSplit = mem.PlayerData(Offset.colosseumBronzeCompleted) && !nextScene.StartsWith("Room_Colosseum_Bronze") && nextScene != sceneName; break; - case SplitName.ColosseumSilverExit: shouldSplit = mem.PlayerData(Offset.colosseumSilverCompleted) && !nextScene.StartsWith("Room_Colosseum_Silver") && nextScene != sceneName; break; - case SplitName.ColosseumGoldExit: shouldSplit = mem.PlayerData(Offset.colosseumGoldCompleted) && !nextScene.StartsWith("Room_Colosseum_Gold") && nextScene != sceneName; break; + case SplitName.ColosseumBronzeEntry: shouldSplit = currScene == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Bronze"; break; + case SplitName.ColosseumSilverEntry: shouldSplit = currScene == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Silver"; break; + case SplitName.ColosseumGoldEntry: shouldSplit = currScene == "Room_Colosseum_01" && nextScene == "Room_Colosseum_Gold"; break; + case SplitName.ColosseumBronzeExit: shouldSplit = mem.PlayerData(Offset.colosseumBronzeCompleted) && !nextScene.StartsWith("Room_Colosseum_Bronze") && nextScene != currScene; break; + case SplitName.ColosseumSilverExit: shouldSplit = mem.PlayerData(Offset.colosseumSilverCompleted) && !nextScene.StartsWith("Room_Colosseum_Silver") && nextScene != currScene; break; + case SplitName.ColosseumGoldExit: shouldSplit = mem.PlayerData(Offset.colosseumGoldCompleted) && !nextScene.StartsWith("Room_Colosseum_Gold") && nextScene != currScene; break; #region Trial of the Warrior case SplitName.Bronze1a: // 1 × Shielded Fool @@ -1497,11 +1500,13 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen break; case SplitName.Bronze7: // 2 × Aspid, 2 × Baldur shouldSplit = - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 6 && - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 9; - shouldSkip = mem.PlayerData(Offset.killsSpitter) == 0 || mem.PlayerData(Offset.killsColRoller) == 0 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 6 || - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 9; + store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 6 + && store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 9; + shouldSkip = + mem.PlayerData(Offset.killsSpitter) == 0 + || mem.PlayerData(Offset.killsColRoller) == 0 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 6 + || store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 9; break; case SplitName.Bronze8a: // 4 × Vengefly shouldSplit = store.killsBuzzerStart - mem.PlayerData(Offset.killsBuzzer) == 4; @@ -1513,18 +1518,19 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen break; case SplitName.Bronze9: // 3 × Sturdy Fool, 2 × Shielded Fool, 2 × Aspid, 2 × Baldur shouldSplit = - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 8 && - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 10 && - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 9 && - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 5; - shouldSkip = mem.PlayerData(Offset.killsSpitter) == 0 || - mem.PlayerData(Offset.killsColRoller) == 0 || - mem.PlayerData(Offset.killsColMiner) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 8 || - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 10 || - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 9 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 5; + store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 8 + && store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 10 + && store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 9 + && store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 5; + shouldSkip = + mem.PlayerData(Offset.killsSpitter) == 0 + || mem.PlayerData(Offset.killsColRoller) == 0 + || mem.PlayerData(Offset.killsColMiner) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 8 + || store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 10 + || store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 9 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 5; break; case SplitName.Bronze10: // 3 × Baldur shouldSplit = store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 13; @@ -1541,46 +1547,45 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen case SplitName.BronzeEnd: // 2 × Gruz Mom shouldSplit = store.killsBigFlyStart - mem.PlayerData(Offset.killsBigFly) == 2; shouldSkip = - mem.PlayerData(Offset.killsBigFly) == 0 && - sceneName.StartsWith("Room_Colosseum_Bronze") && - nextScene != sceneName; + mem.PlayerData(Offset.killsBigFly) == 0 + && currScene.StartsWith("Room_Colosseum_Bronze") + && nextScene != currScene; break; #endregion #region Trial of the Conqueror case SplitName.Silver1: // 2 × Heavy Fool, 3 × Winged Fool shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 2 && - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 3; + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 2 + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 3; shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 2 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 3; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 2 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 3; break; case SplitName.Silver2: // 2 × Squit - shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 2; + shouldSplit = store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 2; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 2; + mem.PlayerData(Offset.killsColMosquito) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 2; break; case SplitName.Silver3: // 2 × Squit shouldSplit = store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 4; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 4; + mem.PlayerData(Offset.killsColMosquito) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 4; break; case SplitName.Silver4: // 1 × Squit, 1 × Winged Fool shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 5 && - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 4; + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 5 + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 4; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 5 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 4; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 5 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 4; break; case SplitName.Silver5: // 2 × Aspid, 2 × Squit, 5 × Infected Gruzzer, aspid kills in Colo 2 use killsSuperSpitter, even though Colo 1 and 3 use killsSpitter shouldSplit = @@ -1597,106 +1602,106 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen break; case SplitName.Silver6: // 1 × Heavy Fool, 3 × Belfly shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 3 && - store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) == 3; + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 3 + && store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) == 3; shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsCeilingDropper) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 3 || - store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 3; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsCeilingDropper) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 3 + || store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 3; break; case SplitName.Silver7: // 1 × Belfly shouldSplit = store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) == 4; shouldSkip = - mem.PlayerData(Offset.killsCeilingDropper) == 0 || - store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 4; + mem.PlayerData(Offset.killsCeilingDropper) == 0 + || store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 4; break; case SplitName.Silver8: // 8 × Hopper, 1 × Great Hopper shouldSplit = store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) == 1; // only checking great hopper shouldSkip = - mem.PlayerData(Offset.killsGiantHopper) == 0 || - store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) > 1; + mem.PlayerData(Offset.killsGiantHopper) == 0 + || store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) > 1; break; case SplitName.Silver9: // 1 × Great Hopper shouldSplit = store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) == 2; shouldSkip = - mem.PlayerData(Offset.killsGiantHopper) == 0 || - store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) > 2; + mem.PlayerData(Offset.killsGiantHopper) == 0 + || store.killsGiantHopperStart - mem.PlayerData(Offset.killsGiantHopper) > 2; break; case SplitName.Silver10: // 1 × Mimic shouldSplit = store.killsGrubMimicStart - mem.PlayerData(Offset.killsGrubMimic) == 1; shouldSkip = - mem.PlayerData(Offset.killsGrubMimic) == 0 || - store.killsGrubMimicStart - mem.PlayerData(Offset.killsGrubMimic) > 1; + mem.PlayerData(Offset.killsGrubMimic) == 0 + || store.killsGrubMimicStart - mem.PlayerData(Offset.killsGrubMimic) > 1; break; case SplitName.Silver11: // 2 × Shielded fool, 2 × Winged Fool, 1 × Heavy Fool, 2 × Squit shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 9 && - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 6 && - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 4; + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 9 + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 6 + && store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 4; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 9 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 6 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 4; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 9 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 6 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 4; break; case SplitName.Silver12: // 1 × Heavy Fool, 1 × Winged Fool shouldSplit = - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 7 && - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 5; + store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 7 + && store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 5; shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 7 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 5; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 7 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 5; break; case SplitName.Silver13: // 1 × Winged Fool, 3 × Squit shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 12 && - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 8; + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 12 + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 8; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 12 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 8; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 12 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 8; break; case SplitName.Silver14: // 3 × Winged Fool, 2 × Squit shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 14 && - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 11; + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 14 + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 11; shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 14 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 11; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 14 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 11; break; case SplitName.Silver15: // 9 × Obbles shouldSplit = store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 9; shouldSkip = - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 9 || - mem.PlayerData(Offset.killsBlobble) == 0; + store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 9 + || mem.PlayerData(Offset.killsBlobble) == 0; break; case SplitName.Silver16: // 4 × Obbles shouldSplit = store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 13; shouldSkip = - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 13 || - mem.PlayerData(Offset.killsBlobble) == 0; + store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 13 + || mem.PlayerData(Offset.killsBlobble) == 0; break; case SplitName.SilverEnd: // 2 × Oblobbles shouldSplit = store.killsOblobbleStart - mem.PlayerData(Offset.killsOblobble) == 2; shouldSkip = - mem.PlayerData(Offset.killsOblobble) == 0 && - sceneName.StartsWith("Room_Colosseum_Silver") && - nextScene != sceneName; + mem.PlayerData(Offset.killsOblobble) == 0 + && currScene.StartsWith("Room_Colosseum_Silver") + && nextScene != currScene; break; #endregion @@ -1704,56 +1709,56 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen case SplitName.Gold1: #region shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 1 && // 1 Heavy Fool - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 1 && // 1 Sturdy Fool - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 2 && // 2 Squit - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 2 && // 2 Shielded Fool - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 1 && // 1 Aspid - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 2 && // 2 Winged Fool - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 2; // 2 Baldurs + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 1 // 1 Heavy Fool + && store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 1 // 1 Sturdy Fool + && store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 2 // 2 Squit + && store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 2 // 2 Shielded Fool + && store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 1 // 1 Aspid + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 2 // 2 Winged Fool + && store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 2; // 2 Baldurs shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColMiner) == 0 || - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - mem.PlayerData(Offset.killsSpitter) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - mem.PlayerData(Offset.killsColRoller) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 1 || - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 1 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 2 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 2 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 1 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 2 || - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 2; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColMiner) == 0 + || mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || mem.PlayerData(Offset.killsSpitter) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || mem.PlayerData(Offset.killsColRoller) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 1 + || store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 1 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 2 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 2 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 1 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 2 + || store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 2; break; #endregion // Wave 2 splits inconsistently since the enemies are killed by the spikes on the floor automatically case SplitName.Gold3: #region shouldSplit = - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 3 && // 3 Obble - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 3 && // 1 Winged Fool - store.killsAngryBuzzerStart - mem.PlayerData(Offset.killsAngryBuzzer) == 2; // 2 Infected Vengefly + store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 3 // 3 Obble + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 3 // 1 Winged Fool + && store.killsAngryBuzzerStart - mem.PlayerData(Offset.killsAngryBuzzer) == 2; // 2 Infected Vengefly shouldSkip = - mem.PlayerData(Offset.killsBlobble) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - mem.PlayerData(Offset.killsAngryBuzzer) == 0 || - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 3 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 3 || - store.killsAngryBuzzerStart - mem.PlayerData(Offset.killsAngryBuzzer) > 2; + mem.PlayerData(Offset.killsBlobble) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || mem.PlayerData(Offset.killsAngryBuzzer) == 0 + || store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 3 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 3 + || store.killsAngryBuzzerStart - mem.PlayerData(Offset.killsAngryBuzzer) > 2; break; #endregion case SplitName.Gold4: #region shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 3 && // 2 Heavy Fool - store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) == 6; // 6 Belflies + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 3 // 2 Heavy Fool + && store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) == 6; // 6 Belflies shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsCeilingDropper) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 3 || - store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 6; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsCeilingDropper) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 3 + || store.killsCeilingDropperStart - mem.PlayerData(Offset.killsCeilingDropper) > 6; break; #endregion case SplitName.Gold5: @@ -1761,8 +1766,8 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) == 3; // 3 Loodle shouldSkip = - mem.PlayerData(Offset.killsColHopper) == 0 || - store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 3; + mem.PlayerData(Offset.killsColHopper) == 0 + || store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 3; break; #endregion case SplitName.Gold6: @@ -1770,8 +1775,8 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) == 8; // 5 Loodle shouldSkip = - mem.PlayerData(Offset.killsColHopper) == 0 || - store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 8; + mem.PlayerData(Offset.killsColHopper) == 0 + || store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 8; break; #endregion case SplitName.Gold7: @@ -1779,56 +1784,56 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) == 11; // 3 Loodle shouldSkip = - mem.PlayerData(Offset.killsColHopper) == 0 || - store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 11; + mem.PlayerData(Offset.killsColHopper) == 0 + || store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 11; break; #endregion case SplitName.Gold8a: #region shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 4 && // 2 Squit - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 5 && // 3 Aspid - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 4; // 1 Winged Fool + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 4 // 2 Squit + && store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 5 // 3 Aspid + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 4; // 1 Winged Fool shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsSpitter) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 4 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 5 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 4; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsSpitter) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 4 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 5 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 4; break; #endregion case SplitName.Gold8: #region shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 6 && // 2 Squit - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 5; // 1 Winged Fool + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 6 // 2 Squit + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 5; // 1 Winged Fool shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 6 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 5; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 6 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 5; break; #endregion case SplitName.Gold9a: #region shouldSplit = - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 3 && // 1 Shielded Fool - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 5 && // 2 Heavy Fool - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 6 && // 1 Aspid - store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) == 2 && // 2 Mantis Traitor - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 4; // 4 Mantis Petra + store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 3 // 1 Shielded Fool + && store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 5 // 2 Heavy Fool + && store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 6 // 1 Aspid + && store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) == 2 // 2 Mantis Traitor + && store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 4; // 4 Mantis Petra shouldSkip = - mem.PlayerData(Offset.killsColShield) == 0 || - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsSpitter) == 0 || - mem.PlayerData(Offset.killsHeavyMantis) == 0 || - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 3 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 5 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 6 || - store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) > 2 || - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) > 4; + mem.PlayerData(Offset.killsColShield) == 0 + || mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsSpitter) == 0 + || mem.PlayerData(Offset.killsHeavyMantis) == 0 + || mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 3 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 5 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) > 6 + || store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) > 2 + || store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) > 4; break; #endregion case SplitName.Gold9b: @@ -1836,83 +1841,83 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) == 1; // 1 Soul Warrior shouldSkip = - mem.PlayerData(Offset.killsMageKnight) == 0 || - store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) > 1; + mem.PlayerData(Offset.killsMageKnight) == 0 + || store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) > 1; break; #endregion case SplitName.Gold10: #region shouldSplit = - store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) == 3 && // 3 Volt Twister - store.killsMageStart - mem.PlayerData(Offset.killsMage) == 4; // 2 Soul Twister + store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) == 3 // 3 Volt Twister + && store.killsMageStart - mem.PlayerData(Offset.killsMage) == 4; // 2 Soul Twister shouldSkip = - mem.PlayerData(Offset.killsElectricMage) == 0 || - mem.PlayerData(Offset.killsMage) == 0 || - store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) > 3 || - store.killsMageStart - mem.PlayerData(Offset.killsMage) > 4; + mem.PlayerData(Offset.killsElectricMage) == 0 + || mem.PlayerData(Offset.killsMage) == 0 + || store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) > 3 + || store.killsMageStart - mem.PlayerData(Offset.killsMage) > 4; break; #endregion case SplitName.Gold11: #region shouldSplit = - store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) == 2 && // 1 Soul Warrior - store.killsMageStart - mem.PlayerData(Offset.killsMage) == 5; // 1 Soul Twister + store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) == 2 // 1 Soul Warrior + && store.killsMageStart - mem.PlayerData(Offset.killsMage) == 5; // 1 Soul Twister shouldSkip = - mem.PlayerData(Offset.killsMageKnight) == 0 || - store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) > 2 || - store.killsMageStart - mem.PlayerData(Offset.killsMage) > 5; + mem.PlayerData(Offset.killsMageKnight) == 0 + || store.killsMageKnightStart - mem.PlayerData(Offset.killsMageKnight) > 2 + || store.killsMageStart - mem.PlayerData(Offset.killsMage) > 5; break; #endregion case SplitName.Gold12a: #region shouldSplit = - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 7 && // 2 Winged Fool - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 4 && // 1 Sturdy Fool - store.killsLesserMawlekStart - mem.PlayerData(Offset.killsLesserMawlek) == 4; // 4 Lesser Mawlek + store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 7 // 2 Winged Fool + && store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 4 // 1 Sturdy Fool + && store.killsLesserMawlekStart - mem.PlayerData(Offset.killsLesserMawlek) == 4; // 4 Lesser Mawlek shouldSkip = - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - mem.PlayerData(Offset.killsColMiner) == 0 || - mem.PlayerData(Offset.killsLesserMawlek) == 0 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 7 || - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 4 || - store.killsLesserMawlekStart - mem.PlayerData(Offset.killsLesserMawlek) > 4; + mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || mem.PlayerData(Offset.killsColMiner) == 0 + || mem.PlayerData(Offset.killsLesserMawlek) == 0 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 7 + || store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 4 + || store.killsLesserMawlekStart - mem.PlayerData(Offset.killsLesserMawlek) > 4; break; #endregion case SplitName.Gold12b: #region shouldSplit = - store.killsMawlekStart - mem.PlayerData(Offset.killsMawlek) == 1; // 1 Brooding Mawlek + store.killsMawlekStart - mem.PlayerData(Offset.killsMawlek) == 1; // 1 Brooding Mawlek shouldSkip = - mem.PlayerData(Offset.killsMawlek) == 0 || - store.killsMawlekStart - mem.PlayerData(Offset.killsMawlek) > 1; + mem.PlayerData(Offset.killsMawlek) == 0 + || store.killsMawlekStart - mem.PlayerData(Offset.killsMawlek) > 1; break; #endregion // Wave 13 doesn't really exist, it's just vertical Garpedes so there's nothing to Split on case SplitName.Gold14a: #region shouldSplit = - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 10 && // 1 Squit - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 7 && // 1 Aspid - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 5; // 1 Mantis Petra + store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 10 // 1 Squit + && store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) == 7 // 1 Aspid + && store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 5; // 1 Mantis Petra shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 || - mem.PlayerData(Offset.killsSpitter) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 10 || - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) > 5 || - store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) - 1 > 7; + mem.PlayerData(Offset.killsColMosquito) == 0 + || mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 + || mem.PlayerData(Offset.killsSpitter) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 10 + || store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) > 5 + || store.killsSpitterStart - mem.PlayerData(Offset.killsSpitter) - 1 > 7; break; #endregion case SplitName.Gold14b: #region shouldSplit = - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 10 && // 2 Winged Fool - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 7; // 4 Obble + store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 10 // 2 Winged Fool + && store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) == 7; // 4 Obble shouldSkip = - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - mem.PlayerData(Offset.killsBlobble) == 0 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 10 || - store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 7; + mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || mem.PlayerData(Offset.killsBlobble) == 0 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 10 + || store.killsBlobbleStart - mem.PlayerData(Offset.killsBlobble) > 7; break; #endregion case SplitName.Gold15: @@ -1920,8 +1925,8 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 12; // 2 Squit shouldSkip = - mem.PlayerData(Offset.killsColMosquito) == 0 || - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 12; + mem.PlayerData(Offset.killsColMosquito) == 0 + || store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) > 12; break; #endregion case SplitName.Gold16: @@ -1929,74 +1934,74 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) == 25; // 14 Loodle elderC shouldSkip = - mem.PlayerData(Offset.killsColHopper) == 0 || - store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 25; + mem.PlayerData(Offset.killsColHopper) == 0 + || store.killsColHopperStart - mem.PlayerData(Offset.killsColHopper) > 25; break; #endregion case SplitName.Gold17a: #region shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 6 && // 1 Heavy Fool - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 5 && // 1 Sturdy Fool - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 4 && // 1 Shielded Fool - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 6 && // 1 Mantis Petra - store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) == 3 && // 1 Mantis Traitor - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 11; // 1 Winged Fool + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 6 // 1 Heavy Fool + && store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 5 // 1 Sturdy Fool + && store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 4 // 1 Shielded Fool + && store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 6 // 1 Mantis Petra + && store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) == 3 // 1 Mantis Traitor + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 11; // 1 Winged Fool shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColMiner) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 || - mem.PlayerData(Offset.killsHeavyMantis) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 6 || - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 5 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 4 || - store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) - 1 > 6 || - store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) > 3 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) - 1 > 11; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColMiner) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || mem.PlayerData(Offset.killsMantisHeavyFlyer) == 0 + || mem.PlayerData(Offset.killsHeavyMantis) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 6 + || store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 5 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 4 + || store.killsHeavyMantisFlyerStart - mem.PlayerData(Offset.killsMantisHeavyFlyer) - 1 > 6 + || store.killsHeavyMantisStart - mem.PlayerData(Offset.killsHeavyMantis) > 3 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) - 1 > 11; break; #endregion case SplitName.Gold17b: #region shouldSplit = - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 7 && // 1 Heavy Fool - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 5 && // 1 Shielded Fool - store.killsMageStart - mem.PlayerData(Offset.killsMage) == 6 && // 1 Soul Twister - store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) == 4; // 1 Volt Twister + store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 7 // 1 Heavy Fool + && store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 5 // 1 Shielded Fool + && store.killsMageStart - mem.PlayerData(Offset.killsMage) == 6 // 1 Soul Twister + && store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) == 4; // 1 Volt Twister shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - mem.PlayerData(Offset.killsMage) == 0 || - mem.PlayerData(Offset.killsElectricMage) == 0 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 7 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 5 || - store.killsMageStart - mem.PlayerData(Offset.killsMage) > 6 || - store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) > 4; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || mem.PlayerData(Offset.killsMage) == 0 + || mem.PlayerData(Offset.killsElectricMage) == 0 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 7 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 5 + || store.killsMageStart - mem.PlayerData(Offset.killsMage) > 6 + || store.killsElectricMageStart - mem.PlayerData(Offset.killsElectricMage) > 4; break; #endregion case SplitName.Gold17c: #region shouldSplit = - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 4 && // 2 Baldur - store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 14 && // 2 Squit - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 8 && // 1 Heavy Fool - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 6 && // 1 Shielded Fool - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 6 && // 1 Sturdy Fool - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 12; // 1 Winged Fool + store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) == 4 // 2 Baldur + && store.killsColMosquitoStart - mem.PlayerData(Offset.killsColMosquito) == 14// 2 Squit + && store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) == 8 // 1 Heavy Fool + && store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) == 6 // 1 Shielded Fool + && store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) == 6 // 1 Sturdy Fool + && store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) == 12; // 1 Winged Fool shouldSkip = - mem.PlayerData(Offset.killsColWorm) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - mem.PlayerData(Offset.killsColMiner) == 0 || - mem.PlayerData(Offset.killsColFlyingSentry) == 0 || - mem.PlayerData(Offset.killsColRoller) == 0 || - mem.PlayerData(Offset.killsColShield) == 0 || - store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 4 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 14 || - store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 8 || - store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 6 || - store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 6 || - store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 12; + mem.PlayerData(Offset.killsColWorm) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || mem.PlayerData(Offset.killsColMiner) == 0 + || mem.PlayerData(Offset.killsColFlyingSentry) == 0 + || mem.PlayerData(Offset.killsColRoller) == 0 + || mem.PlayerData(Offset.killsColShield) == 0 + || store.killsColRollerStart - mem.PlayerData(Offset.killsColRoller) > 4 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 14 + || store.killsColWormStart - mem.PlayerData(Offset.killsColWorm) > 8 + || store.killsColShieldStart - mem.PlayerData(Offset.killsColShield) > 6 + || store.killsColMinerStart - mem.PlayerData(Offset.killsColMiner) > 6 + || store.killsColFlyingSentryStart - mem.PlayerData(Offset.killsColFlyingSentry) > 12; break; #endregion case SplitName.GoldEnd: @@ -2004,18 +2009,17 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen shouldSplit = store.killsLobsterLancerStart - mem.PlayerData(Offset.killsLobsterLancer) == 1; // God Tamer shouldSkip = - mem.PlayerData(Offset.killsLobsterLancer) == 0 && - sceneName.StartsWith("Room_Colosseum_Gold") && - nextScene != sceneName; + mem.PlayerData(Offset.killsLobsterLancer) == 0 + && currScene.StartsWith("Room_Colosseum_Gold") + && nextScene != currScene; break; #endregion #endregion + #endregion Colosseum + default: - //throw new Exception(split + " does not have a defined shouldsplit value"); - if (!failedValues.Contains(split)) { - failedValues.Add(split); - } + shouldSkip = true; break; } @@ -2026,39 +2030,38 @@ private SplitterAction CheckSplit(SplitName split, string nextScene, string scen action = SplitterAction.Skip; } else if (shouldSplit) { action = SplitterAction.Split; - } else { - action = SplitterAction.Pass; } return action; + } - private void HandleSplit(SplitterAction action, bool shouldReset = false) { - bool splitAdvanced = false; + private void DoAction(SplitterAction action, bool shouldReset = false) { + + var update = () => { + store.SplitThisTransition = true; + store.Update(); + }; if (action == SplitterAction.Reset || shouldReset) { - if (currentSplit >= 0) { + if (currentSplitIndex >= 0) { Model.Reset(); } } else if (action == SplitterAction.Skip) { - if (currentSplit >= 0) { + if (currentSplitIndex >= 0) { Model.SkipSplit(); + update(); } - splitAdvanced = true; } else if (action == SplitterAction.Split) { - if (currentSplit < 0) { + if (currentSplitIndex == 0) { // if start of run Model.Start(); - } else { + } else { // if anywhere else in run Model.Split(); } - splitAdvanced = true; + update(); } - if (splitAdvanced) { - store.SplitThisTransition = true; - store.Update(); - } - } + }//2007 #endif private void LogValues() { if (lastLogCheck == 0) { @@ -2078,7 +2081,7 @@ private void LogValues() { switch (key) { case "CurrentSplit": - curr = currentSplit.ToString(); + curr = currentSplitIndex.ToString(); break; case "State": curr = state.ToString(); break; case "GameState": curr = mem.GameState().ToString(); break; @@ -2150,19 +2153,12 @@ public void Update(IInvalidator invalidator, LiveSplitState lvstate, float width } public void OnReset(object sender, TimerPhase e) { - currentSplit = -1; + currentSplitIndex = 0; // index zero now has the auto-start split state = 0; + menuSplitHelper = false; lookForTeleporting = false; Model.CurrentState.IsGameTimePaused = true; - splitsDone.Clear(); store.Reset(); - if (failedValues.Count > 0) { - WriteLog("---------Splits without match-------------------"); - foreach (var value in failedValues) { - WriteLogWithTime(value.ToString() + " - does not have a defined shouldsplit value"); - } - failedValues.Clear(); - } WriteLog("---------Reset----------------------------------"); } public void OnResume(object sender, EventArgs e) { @@ -2172,32 +2168,31 @@ public void OnPause(object sender, EventArgs e) { WriteLog("---------Paused---------------------------------"); } public void OnStart(object sender, EventArgs e) { - currentSplit = 0; + currentSplitIndex = 1; state = 0; + menuSplitHelper = false; Model.CurrentState.IsGameTimePaused = true; Model.CurrentState.SetGameTime(Model.CurrentState.CurrentTime.RealTime); - splitsDone.Clear(); store.Reset(); - failedValues.Clear(); store.SplitThisTransition = true; store.Update(); WriteLog("---------New Game-------------------------------"); } public void OnUndoSplit(object sender, EventArgs e) { - currentSplit--; - //if (!settings.Ordered) splitsDone.Remove(lastSplitDone); Reminder of THIS BREAKS THINGS + currentSplitIndex--; state = 0; } public void OnSkipSplit(object sender, EventArgs e) { - currentSplit++; + currentSplitIndex++; state = 0; + menuSplitHelper = false; } public void OnSplit(object sender, EventArgs e) { - currentSplit++; + currentSplitIndex++; + state = 0; + menuSplitHelper = false; store.SplitThisTransition = true; store.Update(); - - state = 0; } public Control GetSettingsControl(LayoutMode mode) { return settings; } public void SetSettings(XmlNode document) { settings.SetSettings(document); } diff --git a/HollowKnightSettings.Designer.cs b/HollowKnightSettings.Designer.cs index c14d86d..5c76f2f 100644 --- a/HollowKnightSettings.Designer.cs +++ b/HollowKnightSettings.Designer.cs @@ -20,7 +20,7 @@ protected override void Dispose(bool disposing) { /// /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. + /// the contents of this method with the code editor. // oop sorry 'bout that /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); @@ -29,11 +29,8 @@ private void InitializeComponent() { this.flowOptions = new System.Windows.Forms.FlowLayoutPanel(); this.Options_GroupBox = new System.Windows.Forms.GroupBox(); this.versionLabel = new System.Windows.Forms.Label(); - this.RunBehaviour_GroupBox = new System.Windows.Forms.GroupBox(); + this.cboStartTriggerName = new System.Windows.Forms.ComboBox(); - this.chkAutosplitStartRuns = new System.Windows.Forms.CheckBox(); - this.chkOrdered = new System.Windows.Forms.CheckBox(); - this.chkAutosplitEndRuns = new System.Windows.Forms.CheckBox(); this.SortBy_GroupBox = new System.Windows.Forms.GroupBox(); this.rdAlpha = new System.Windows.Forms.RadioButton(); this.rdType = new System.Windows.Forms.RadioButton(); @@ -41,7 +38,7 @@ private void InitializeComponent() { this.flowMain.SuspendLayout(); this.flowOptions.SuspendLayout(); this.Options_GroupBox.SuspendLayout(); - this.RunBehaviour_GroupBox.SuspendLayout(); + this.SortBy_GroupBox.SuspendLayout(); this.SuspendLayout(); // @@ -52,7 +49,7 @@ private void InitializeComponent() { this.btnAddSplit.Size = new System.Drawing.Size(57, 21); this.btnAddSplit.TabIndex = 0; this.btnAddSplit.Text = "Add Split"; - this.ToolTips.SetToolTip(this.btnAddSplit, "All game endings automatically stop timer when on final split"); + this.ToolTips.SetToolTip(this.btnAddSplit, "Add another autosplit"); this.btnAddSplit.UseVisualStyleBackColor = true; this.btnAddSplit.Click += new System.EventHandler(this.btnAddSplit_Click); // @@ -89,7 +86,6 @@ private void InitializeComponent() { // this.Options_GroupBox.Controls.Add(this.btnAddSplit); this.Options_GroupBox.Controls.Add(this.versionLabel); - this.Options_GroupBox.Controls.Add(this.RunBehaviour_GroupBox); this.Options_GroupBox.Controls.Add(this.SortBy_GroupBox); this.Options_GroupBox.Location = new System.Drawing.Point(3, 3); this.Options_GroupBox.Name = "Options_GroupBox"; @@ -105,66 +101,17 @@ private void InitializeComponent() { this.versionLabel.Size = new System.Drawing.Size(182, 24); this.versionLabel.TabIndex = 7; this.versionLabel.Text = "Autosplitter Version: x.x.x.x"; - this.versionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // RunBehaviour_GroupBox - // - this.RunBehaviour_GroupBox.Controls.Add(this.cboStartTriggerName); - this.RunBehaviour_GroupBox.Controls.Add(this.chkAutosplitStartRuns); - this.RunBehaviour_GroupBox.Controls.Add(this.chkOrdered); - this.RunBehaviour_GroupBox.Controls.Add(this.chkAutosplitEndRuns); - this.RunBehaviour_GroupBox.Location = new System.Drawing.Point(143, 15); - this.RunBehaviour_GroupBox.Name = "RunBehaviour_GroupBox"; - this.RunBehaviour_GroupBox.Size = new System.Drawing.Size(301, 71); - this.RunBehaviour_GroupBox.TabIndex = 7; - this.RunBehaviour_GroupBox.TabStop = false; - this.RunBehaviour_GroupBox.Text = "Run behaviour"; // // cboStartTriggerName // this.cboStartTriggerName.Enabled = false; this.cboStartTriggerName.FormattingEnabled = true; - this.cboStartTriggerName.Location = new System.Drawing.Point(148, 42); + this.cboStartTriggerName.Location = new System.Drawing.Point(148, 17); this.cboStartTriggerName.Name = "cboStartTriggerName"; this.cboStartTriggerName.Size = new System.Drawing.Size(145, 21); this.cboStartTriggerName.TabIndex = 7; this.cboStartTriggerName.SelectedIndexChanged += new System.EventHandler(this.cboStartTriggerName_SelectedIndexChanged); // - // chkAutosplitStartRuns - // - this.chkAutosplitStartRuns.AutoSize = true; - this.chkAutosplitStartRuns.Location = new System.Drawing.Point(6, 42); - this.chkAutosplitStartRuns.Name = "chkAutosplitStartRuns"; - this.chkAutosplitStartRuns.Size = new System.Drawing.Size(139, 17); - this.chkAutosplitStartRuns.TabIndex = 6; - this.chkAutosplitStartRuns.Text = "Start-triggering autosplit:"; - this.ToolTips.SetToolTip(this.chkAutosplitStartRuns, "The specified autosplit starts the timer. Use for ILs"); - this.chkAutosplitStartRuns.UseVisualStyleBackColor = true; - this.chkAutosplitStartRuns.CheckedChanged += new System.EventHandler(this.AutosplitStartChanged); - // - // chkOrdered - // - this.chkOrdered.Location = new System.Drawing.Point(6, 17); - this.chkOrdered.Name = "chkOrdered"; - this.chkOrdered.Size = new System.Drawing.Size(92, 19); - this.chkOrdered.TabIndex = 4; - this.chkOrdered.Text = "Ordered Splits"; - this.ToolTips.SetToolTip(this.chkOrdered, "Required for runs with Pantheon and/or transition splits"); - this.chkOrdered.UseVisualStyleBackColor = true; - this.chkOrdered.CheckedChanged += new System.EventHandler(this.ControlChanged); - // - // chkAutosplitEndRuns - // - this.chkAutosplitEndRuns.AutoEllipsis = true; - this.chkAutosplitEndRuns.Location = new System.Drawing.Point(148, 17); - this.chkAutosplitEndRuns.Name = "chkAutosplitEndRuns"; - this.chkAutosplitEndRuns.Size = new System.Drawing.Size(133, 19); - this.chkAutosplitEndRuns.TabIndex = 5; - this.chkAutosplitEndRuns.Text = "End-triggering autosplit"; - this.ToolTips.SetToolTip(this.chkAutosplitEndRuns, "Any autosplit can stop the timer on final split to finish a run"); - this.chkAutosplitEndRuns.UseVisualStyleBackColor = true; - this.chkAutosplitEndRuns.CheckedChanged += new System.EventHandler(this.AutosplitEndChanged); - // // SortBy_GroupBox // this.SortBy_GroupBox.Controls.Add(this.rdAlpha); @@ -220,8 +167,6 @@ private void InitializeComponent() { this.flowMain.PerformLayout(); this.flowOptions.ResumeLayout(false); this.Options_GroupBox.ResumeLayout(false); - this.RunBehaviour_GroupBox.ResumeLayout(false); - this.RunBehaviour_GroupBox.PerformLayout(); this.SortBy_GroupBox.ResumeLayout(false); this.SortBy_GroupBox.PerformLayout(); this.ResumeLayout(false); @@ -235,14 +180,10 @@ private void InitializeComponent() { private System.Windows.Forms.FlowLayoutPanel flowOptions; private System.Windows.Forms.RadioButton rdType; private System.Windows.Forms.RadioButton rdAlpha; - private System.Windows.Forms.CheckBox chkOrdered; - private System.Windows.Forms.CheckBox chkAutosplitEndRuns; private System.Windows.Forms.GroupBox Options_GroupBox; private System.Windows.Forms.ToolTip ToolTips; private System.Windows.Forms.Label versionLabel; - private System.Windows.Forms.GroupBox RunBehaviour_GroupBox; private System.Windows.Forms.GroupBox SortBy_GroupBox; - private System.Windows.Forms.CheckBox chkAutosplitStartRuns; private System.Windows.Forms.ComboBox cboStartTriggerName; } } diff --git a/HollowKnightSettings.cs b/HollowKnightSettings.cs index b5806ab..91ad549 100644 --- a/HollowKnightSettings.cs +++ b/HollowKnightSettings.cs @@ -9,12 +9,10 @@ namespace LiveSplit.HollowKnight { public partial class HollowKnightSettings : UserControl { public List Splits { get; private set; } - public bool Ordered { get; set; } - public bool AutosplitEndRuns { get; set; } - public SplitName? AutosplitStartRuns { get; set; } private bool isLoading; private List availableSplits = new List(); private List availableSplitsAlphaSorted = new List(); + private Label startTriggerSeparator = new Label(); public HollowKnightSettings() { isLoading = true; @@ -36,6 +34,7 @@ public bool HasSplit(SplitName split) { private void Settings_Load(object sender, EventArgs e) { LoadSettings(); } + public void LoadSettings() { isLoading = true; this.flowMain.SuspendLayout(); @@ -44,10 +43,6 @@ public void LoadSettings() { flowMain.Controls.RemoveAt(i); } - chkOrdered.Checked = Ordered; - chkAutosplitEndRuns.Checked = AutosplitEndRuns; - chkAutosplitStartRuns.Checked = AutosplitStartRuns != null; - foreach (SplitName split in Splits) { MemberInfo info = typeof(SplitName).GetMember(split.ToString())[0]; DescriptionAttribute description = (DescriptionAttribute)info.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]; @@ -61,9 +56,27 @@ public void LoadSettings() { flowMain.Controls.Add(setting); } + AddStartTriggerSeparator(); + isLoading = false; this.flowMain.ResumeLayout(true); } + + private void AddStartTriggerSeparator() { + // horizontal rule (https://stackoverflow.com/a/3296161) + this.startTriggerSeparator.AccessibleName = "Start trigger separator"; + this.startTriggerSeparator.Text = string.Empty; + this.startTriggerSeparator.BorderStyle = BorderStyle.Fixed3D; + this.startTriggerSeparator.AutoSize = false; + this.startTriggerSeparator.Height = 2; + this.flowMain.Controls.Add(this.startTriggerSeparator); + PositionStartTriggerSeparator(); + } + + private void PositionStartTriggerSeparator() { + this.flowMain.Controls.SetChildIndex(this.startTriggerSeparator, 2); + } + private void AddHandlers(HollowKnightSplitSettings setting) { setting.cboName.SelectedIndexChanged += new EventHandler(ControlChanged); setting.btnRemove.Click += new EventHandler(btnRemove_Click); @@ -135,14 +148,11 @@ public void ControlChanged(object sender, EventArgs e) { UpdateSplits(); } public void UpdateSplits() { - if (isLoading) return; - Ordered = chkOrdered.Checked; - AutosplitEndRuns = chkAutosplitEndRuns.Checked; - AutosplitStartRuns = chkAutosplitStartRuns.Checked ? - HollowKnightSplitSettings.GetSplitName(cboStartTriggerName.Text) : null; + if (isLoading) return; Splits.Clear(); + foreach (Control c in flowMain.Controls) { if (c is HollowKnightSplitSettings) { HollowKnightSplitSettings setting = (HollowKnightSplitSettings)c; @@ -152,14 +162,15 @@ public void UpdateSplits() { } } } + PositionStartTriggerSeparator(); } public XmlNode UpdateSettings(XmlDocument document) { + XmlElement xmlSettings = document.CreateElement("Settings"); - XmlElement xmlOrdered = document.CreateElement("Ordered"); - xmlOrdered.InnerText = Ordered.ToString(); - xmlSettings.AppendChild(xmlOrdered); + // TODO: have livesplit automatically change starting and ending split to just another split + /* XmlElement xmlAutosplitEndRuns = document.CreateElement("AutosplitEndRuns"); xmlAutosplitEndRuns.InnerText = AutosplitEndRuns.ToString(); xmlSettings.AppendChild(xmlAutosplitEndRuns); @@ -167,6 +178,7 @@ public XmlNode UpdateSettings(XmlDocument document) { XmlElement xmlAutosplitStartRuns = document.CreateElement("AutosplitStartRuns"); xmlAutosplitStartRuns.InnerText = AutosplitStartRuns.ToString(); xmlSettings.AppendChild(xmlAutosplitStartRuns); + */ XmlElement xmlSplits = document.CreateElement("Splits"); xmlSettings.AppendChild(xmlSplits); @@ -181,40 +193,65 @@ public XmlNode UpdateSettings(XmlDocument document) { return xmlSettings; } public void SetSettings(XmlNode settings) { - XmlNode orderedNode = settings.SelectSingleNode(".//Ordered"); - XmlNode AutosplitEndRunsNode = settings.SelectSingleNode(".//AutosplitEndRuns"); - XmlNode AutosplitStartRunsNode = settings.SelectSingleNode(".//AutosplitStartRuns"); - bool isOrdered = false; - bool isAutosplitEndRuns = false; - - if (orderedNode != null) { - bool.TryParse(orderedNode.InnerText, out isOrdered); - } - if (AutosplitEndRunsNode != null) { - bool.TryParse(AutosplitEndRunsNode.InnerText, out isAutosplitEndRuns); - } - if (AutosplitStartRunsNode != null) { - string splitDescription = AutosplitStartRunsNode.InnerText.Trim(); - if (!string.IsNullOrEmpty(splitDescription)) { - cboStartTriggerName.DataSource = GetAvailableSplits(); - AutosplitStartRuns = HollowKnightSplitSettings.GetSplitName(splitDescription); - MemberInfo info = typeof(SplitName).GetMember(AutosplitStartRuns.ToString())[0]; - DescriptionAttribute description = (DescriptionAttribute)info.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]; - cboStartTriggerName.Text = description.Description; - chkAutosplitStartRuns.Checked = true; + + Splits.Clear(); // reset the splits + + XmlNode splitsNode = settings.SelectSingleNode(".//Splits"); // will be null if it's the WASM autosplitter + XmlNode customSettingsNode = settings.SelectSingleNode(".//CustomSettings"); // will be null if it's the Default autosplitter + + if (splitsNode != null) { + // Default autosplitter + XmlNodeList splitNodes = settings.SelectNodes(".//Splits/Split"); + foreach (XmlNode splitNode in splitNodes) { + SplitName split = HollowKnightSplitSettings.GetSplitName(splitNode.InnerText); + Splits.Add(split); } - } - Ordered = isOrdered; - AutosplitEndRuns = isAutosplitEndRuns; - Splits.Clear(); - XmlNodeList splitNodes = settings.SelectNodes(".//Splits/Split"); - foreach (XmlNode splitNode in splitNodes) { - string splitDescription = splitNode.InnerText; - SplitName split = HollowKnightSplitSettings.GetSplitName(splitDescription); - Splits.Add(split); + // legacy auto-start and auto-end splits + + XmlNode AutosplitStartRunsNode = settings.SelectSingleNode(".//AutosplitStartRuns"); // will be null if it's the new version (or really really old version, that'll be broken i guess) + XmlNode AutosplitEndRunsNode = settings.SelectSingleNode(".//AutosplitEndRuns"); // will be null if it's the new version... same as above + XmlNode OrderedNode = settings.SelectSingleNode(".//Ordered"); // will be null if it's the new version... same as above + if (AutosplitStartRunsNode != null || AutosplitEndRunsNode != null || OrderedNode != null) { // if it's the an old .lss file + string splitDescription = AutosplitStartRunsNode?.InnerText?.Trim(); + + // if there's an explicit auto-start split, add it to the list, if not, add legacy start + if (!string.IsNullOrEmpty(splitDescription)) { + cboStartTriggerName.DataSource = GetAvailableSplits(); + Splits.Insert(0, HollowKnightSplitSettings.GetSplitName(splitDescription)); + } else { // implicit auto-start in .lss, add it to the list + Splits.Insert(0, SplitName.LegacyStart); // add the legacy start split for now + } + + // check if autoend split + bool isAutosplitEndRuns = false; + if (AutosplitEndRunsNode != null) { + bool.TryParse(AutosplitEndRunsNode.InnerText, out isAutosplitEndRuns); + } + + // if there's an explicit auto-end, leave it, if there's not, add legacy ending split to list + if (!isAutosplitEndRuns) { + Splits.Add(SplitName.LegacyEnd); + } + + } + } else if (customSettingsNode != null) { + // WASM autosplitter + XmlNodeList splitNodes = settings.SelectNodes(".//CustomSettings/Setting[@id='splits']/Setting"); + foreach (XmlNode splitNode in splitNodes) { + string value = splitNode.Attributes.GetNamedItem("value").Value; + Splits.Add(HollowKnightSplitSettings.GetSplitName(value)); + } + } else { + // no splits settings, default auto-start and auto-end + Splits.Insert(0, SplitName.LegacyStart); + Splits.Add(SplitName.LegacyEnd); } + + return; + } + private HollowKnightSplitSettings createSetting() { HollowKnightSplitSettings setting = new HollowKnightSplitSettings(); List splitNames = GetAvailableSplits(); @@ -260,12 +297,6 @@ private void radio_CheckedChanged(object sender, EventArgs e) { } } } - - if (chkAutosplitStartRuns.Checked) { - string text = cboStartTriggerName.Text; - cboStartTriggerName.DataSource = GetAvailableSplits(); - cboStartTriggerName.Text = text; - } } private void flowMain_DragDrop(object sender, DragEventArgs e) { UpdateSplits(); @@ -290,22 +321,7 @@ private void flowMain_DragOver(object sender, DragEventArgs e) { destination.Invalidate(); } } - } - private void AutosplitEndChanged(object sender, EventArgs e) { - UpdateSplits(); - } - - private void AutosplitStartChanged(object sender, EventArgs e) { - if (chkAutosplitStartRuns.Checked) { - cboStartTriggerName.Enabled = true; - cboStartTriggerName.DataSource = GetAvailableSplits(); - } - else { - cboStartTriggerName.Text = ""; - cboStartTriggerName.Enabled = false; - cboStartTriggerName.DataSource = new List(); - } - UpdateSplits(); + PositionStartTriggerSeparator(); } private void cboStartTriggerName_SelectedIndexChanged(object sender, EventArgs e) { diff --git a/HollowKnightSplitSettings.cs b/HollowKnightSplitSettings.cs index e840310..e9ca5d3 100644 --- a/HollowKnightSplitSettings.cs +++ b/HollowKnightSplitSettings.cs @@ -209,7 +209,7 @@ public enum SplitName { VesselFragment7, [Description("Vessel Fragment 8 (Fragment)"), ToolTip("Splits when getting 8th Soul Vessel Fragment")] VesselFragment8, - [Description("Soul Vessel 3 (Upgrade)"), ToolTip("Splits when upgrading to 3 Soul Vessels (9 Soul Vessel Fragments")] + [Description("Soul Vessel 3 (Upgrade)"), ToolTip("Splits when upgrading to 3 Soul Vessels (9 Soul Vessel Fragments)")] Vessel3, [Description("Brooding Mawlek Mask Shard (Obtain)"), ToolTip("Splits when getting the Mask Shard from Brooding Mawlek")] @@ -272,9 +272,6 @@ public enum SplitName { DungDefender, [Description("Dung Defender Idol (Item)"), ToolTip("Splits when picking up Dung Defender idol as the first idol")] DungDefenderIdol, - - - [Description("Glade Idol (Item)"), ToolTip("Splits when picking up the King's Idol in the Spirits' Glade")] GladeIdol, [Description("Elder Hu (Boss)"), ToolTip("Splits when killing Elder Hu")] @@ -621,8 +618,6 @@ public enum SplitName { AspidHunter, [Description("Aluba (Killed)"), ToolTip("Splits when killing an Aluba")] Aluba, - //[Description("Al2ba (Killed)"), ToolTip("Splits when killing two Alubas")] - //Al2ba, [Description("Little Baldur Hunter's Notes (Killed)"), ToolTip("Splits when killing all little Baldurs needed for Hunter's Notes journal completion")] RollerHuntersNotes, [Description("Maggots (Killed)"), ToolTip("Splits when killing both Maggots")] @@ -641,8 +636,6 @@ public enum SplitName { killedSanctumWarrior, [Description("Soul Twister (Killed)"), ToolTip("Splits on first Soul Twister kill")] killedSoulTwister, - //[Description("Revek (Killed)"), ToolTip("Splits when talking to Revek after clearing all other Glade ghosts")] - //Revek, [Description("Moss Knight (Mini Boss)"), ToolTip("Splits when killing Moss Knight")] MossKnight, [Description("Shrumal Ogres (Mini Boss)"), ToolTip("Splits when killing the final Shrumal Ogre")] @@ -1454,12 +1447,24 @@ public enum SplitName { Menu, [Description("Main Menu w/ Claw (Menu)"), ToolTip("Splits on transition to the main menu after Mantis Claw acquired")] MenuClaw, + [Description("Main Menu w/ Mothwing Cloak (Menu)"), ToolTip("Splits on transition to the main menu after Mothwing Cloak acquired")] + MenuCloak, + [Description("Main Menu w/ Dashmaster (Menu)"), ToolTip("Splits on transition to the main menu after Dashmaster acquired")] + MenuDashmaster, + [Description("Main Menu w/ Dream Nail (Menu)"), ToolTip("Splits on transition to the main menu after Dream Nail acquired")] + MenuDreamNail, + [Description("Main Menu w/ Dream Gate (Menu)"), ToolTip("Splits on transition to the main menu after Dream Gate acquired")] + MenuDreamGate, + [Description("Main Menu w/ 3 Dreamers (Menu)"), ToolTip("Splits on transition to the main menu after 3 Dreamers acquired")] + MenuDreamer3, [Description("Main Menu w/ Ghusk (Menu)"), ToolTip("Splits on transition to the main menu after Gorgeous Husk defeated")] MenuGorgeousHusk, [Description("Main Menu w/ Isma's Tear (Menu)"), ToolTip("Splits on transition to the main menu after Isma's Tear acquired")] MenuIsmasTear, [Description("Main Menu w/ Shade Soul (Menu)"), ToolTip("Splits on transition to the main menu after Shade Soul acquired")] MenuShadeSoul, + [Description("Main Menu w/ Void Heart (Menu)"), ToolTip("Splits on transition to the main menu after Void Heart acquired")] + MenuVoidHeart, [Description("Cornifer at Home (Transition)"), ToolTip("Splits when entering Iselda's hut while Cornifer is sleeping")] CorniferAtHome, @@ -1677,28 +1682,6 @@ public enum SplitName { [Description("Ghost Coins Incremented (Event)"), ToolTip("Splits when the ghostCoins PlayerData is updated. Unused by unmodded game, intended for use with mods.")] OnGhostCoinsIncremented, - /* - [Description("Mage Door (Test)"), ToolTip("Splits when Nailsmith is spared")] - MageDoor, - [Description("Sanctum Warrior Window (Test)"), ToolTip("Splits when Nailsmith is killed")] - MageWindow, - [Description("Mage Lord Enc. (Test)"), ToolTip("Splits when Nailsmith is spared")] - MageLordEncountered, - [Description("Mage Lord 2 Enc. (Test)"), ToolTip("Splits when Nailsmith is killed")] - MageDoor2, - [Description("Mage Window (Test)"), ToolTip("Splits when Nailsmith is spared")] - MageWindowGlass, - [Description("Mage Window Glass (Test)"), ToolTip("Splits when Nailsmith is killed")] - MageLordEncountered2, - */ - - - - /* - [Description("Equipped fr. health (menu testing)"), ToolTip("Splits when equipping charm23, for timing menuing")] - EquippedFragileHealth, - */ - } public class ToolTipAttribute : Attribute { public string ToolTip { get; set; } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 1f0d657..3f46791 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -12,8 +12,8 @@ [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("b3294e28-2bd4-4e39-92fa-e04a620c7e77")] -[assembly: AssemblyVersion("3.1.16.0")] -[assembly: AssemblyFileVersion("3.1.16.0")] +[assembly: AssemblyVersion("4.0.0.0")] +[assembly: AssemblyFileVersion("4.0.0.0")] #if !Info [assembly: ComponentFactory(typeof(HollowKnightFactory))] #endif diff --git a/README.md b/README.md index 5534f5c..4568e4b 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,27 @@ Hollow Knight Autosplitter / Load Remover - Edit your splits - Click the 'Activate' autosplitter button - Add any splits to your main splits file -- Hit the 'Settings' button to then set up the same autosplitter splits \ No newline at end of file +- Hit the 'Settings' button to then set up the same autosplitter splits + +## Building the autosplitter from source +If you would like to modify and build the autosplitter yourself, download the source and change the file path to your livesplit folder in `LiveSplit.HollowKnight.csproj`. +```xml + + + ..\..\LiveSplit + +``` +For example, I set it to `D:\Documents\LiveSplit` as that is where my `LiveSplit.exe` is. With this you should be set all to build it. + +## Make your own autosplit +If you would like to add or modify an autosplit, there are two things you must do: +Each split is a value in an enum called `SplitName`, which is declared in `HollowKnightSplitSettings.cs`. You must add a value for your splits, and give it the proper attributes that will be the split's name and mouse-over description inside LiveSplit. To add logic for your split, you need to add a case for it in the giant switch in `HollowKnightComponent`, and have it appropriately set the value of `shouldSplit`, `shouldSkip` and `shouldReset` to true for the conditions under which you wish to split, skip or reset respectively. + +**Important note** : Modifications to the autosplitter are allowed but may be subject to retiming at moderators' discretion. Modifications to the load removal or the start/end conditions may result in your run time being adjusted or retimed RTA. + + +## Contributing to the official autosplitter +Autosplitter maintenance is currently led by slaurent22. If you would like to contribute, send pull requests to [his branch](https://github.com/slaurent22/LiveSplit.HollowKnight) and he will manage including it in the next official update. + +*** +If you have any specific questions about the autosplitter's code, you can message @slaurent, @mayonnaisical or @cerpintext on discord