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 @@
+