From ab015b6487aa39bdc062b478e58bbe0e7fc89859 Mon Sep 17 00:00:00 2001 From: jakzo Date: Fri, 10 Nov 2023 00:53:52 +1100 Subject: [PATCH 1/5] boneworks 100% asl --- scripts/Boneworks100.asl | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 scripts/Boneworks100.asl diff --git a/scripts/Boneworks100.asl b/scripts/Boneworks100.asl new file mode 100644 index 0000000..438ea9a --- /dev/null +++ b/scripts/Boneworks100.asl @@ -0,0 +1,84 @@ +state("BONEWORKS") { + int levelNumber : "GameAssembly.dll", 0x01E7E4E0, 0xB8, 0x590; +} + +init { + var module = modules.First(x => x.ModuleName == "vrclient_x64.dll"); + + var scanner = + new SignatureScanner(game, module.BaseAddress, module.ModuleMemorySize); + + vars.loadingPointer = scanner.Scan(new SigScanTarget( + 3, + "4889??????????488B??????????48FF????488B??????????488B??4889??????????488D??????????488B??????????48FF??????????????????????????????488B??????????418B") { + OnFound = (process, scanners, addr) => + addr + 0x4 + process.ReadValue(addr) + }); + if (vars.loadingPointer == IntPtr.Zero) { + throw new Exception("Game engine not initialized - retrying"); + } + + vars.isLoading = + new MemoryWatcher(new DeepPointer(vars.loadingPointer, 0xC54)); + + // Will split when entering each level in this list in this order + // If entering a level later in the list it will split until it reaches it + vars.levelOrder = new int[] { + 1, // scene_mainMenu + 2, // scene_theatrigon_movie01 -> scene_breakroom + 4, // scene_museum + 5, // scene_streets + 6, // scene_runoff + 7, // scene_sewerStation + 8, // scene_warehouse + 9, // scene_subwayStation + 10, // scene_tower + 11, // scene_towerBoss + 12, // scene_theatrigon_movie02 -> scene_dungeon + 14, // scene_arena + 15, // scene_throneRoom + 1, // scene_mainMenu + 5, // scene_streets + 6, // scene_runoff + 18, // scene_redactedChamber + 19, // sandbox_handgunBox + 22, // scene_hoverJunkers + 16, // arena_fantasy + 23, // zombie_warehouse + // 23, // zombie_warehouse + // 23, // zombie_warehouse + 1, // scene_mainMenu + 1, // scene_mainMenu + 1, // scene_mainMenu + }; + vars.levelOrderIdx = 0; + vars.targetLevelOrderIdx = 0; +} + +update { vars.isLoading.Update(game); } + +isLoading { return vars.isLoading.Current; } + +start { return vars.isLoading.Current && current.levelNumber == 2; } + +split { + if (vars.isLoading.Current && + (!vars.isLoading.Old || current.levelNumber != old.levelNumber)) { + for (var i = vars.levelOrderIdx + 1; + i < vars.levelOrder.Length && i <= vars.levelOrderIdx + 2; i++) { + if (vars.levelOrder[i] == current.levelNumber) { + vars.targetLevelOrderIdx = i; + break; + } + } + + if (vars.levelOrderIdx < vars.targetLevelOrderIdx) { + vars.levelOrderIdx++; + return true; + } + } + + return false; +} + +exit { timer.IsGameTimePaused = true; } From 021d3adc0aab3e7b85477e1e5c5c0f3b5fd06719 Mon Sep 17 00:00:00 2001 From: jakzo Date: Fri, 10 Nov 2023 02:59:23 +1100 Subject: [PATCH 2/5] update asl --- scripts/Boneworks100.asl | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/scripts/Boneworks100.asl b/scripts/Boneworks100.asl index 438ea9a..38e6ead 100644 --- a/scripts/Boneworks100.asl +++ b/scripts/Boneworks100.asl @@ -24,10 +24,11 @@ init { // Will split when entering each level in this list in this order // If entering a level later in the list it will split until it reaches it vars.levelOrder = new int[] { - 1, // scene_mainMenu 2, // scene_theatrigon_movie01 -> scene_breakroom 4, // scene_museum 5, // scene_streets + 5, // scene_streets + 6, // scene_runoff 6, // scene_runoff 7, // scene_sewerStation 8, // scene_warehouse @@ -38,8 +39,6 @@ init { 14, // scene_arena 15, // scene_throneRoom 1, // scene_mainMenu - 5, // scene_streets - 6, // scene_runoff 18, // scene_redactedChamber 19, // sandbox_handgunBox 22, // scene_hoverJunkers @@ -48,36 +47,32 @@ init { // 23, // zombie_warehouse // 23, // zombie_warehouse 1, // scene_mainMenu - 1, // scene_mainMenu - 1, // scene_mainMenu }; vars.levelOrderIdx = 0; - vars.targetLevelOrderIdx = 0; } update { vars.isLoading.Update(game); } isLoading { return vars.isLoading.Current; } -start { return vars.isLoading.Current && current.levelNumber == 2; } +start { + if (vars.isLoading.Current && current.levelNumber == 2) { + vars.levelOrderIdx = 0; + return true; + } + return false; +} split { if (vars.isLoading.Current && (!vars.isLoading.Old || current.levelNumber != old.levelNumber)) { - for (var i = vars.levelOrderIdx + 1; - i < vars.levelOrder.Length && i <= vars.levelOrderIdx + 2; i++) { - if (vars.levelOrder[i] == current.levelNumber) { - vars.targetLevelOrderIdx = i; - break; - } - } - - if (vars.levelOrderIdx < vars.targetLevelOrderIdx) { - vars.levelOrderIdx++; + var nextLevelOrderIdx = vars.levelOrderIdx + 1; + if (nextLevelOrderIdx < vars.levelOrder.Length && + vars.levelOrder[nextLevelOrderIdx] == current.levelNumber) { + vars.levelOrderIdx = nextLevelOrderIdx; return true; } } - return false; } From 0be4195158f32d650ee95d347ac92937c67fb64b Mon Sep 17 00:00:00 2001 From: jakzo Date: Fri, 10 Nov 2023 18:02:41 +1100 Subject: [PATCH 3/5] starting split --- scripts/Boneworks100.asl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/Boneworks100.asl b/scripts/Boneworks100.asl index 38e6ead..c8a750d 100644 --- a/scripts/Boneworks100.asl +++ b/scripts/Boneworks100.asl @@ -21,6 +21,9 @@ init { vars.isLoading = new MemoryWatcher(new DeepPointer(vars.loadingPointer, 0xC54)); + // Index in levelOrder to start the run at (for practice) + vars.startingSplit = 0; + // Will split when entering each level in this list in this order // If entering a level later in the list it will split until it reaches it vars.levelOrder = new int[] { @@ -49,6 +52,7 @@ init { 1, // scene_mainMenu }; vars.levelOrderIdx = 0; + vars.targetLevelOrderIdx = vars.startingSplit; } update { vars.isLoading.Update(game); } @@ -56,7 +60,8 @@ update { vars.isLoading.Update(game); } isLoading { return vars.isLoading.Current; } start { - if (vars.isLoading.Current && current.levelNumber == 2) { + if (vars.isLoading.Current && + current.levelNumber == vars.levelOrder[vars.startingSplit]) { vars.levelOrderIdx = 0; return true; } @@ -69,10 +74,15 @@ split { var nextLevelOrderIdx = vars.levelOrderIdx + 1; if (nextLevelOrderIdx < vars.levelOrder.Length && vars.levelOrder[nextLevelOrderIdx] == current.levelNumber) { - vars.levelOrderIdx = nextLevelOrderIdx; - return true; + vars.targetLevelOrderIdx = nextLevelOrderIdx; } } + + if (vars.levelOrderIdx < vars.targetLevelOrderIdx) { + vars.levelOrderIdx++; + return true; + } + return false; } From e63111b57eeb9f3b177ffd0bf40917a54f35fc5b Mon Sep 17 00:00:00 2001 From: jakzo Date: Sat, 11 Nov 2023 12:48:49 +1100 Subject: [PATCH 4/5] arena splitting --- .../src/Features/ArenaSplitState.cs | 50 +++++++++++++++++++ projects/Boneworks/SpeedrunTools/src/Mod.cs | 1 + scripts/Boneworks100.asl | 16 +++++- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 projects/Boneworks/SpeedrunTools/src/Features/ArenaSplitState.cs diff --git a/projects/Boneworks/SpeedrunTools/src/Features/ArenaSplitState.cs b/projects/Boneworks/SpeedrunTools/src/Features/ArenaSplitState.cs new file mode 100644 index 0000000..aa93f3d --- /dev/null +++ b/projects/Boneworks/SpeedrunTools/src/Features/ArenaSplitState.cs @@ -0,0 +1,50 @@ +using MelonLoader; +using HarmonyLib; +using UnityEngine; +using StressLevelZero.Arena; + +namespace Sst.Features { +class ArenaSplitState : Feature { + // State that the ASL finds using signature scanning + private static byte[] State = { + // 0 = magic string start + // Signature is set dynamically to avoid finding this hardcoded array + 0x00, // 0xD5 + 0xE2, + 0x03, + 0x34, + 0xC2, + 0xDF, + 0x63, + // 7 = arena index + 0x00, + }; + + private static bool _isCurrentChallengeCompleted = true; + + public ArenaSplitState() { State[0] = 0xD5; } + + [HarmonyPatch(typeof(Arena_GameManager), + nameof(Arena_GameManager.RingTheBell))] + class ArenaGameManager_RingTheBell_Patch { + [HarmonyPostfix()] + internal static void Postfix(Arena_GameManager __instance) { + _isCurrentChallengeCompleted = + __instance.activeChallenge?.profile?.completedHard ?? true; + } + } + + [HarmonyPatch(typeof(Arena_GameManager), + nameof(Arena_GameManager.SaveChallengeCompletion))] + class ArenaGameManager_SaveChallengeCompletion_Patch { + [HarmonyPostfix()] + internal static void Postfix(Arena_GameManager __instance) { + if (!_isCurrentChallengeCompleted && + __instance.activeChallenge.profile.completedHard) { + _isCurrentChallengeCompleted = true; + State[7]++; + } + } + } +} +} diff --git a/projects/Boneworks/SpeedrunTools/src/Mod.cs b/projects/Boneworks/SpeedrunTools/src/Mod.cs index c425a51..37b3c95 100644 --- a/projects/Boneworks/SpeedrunTools/src/Mod.cs +++ b/projects/Boneworks/SpeedrunTools/src/Mod.cs @@ -31,6 +31,7 @@ public class Mod : MelonMod { new Features.Gripless(), new Features.Armless(), new Features.RestartLevel(), + new Features.ArenaSplitState(), // Dev features new Features.Speedometer(), diff --git a/scripts/Boneworks100.asl b/scripts/Boneworks100.asl index c8a750d..c4f0985 100644 --- a/scripts/Boneworks100.asl +++ b/scripts/Boneworks100.asl @@ -21,6 +21,13 @@ init { vars.isLoading = new MemoryWatcher(new DeepPointer(vars.loadingPointer, 0xC54)); + var arenaTarget = new SigScanTarget(7, "D4 E2 03 34 C2 DF 63 ??"); + var ptr = scanner.Scan(target); + if (ptr == IntPtr.Zero) { + throw new Exception("Game engine not initialized - retrying"); + } + vars.arenaWatcher = new MemoryWatcher(ptr); + // Index in levelOrder to start the run at (for practice) vars.startingSplit = 0; @@ -55,7 +62,10 @@ init { vars.targetLevelOrderIdx = vars.startingSplit; } -update { vars.isLoading.Update(game); } +update { + vars.isLoading.Update(game); + vars.arenaWatcher.Update(game); +} isLoading { return vars.isLoading.Current; } @@ -69,6 +79,10 @@ start { } split { + if (vars.arenaWatcher.Current != vars.arenaWatcher.Old) { + return true; + } + if (vars.isLoading.Current && (!vars.isLoading.Old || current.levelNumber != old.levelNumber)) { var nextLevelOrderIdx = vars.levelOrderIdx + 1; From 1f70e1649f1cad237905b430dc9286b237f3aaa8 Mon Sep 17 00:00:00 2001 From: jakzo Date: Sat, 11 Nov 2023 13:51:03 +1100 Subject: [PATCH 5/5] fix --- scripts/Boneworks100.asl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/Boneworks100.asl b/scripts/Boneworks100.asl index c4f0985..6ca120e 100644 --- a/scripts/Boneworks100.asl +++ b/scripts/Boneworks100.asl @@ -21,10 +21,17 @@ init { vars.isLoading = new MemoryWatcher(new DeepPointer(vars.loadingPointer, 0xC54)); - var arenaTarget = new SigScanTarget(7, "D4 E2 03 34 C2 DF 63 ??"); - var ptr = scanner.Scan(target); + var arenaTarget = new SigScanTarget(7, "D5 E2 03 34 C2 DF 63 ??"); + IntPtr ptr = IntPtr.Zero; + foreach (var page in game.MemoryPages(true)) { + var pageScanner = + new SignatureScanner(game, page.BaseAddress, (int)page.RegionSize); + ptr = pageScanner.Scan(arenaTarget); + if (ptr != IntPtr.Zero) + break; + } if (ptr == IntPtr.Zero) { - throw new Exception("Game engine not initialized - retrying"); + throw new Exception("Arena state not found - retrying"); } vars.arenaWatcher = new MemoryWatcher(ptr);