From 6b10fe165d6d597523d8c845c398117bd0611c05 Mon Sep 17 00:00:00 2001 From: Robin Sonneveld <6283731+rtsonneveld@users.noreply.github.com> Date: Mon, 19 Jun 2023 20:51:19 +0200 Subject: [PATCH] 3.9.0 Use ghostmode to reset camera when teleporting, added custom spawn point for rayman 2, small refactorings and bugfixes. --- .../Games/Rayman2/Rayman2CheckpointExtra.cs | 82 ++++ .../Games/Rayman2/Rayman2GameManager.cs | 4 + .../Games/Rayman3/Rayman3GameManager.cs | 3 +- .../GameManager/GenericGameManager.cs | 243 ++++++----- .../GameManager/OpenspaceGameManager.cs | 385 +++++++++++------- OpenSpaceToolbox/Helpers/Memory.cs | 16 +- OpenSpaceToolbox/OpenSpaceToolbox.csproj | 1 + 7 files changed, 462 insertions(+), 272 deletions(-) create mode 100644 OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2CheckpointExtra.cs diff --git a/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2CheckpointExtra.cs b/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2CheckpointExtra.cs new file mode 100644 index 0000000..b56629e --- /dev/null +++ b/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2CheckpointExtra.cs @@ -0,0 +1,82 @@ +using System; +using System.Threading; + +namespace OpenSpaceToolbox +{ + public class Rayman2CheckpointExtra : OpenspaceExtraAction + { + public Rayman2CheckpointExtra(Rayman2GameManager gameManager) : base(gameManager) + { + Name = ShortName = "Set spawn point (CAREFUL)"; + + ResurrectionPositionPointer = 0x500590; + + AssemblyNop1Pointer = 0x406495; + AssemblyNop2Pointer = 0x4064A2; + AssemblyNop3Pointer = 0x4031CB; + + RespawnPersoPointer = 0x4B7308; + RespawnPersoPointerPath = new int[] {0xC, 0, 0x4, 0x1C, 0xA90 }; + } + + private int RespawnPersoPointer { get; } + private int[] RespawnPersoPointerPath { get; } + + private int ResurrectionPositionPointer { get; } + + private int AssemblyNop1Pointer { get; } + private int AssemblyNop2Pointer { get; } + private int AssemblyNop3Pointer { get; } + + public override void Action() + { + int processHandle = GameManager.GetProcessHandle(); + if (processHandle < 0) + return; + + // (ugly and a bit too permanent) + // nop the code that resets the resurrection point + GameManager.WriteBytes(new byte[5] { 0x90, 0x90, 0x90, 0x90, 0x90 }, AssemblyNop1Pointer); + GameManager.WriteBytes(new byte[5] { 0x90, 0x90, 0x90, 0x90, 0x90 }, AssemblyNop2Pointer); + + /* + * Code that's NOPed: + * void fn_vSnifThePlayerIsDead(void) + { + -> POS_fn_vSetIdentityMatrix(&g_stEngineStructure.stMainCharacterPosition); + -> POS_fn_vSetIdentityMatrix(&g_stEngineStructure.stMainCameraPosition); + ... + */ + + // and nop the code that checks if resurrection is TRUE + // (so it always executes that part) + GameManager.WriteBytes(new byte[2] { 0x90, 0x90}, AssemblyNop3Pointer); + + /* + * Code that's NOPed: + * void fn_vInitDeadLoop() { + * ... + * -> if(g_stEngineStructure.bResurection) + */ + + var playerCoords = GameManager.PlayerCoordinates; + + Thread.Sleep(100); + + GameManager.WriteCoordinates( + playerCoords.Item1, playerCoords.Item2, playerCoords.Item3, + ResurrectionPositionPointer); + + // GlobalActorModel.DsgVar_29, reset checkpoint object to null + GameManager.WriteDWord(0, RespawnPersoPointer, RespawnPersoPointerPath); + + Thread.Sleep(50); + + // Deathwarp and immediately put player back + GameManager.WriteEngineMode(8); // EM_ModePlayerDead + + Thread.Sleep(150); + GameManager.PlayerCoordinates = playerCoords; + } + } +} \ No newline at end of file diff --git a/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2GameManager.cs b/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2GameManager.cs index 6c363d2..793bc58 100644 --- a/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2GameManager.cs +++ b/OpenSpaceToolbox/GameManager/Games/Rayman2/Rayman2GameManager.cs @@ -22,6 +22,9 @@ public Rayman2GameManager() PausedStatePointer = 0x500FAA; PlayerCoordinatesBasePointer = 0x500560; PlayerCoordinatesOffsets = new[] { 0x224, 0x310, 0x34, 0x0, 0x1ac }; + + GhostModePointer = 0x500370; + PossibleProcessNames = new[] { "Rayman2", "Rayman2.exe", "Rayman2.exe.noshim" }; //Extras @@ -33,6 +36,7 @@ public Rayman2GameManager() new Rayman2MaxHpExtra(this), new Rayman2GlmMonitorExtra(this), new Rayman2ProgressArrayExtra(this), + new Rayman2CheckpointExtra(this), }; //Levels diff --git a/OpenSpaceToolbox/GameManager/Games/Rayman3/Rayman3GameManager.cs b/OpenSpaceToolbox/GameManager/Games/Rayman3/Rayman3GameManager.cs index b342234..0aac4a6 100644 --- a/OpenSpaceToolbox/GameManager/Games/Rayman3/Rayman3GameManager.cs +++ b/OpenSpaceToolbox/GameManager/Games/Rayman3/Rayman3GameManager.cs @@ -20,6 +20,7 @@ public Rayman3GameManager() EngineModePointer = EngineStructurePointer + 0x0; LevelNamePointer = EngineStructurePointer + 0x1F; PausedStatePointer = 0x7D848C; + GhostModePointer = 0x7D7D84; PlayerCoordinatesBasePointer = 0x5BFAD4; PlayerCoordinatesOffsets = new[] { 0x140, 0x258, 0x108, 0x324}; PossibleProcessNames = new[] { "Rayman3", "Rayman3.exe", "Rayman3.exe.noshim" }; @@ -133,6 +134,6 @@ public Rayman3GameManager() Levels = LevelContainers.SelectMany(x => x.Levels); } - #endregion + #endregion } } diff --git a/OpenSpaceToolbox/GameManager/GenericGameManager.cs b/OpenSpaceToolbox/GameManager/GenericGameManager.cs index 3e8afb9..519a3e0 100644 --- a/OpenSpaceToolbox/GameManager/GenericGameManager.cs +++ b/OpenSpaceToolbox/GameManager/GenericGameManager.cs @@ -1,61 +1,71 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; namespace OpenSpaceToolbox { - /// - /// Generic game manager. - /// - public abstract class GenericGameManager - { - #region Public Properties - - /// - /// The full name of the game. - /// - public string Name { get; protected set; } - - /// - /// The name of the executable, without extension. - /// - public string ExecName { get; protected set; } - - /// - /// The name of the game window, used for determining if the game is focused. - /// - public string WindowName { get; protected set; } - - /// - /// Filename used to save level bookmarks. - /// - public string BookmarkFileName { get; protected set; } - - /// - /// Player coordinates tuple. - /// Retrieving and writing values to the memory should be handled in functions: ReadPlayerCoordinates and WritePlayerCoordinates. - /// - public (float, float, float) PlayerCoordinates - { - get => ReadPlayerCoordinates(); - set => WritePlayerCoordinates(value.Item1, value.Item2, value.Item3); - } - - /// - /// Current level name. - /// Retrieving and writing values to the memory should be handled in functions: GetCurrentLevelName and ChangeLevel. - /// - public string CurrentLevel - { - get => GetCurrentLevelName(); - set => ChangeLevel(value); - } - - public ObservableCollection ExtraActions { get; protected set; } - - public ObservableCollection LevelContainers { get; protected set; } - - public IEnumerable Levels { get; protected set; } + /// + /// Generic game manager. + /// + public abstract class GenericGameManager + { + #region Public Properties + + /// + /// The full name of the game. + /// + public string Name { get; protected set; } + + /// + /// The name of the executable, without extension. + /// + public string ExecName { get; protected set; } + + /// + /// The name of the game window, used for determining if the game is focused. + /// + public string WindowName { get; protected set; } + + /// + /// Filename used to save level bookmarks. + /// + public string BookmarkFileName { get; protected set; } + + /// + /// Player coordinates tuple. + /// Retrieving and writing values to the memory should be handled in functions: ReadPlayerCoordinates and WritePlayerCoordinates. + /// + public (float, float, float) PlayerCoordinates + { + get => ReadPlayerCoordinates(); + set + { + WritePlayerCoordinates(value.Item1, value.Item2, value.Item3); + + bool oldGhostMode = ReadGhostMode(); + WriteGhostMode(true); + Thread.Sleep(30); + WriteGhostMode(oldGhostMode); + } + } + + /// + /// Current level name. + /// Retrieving and writing values to the memory should be handled in functions: GetCurrentLevelName and ChangeLevel. + /// + public string CurrentLevel + { + get => GetCurrentLevelName(); + set => ChangeLevel(value); + } + + public ObservableCollection ExtraActions { get; protected set; } + + public ObservableCollection LevelContainers { get; protected set; } + + public IEnumerable Levels { get; protected set; } #endregion @@ -82,62 +92,73 @@ public string CurrentLevel /// protected abstract (float, float, float) ReadPlayerCoordinates(); - /// - /// Writes player coordinates from the game memory. - /// - /// - /// - /// - protected abstract void WritePlayerCoordinates(float x, float y, float z); - - /// - /// Get current level name from the game memory. - /// - /// - protected abstract string GetCurrentLevelName(); - - /// - /// Loads a new level. - /// - /// - protected virtual void ChangeLevel(string levelName) - { - OnChangeLevel?.Invoke(levelName); - } - - #endregion - - #region Public Methods - - /// - /// Get the process handle of the game. - /// - /// Indicates if a message should be shown if the process is not found - /// - public abstract int GetProcessHandle(bool showMessage = true); - - /// - /// Checks if the game is currently paused. - /// - /// - public abstract bool IsGamePaused(); - - /// - /// Checks if the game window is currently focused. - /// - /// - public abstract bool IsGameFocused(); - - /// - /// Reloads the current level. - /// - public virtual void ReloadLevel() - { - OnReloadLevel?.Invoke(); - } - - public abstract void LoadOffsetLevel(int offset); - - #endregion - } -} + /// + /// Writes player coordinates from the game memory. + /// + /// + /// + /// + protected abstract void WritePlayerCoordinates(float x, float y, float z); + + /// + /// Checks if GhostMode (g_ucIsEdInGhostMode) is active + /// + /// g_ucIsEdInGhostMode + public abstract bool ReadGhostMode(); + + /// + /// Sets GhostMode (g_ucIsEdInGhostMode) + /// + public abstract void WriteGhostMode(bool value); + + /// + /// Get current level name from the game memory. + /// + /// + protected abstract string GetCurrentLevelName(); + + /// + /// Loads a new level. + /// + /// + protected virtual void ChangeLevel(string levelName) + { + OnChangeLevel?.Invoke(levelName); + } + + #endregion + + #region Public Methods + + /// + /// Get the process handle of the game. + /// + /// Indicates if a message should be shown if the process is not found + /// + public abstract int GetProcessHandle(bool showMessage = true); + + /// + /// Checks if the game is currently paused. + /// + /// + public abstract bool IsGamePaused(); + + /// + /// Checks if the game window is currently focused. + /// + /// + public abstract bool IsGameFocused(); + + /// + /// Reloads the current level. + /// + public virtual void ReloadLevel() + { + OnReloadLevel?.Invoke(); + } + + public abstract void LoadOffsetLevel(int offset); + + #endregion + } +} \ No newline at end of file diff --git a/OpenSpaceToolbox/GameManager/OpenspaceGameManager.cs b/OpenSpaceToolbox/GameManager/OpenspaceGameManager.cs index 884ffb5..eb33d2a 100644 --- a/OpenSpaceToolbox/GameManager/OpenspaceGameManager.cs +++ b/OpenSpaceToolbox/GameManager/OpenspaceGameManager.cs @@ -6,221 +6,302 @@ namespace OpenSpaceToolbox { - /// - /// Game manager for Ubisoft OpenSpace engine games. - /// - public abstract class OpenspaceGameManager : GenericGameManager - { - - #region Protected Properties + /// + /// Game manager for Ubisoft OpenSpace engine games. + /// + public abstract class OpenspaceGameManager : GenericGameManager + { + #region Protected Properties protected int EngineStructurePointer { get; set; } - protected int EngineModePointer { get; set; } - protected int LevelNamePointer { get; set; } - protected int PausedStatePointer { get; set; } - protected int GhostModePointer { get; set; } - protected int PlayerCoordinatesBasePointer { get; set; } - protected int[] PlayerCoordinatesOffsets { get; set; } - protected string[] PossibleProcessNames { get; set; } + protected int EngineModePointer { get; set; } + protected int LevelNamePointer { get; set; } + protected int PausedStatePointer { get; set; } + protected int GhostModePointer { get; set; } + protected int PlayerCoordinatesBasePointer { get; set; } + protected int[] PlayerCoordinatesOffsets { get; set; } - #endregion + protected string[] PossibleProcessNames { get; set; } - #region Protected Methods + #endregion - protected override (float, float, float) ReadPlayerCoordinates() => - ReadCoordinates(PlayerCoordinatesBasePointer, PlayerCoordinatesOffsets); + #region Protected Methods - protected override void WritePlayerCoordinates(float x, float y, float z) => - WriteCoordinates(x, y, z, PlayerCoordinatesBasePointer, PlayerCoordinatesOffsets); + protected override (float, float, float) ReadPlayerCoordinates() => + ReadCoordinates(PlayerCoordinatesBasePointer, PlayerCoordinatesOffsets); - protected override string GetCurrentLevelName() - { - int processHandle = GetProcessHandle(false); + protected override void WritePlayerCoordinates(float x, float y, float z) => + WriteCoordinates(x, y, z, PlayerCoordinatesBasePointer, PlayerCoordinatesOffsets); - int bytesReadOrWritten = 0; - byte[] buffer = new byte[16]; + protected override string GetCurrentLevelName() + { + int processHandle = GetProcessHandle(false); - Memory.ReadProcessMemory(processHandle, LevelNamePointer, buffer, buffer.Length, ref bytesReadOrWritten); + int bytesReadOrWritten = 0; + byte[] buffer = new byte[16]; - string levelName = Encoding.ASCII.GetString(buffer); - levelName = levelName.Substring(0, levelName.IndexOf((char)0)); + Memory.ReadProcessMemory(processHandle, LevelNamePointer, buffer, buffer.Length, ref bytesReadOrWritten); - return levelName; - } + string levelName = Encoding.ASCII.GetString(buffer); + levelName = levelName.Substring(0, levelName.IndexOf((char)0)); - protected override void ChangeLevel(string levelName) - { - base.ChangeLevel(levelName); - int processHandle = GetProcessHandle(); - int bytesReadOrWritten = 0; + return levelName; + } - var buffer = Encoding.ASCII.GetBytes(levelName + char.MinValue); - Memory.WriteProcessMemory(processHandle, LevelNamePointer, buffer, buffer.Length, ref bytesReadOrWritten); + protected override void ChangeLevel(string levelName) + { + base.ChangeLevel(levelName); + int processHandle = GetProcessHandle(); + int bytesReadOrWritten = 0; - buffer = new byte[] {6}; + var buffer = Encoding.ASCII.GetBytes(levelName + char.MinValue); + Memory.WriteProcessMemory(processHandle, LevelNamePointer, buffer, buffer.Length, ref bytesReadOrWritten); - Memory.WriteProcessMemory(processHandle, EngineModePointer, buffer, buffer.Length, ref bytesReadOrWritten); + WriteEngineMode(6); + } + #endregion + + #region Public Methods + + public void WriteEngineMode(byte newMode) + { + WriteBytes(new byte[]{newMode}, EngineModePointer); } - #endregion + public int ReadDWord(int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return 0; + + int bytesReadOrWritten = 0; + int offset = Memory.GetPointerPath(processHandle, baseAddress, offsets); - #region Public Methods + byte[] buffer = new byte[4]; - public (float, float, float) ReadCoordinates(int baseAddress, params int[] offsets) - { - int processHandle = GetProcessHandle(); - if (processHandle < 0) - return (0, 0, 0); + Memory.ReadProcessMemory(processHandle, offset, buffer, 4, ref bytesReadOrWritten); - int bytesReadOrWritten = 0; - int offXcoord = Memory.GetPointerPath(processHandle, baseAddress, offsets); - int offYcoord = offXcoord + 4; - int offZcoord = offXcoord + 8; + return BitConverter.ToInt32(buffer, 0); + } - byte[] xCoordBuffer = new byte[4]; - byte[] yCoordBuffer = new byte[4]; - byte[] zCoordBuffer = new byte[4]; + public byte[] ReadBytes(int length, int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return null; - Memory.ReadProcessMemory(processHandle, offXcoord, xCoordBuffer, 4, ref bytesReadOrWritten); - Memory.ReadProcessMemory(processHandle, offYcoord, yCoordBuffer, 4, ref bytesReadOrWritten); - Memory.ReadProcessMemory(processHandle, offZcoord, zCoordBuffer, 4, ref bytesReadOrWritten); + int bytesReadOrWritten = 0; + int offset = Memory.GetPointerPath(processHandle, baseAddress, offsets); - return ( - BitConverter.ToSingle(xCoordBuffer, 0), - BitConverter.ToSingle(yCoordBuffer, 0), - BitConverter.ToSingle(zCoordBuffer, 0) - ); - } + byte[] buffer = new byte[length]; - public void WriteCoordinates(float x, float y, float z, int baseAddress, params int[] offsets) - { - int processHandle = GetProcessHandle(); - if (processHandle < 0) - return; + Memory.ReadProcessMemory(processHandle, offset, buffer, buffer.Length, ref bytesReadOrWritten); - int bytesReadOrWritten = 0; - int offXcoord = Memory.GetPointerPath(processHandle, baseAddress, offsets); - int offYcoord = offXcoord + 4; - int offZcoord = offXcoord + 8; + return buffer; + } - byte[] xCoordBuffer = BitConverter.GetBytes(x); - byte[] yCoordBuffer = BitConverter.GetBytes(y); - byte[] zCoordBuffer = BitConverter.GetBytes(z); + public void WriteDWord(int value, int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return; - Memory.WriteProcessMemory(processHandle, offXcoord, xCoordBuffer, 4, ref bytesReadOrWritten); - Memory.WriteProcessMemory(processHandle, offYcoord, yCoordBuffer, 4, ref bytesReadOrWritten); - Memory.WriteProcessMemory(processHandle, offZcoord, zCoordBuffer, 4, ref bytesReadOrWritten); - } + int bytesReadOrWritten = 0; + int offset = Memory.GetPointerPath(processHandle, baseAddress, offsets); - public override int GetProcessHandle(bool showMessage = true) - { - Process process = (from name in PossibleProcessNames select Process.GetProcessesByName(name) into p where p.Any() select p.First()).FirstOrDefault(); + byte[] buffer = BitConverter.GetBytes(value); - if (process == null) - { - if (showMessage) - MessageBox.Show($"Couldn't find process '{ExecName}'. Please make sure the game is running or try launching this program with Administrator rights."); + Memory.WriteProcessMemory(processHandle, offset, buffer, 4, ref bytesReadOrWritten); + } - return -1; - } + public void WriteBytes(byte[] bytes, int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return; + + int bytesReadOrWritten = 0; + int offset = Memory.GetPointerPath(processHandle, baseAddress, offsets); - IntPtr processHandle = Memory.OpenProcess(Memory.PROCESS_WM_READ | Memory.PROCESS_VM_WRITE | Memory.PROCESS_VM_OPERATION, false, process.Id); - process.Dispose(); + Memory.WriteProcessMemory(processHandle, offset, bytes, bytes.Length, ref bytesReadOrWritten); + } + + public (float, float, float) ReadCoordinates(int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return (0, 0, 0); + + int bytesReadOrWritten = 0; + int offXcoord = Memory.GetPointerPath(processHandle, baseAddress, offsets); + int offYcoord = offXcoord + 4; + int offZcoord = offXcoord + 8; + + byte[] xCoordBuffer = new byte[4]; + byte[] yCoordBuffer = new byte[4]; + byte[] zCoordBuffer = new byte[4]; + + Memory.ReadProcessMemory(processHandle, offXcoord, xCoordBuffer, 4, ref bytesReadOrWritten); + Memory.ReadProcessMemory(processHandle, offYcoord, yCoordBuffer, 4, ref bytesReadOrWritten); + Memory.ReadProcessMemory(processHandle, offZcoord, zCoordBuffer, 4, ref bytesReadOrWritten); + + return ( + BitConverter.ToSingle(xCoordBuffer, 0), + BitConverter.ToSingle(yCoordBuffer, 0), + BitConverter.ToSingle(zCoordBuffer, 0) + ); + } + + public void WriteCoordinates(float x, float y, float z, int baseAddress, params int[] offsets) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return; + + int bytesReadOrWritten = 0; + int offXcoord = Memory.GetPointerPath(processHandle, baseAddress, offsets); + int offYcoord = offXcoord + 4; + int offZcoord = offXcoord + 8; + + byte[] xCoordBuffer = BitConverter.GetBytes(x); + byte[] yCoordBuffer = BitConverter.GetBytes(y); + byte[] zCoordBuffer = BitConverter.GetBytes(z); + + Memory.WriteProcessMemory(processHandle, offXcoord, xCoordBuffer, 4, ref bytesReadOrWritten); + Memory.WriteProcessMemory(processHandle, offYcoord, yCoordBuffer, 4, ref bytesReadOrWritten); + Memory.WriteProcessMemory(processHandle, offZcoord, zCoordBuffer, 4, ref bytesReadOrWritten); + } - if ((int)processHandle == 0) { - if (showMessage) { - MessageBox.Show($"Error opening process '{ExecName}'. Try launching this program with Administrator rights."); - } + public override int GetProcessHandle(bool showMessage = true) + { + Process process = + (from name in PossibleProcessNames + select Process.GetProcessesByName(name) + into p + where p.Any() + select p.First()).FirstOrDefault(); + + if (process == null) { + if (showMessage) + MessageBox.Show( + $"Couldn't find process '{ExecName}'. Please make sure the game is running or try launching this program with Administrator rights."); + + return -1; + } + + IntPtr processHandle = + Memory.OpenProcess(Memory.PROCESS_WM_READ | Memory.PROCESS_VM_WRITE | Memory.PROCESS_VM_OPERATION, false, + process.Id); + process.Dispose(); + + if ((int)processHandle == 0) { + if (showMessage) { + MessageBox.Show( + $"Error opening process '{ExecName}'. Try launching this program with Administrator rights."); } + } - return (int)processHandle; - } + return (int)processHandle; + } - public override bool IsGamePaused() - { - int processHandle = GetProcessHandle(false); - if (processHandle < 0) - return false; + public override bool IsGamePaused() + { + int processHandle = GetProcessHandle(false); + if (processHandle < 0) + return false; - int bytesReadOrWritten = 0; - byte[] pausePointerBuffer = new byte[4]; + int bytesReadOrWritten = 0; + byte[] pausePointerBuffer = new byte[4]; - Memory.ReadProcessMemory(processHandle, PausedStatePointer, pausePointerBuffer, pausePointerBuffer.Length, ref bytesReadOrWritten); + Memory.ReadProcessMemory(processHandle, PausedStatePointer, pausePointerBuffer, pausePointerBuffer.Length, + ref bytesReadOrWritten); - return BitConverter.ToInt32(pausePointerBuffer, 0) == 1; - } + return BitConverter.ToInt32(pausePointerBuffer, 0) == 1; + } - public override bool IsGameFocused() - { - const int nChars = 256; + public override bool IsGameFocused() + { + const int nChars = 256; - StringBuilder buff = new StringBuilder(nChars); + StringBuilder buff = new StringBuilder(nChars); - IntPtr handle = Memory.GetForegroundWindow(); + IntPtr handle = Memory.GetForegroundWindow(); - if (Memory.GetWindowText(handle, buff, nChars) <= 0) - return false; + if (Memory.GetWindowText(handle, buff, nChars) <= 0) + return false; - return buff.ToString() == WindowName; - } + return buff.ToString() == WindowName; + } - public override void ReloadLevel() - { - base.ReloadLevel(); + public override void ReloadLevel() + { + base.ReloadLevel(); int processHandle = GetProcessHandle(); - int bytesReadOrWritten = 0; + int bytesReadOrWritten = 0; - byte[] currentBufferLevelName = new byte[1]; - Memory.ReadProcessMemory(processHandle, LevelNamePointer, currentBufferLevelName, currentBufferLevelName.Length, ref bytesReadOrWritten); + byte[] currentBufferLevelName = new byte[1]; + Memory.ReadProcessMemory(processHandle, LevelNamePointer, currentBufferLevelName, + currentBufferLevelName.Length, ref bytesReadOrWritten); - if (currentBufferLevelName[0] == 0) return; + if (currentBufferLevelName[0] == 0) return; + + WriteEngineMode(6); + } - var buffer = new byte[] {6}; + public override void LoadOffsetLevel(int offset) + { + int processHandle = GetProcessHandle(); + if (processHandle < 0) + return; - Memory.WriteProcessMemory(processHandle, EngineModePointer, buffer, buffer.Length, ref bytesReadOrWritten); + string levelName = CurrentLevel; + var lvls = Levels.ToList(); + int currentIndex = lvls.FindIndex(x => + string.Equals(x.FileName, levelName, StringComparison.CurrentCultureIgnoreCase)); - } + if (currentIndex < 0) + return; - public override void LoadOffsetLevel(int offset) - { - int processHandle = GetProcessHandle(); - if (processHandle < 0) - return; + int newIndex = currentIndex + offset; - string levelName = CurrentLevel; - var lvls = Levels.ToList(); - int currentIndex = lvls.FindIndex(x => string.Equals(x.FileName, levelName, StringComparison.CurrentCultureIgnoreCase)); + if (newIndex < 0) + newIndex = lvls.Count - 1; - if (currentIndex < 0) - return; + if (newIndex >= lvls.Count) + newIndex = 0; - int newIndex = currentIndex + offset; + string levelToLoad = lvls[newIndex].FileName; - if (newIndex < 0) - newIndex = lvls.Count - 1; + CurrentLevel = levelToLoad; + } - if (newIndex >= lvls.Count) - newIndex = 0; + public override bool ReadGhostMode() + { + var processHandle = GetProcessHandle(); + if (processHandle < 0) + return false; - string levelToLoad = lvls[newIndex].FileName; + var buffer = new byte[1]; - CurrentLevel = levelToLoad; - } + var bytesReadOrWritten = 0; + Memory.ReadProcessMemory(processHandle, GhostModePointer, buffer, 1, ref bytesReadOrWritten); + return BitConverter.ToBoolean(buffer, 0); + } - public void WriteGhostMode(bool enable) - { - var processHandle = GetProcessHandle(); - if (processHandle < 0) - return; + public override void WriteGhostMode(bool enable) + { + var processHandle = GetProcessHandle(); + if (processHandle < 0) + return; - var buffer = BitConverter.GetBytes(enable ? 1 : 0); + var buffer = BitConverter.GetBytes(enable ? 1 : 0); - var bytesReadOrWritten = 0; - Memory.WriteProcessMemory(processHandle, GhostModePointer, buffer, 1, ref bytesReadOrWritten); - } + var bytesReadOrWritten = 0; + Memory.WriteProcessMemory(processHandle, GhostModePointer, buffer, 1, ref bytesReadOrWritten); + } #endregion } -} +} \ No newline at end of file diff --git a/OpenSpaceToolbox/Helpers/Memory.cs b/OpenSpaceToolbox/Helpers/Memory.cs index 59061b8..ec8da3f 100644 --- a/OpenSpaceToolbox/Helpers/Memory.cs +++ b/OpenSpaceToolbox/Helpers/Memory.cs @@ -28,6 +28,8 @@ public static class Memory public static int GetPointerPath(int processHandle, int baseAddress, params int[] offsets) { + if (offsets == null || offsets.Length == 0) return baseAddress; + int currentAddress = baseAddress; int bytesReadOrWritten = 0; @@ -35,15 +37,13 @@ public static int GetPointerPath(int processHandle, int baseAddress, params int[ ReadProcessMemory(processHandle, currentAddress, buffer, buffer.Length, ref bytesReadOrWritten); currentAddress = BitConverter.ToInt32(buffer, 0); - foreach (int offset in offsets) - { - if (offset == offsets.Last()) - { + for (var index = 0; index < offsets.Length; index++) { + var offset = offsets[index]; + if (index == offsets.Length-1) { currentAddress += offset; - } - else - { - ReadProcessMemory(processHandle, currentAddress + offset, buffer, buffer.Length, ref bytesReadOrWritten); + } else { + ReadProcessMemory(processHandle, currentAddress + offset, buffer, buffer.Length, + ref bytesReadOrWritten); currentAddress = BitConverter.ToInt32(buffer, 0); } } diff --git a/OpenSpaceToolbox/OpenSpaceToolbox.csproj b/OpenSpaceToolbox/OpenSpaceToolbox.csproj index 5b230cf..d60a85d 100644 --- a/OpenSpaceToolbox/OpenSpaceToolbox.csproj +++ b/OpenSpaceToolbox/OpenSpaceToolbox.csproj @@ -98,6 +98,7 @@ +