private static void OnTick(int counter, EventArgs args) { if (processHandle == IntPtr.Zero) //if we still don't have a handle to the process { var wndHnd = Memory.FindWindowClassName("UnityWndClass"); //try finding the window of the process (check if it's spawned and loaded) if (wndHnd != IntPtr.Zero) //if it exists { var calcPid = Memory.GetPIDFromHWND(wndHnd); //get the PID of that same process if (calcPid > 0) //if we got the PID { processHandle = Memory.OpenProcess(PROCESS_ALL_ACCESS, calcPid); //get full access to the process so we can use it later if (processHandle != IntPtr.Zero) { //if we got access to the game, check if it's x64 bit, this is needed when reading pointers, since their size is 4 for x86 and 8 for x64 isWow64Process = Memory.IsProcess64Bit(processHandle); //here you can scan for signatures and stuff, it happens only once on "attach" } } } } else //else we have a handle, lets check if we should close it, or use it { var wndHnd = Memory.FindWindowClassName("UnityWndClass"); if (wndHnd != IntPtr.Zero) //window still exists, so handle should be valid? let's keep using it { //the lines of code below execute every 33ms outside of the renderer thread, heavy code can be put here if it's not render dependant gameProcessExists = true; isGameOnTop = Renderer.IsGameOnTop(wndHnd); isOverlayOnTop = Overlay.IsOnTop(); if (GameAssembly_dll == IntPtr.Zero) { GameAssembly_dll = Memory.GetModule(processHandle, "GameAssembly.dll"); } //since we're not drawing, the rest of the code can be put here. if (characterPtr == IntPtr.Zero) { characterPtr = Memory.FindSignatureBase(processHandle, IntPtr.Zero, IntPtr.Zero, "00 00 18 41 00 00 18 41 00 00 E0 40 CD CC 4C 3E 00 00 A0 40 00 00 E0 40 00 00 00 41 00 00 00 41 00"); //just to get the base of the character allocation data //9.50 9.50 7.00 0.20 5.00 7.00 8.00 or ... 41180000 41180000 40E00000 3E4CCCCD 40A00000 40E00000 41000000 if (characterPtr != IntPtr.Zero) { Console.WriteLine($"FOUND Character Base Ptr: {characterPtr.ToString("X")}"); } else { Console.WriteLine("FAILED TO FIND Character Base Ptr :("); } } else { //we are in game and got char ptr ... continue with menu modifications every tick IntPtr timeToRunNextCharacterControllerDataCheckPTR = SDKUtil.ReadPointerChain(processHandle, (IntPtr)(GameAssembly_dll.ToInt64() + 0x02BC6108), isWow64Process, 0xB8, 0x0, 0xB8, 0x10, 0x30, 0x1C8); //Console.WriteLine(timeToRunNextCharacterControllerDataCheck.ToString("X")); if (timeToRunNextCharacterControllerDataCheckPTR != IntPtr.Zero) { var timeToRunNextCharacterControllerDataCheck = Memory.ReadFloat(processHandle, (IntPtr)timeToRunNextCharacterControllerDataCheckPTR.ToInt64() + 0x10); if ((timeToRunNextCharacterControllerDataCheck > 0) && (timeToRunNextCharacterControllerDataCheck < 100000000.0f)) { Memory.WriteFloat(processHandle, (IntPtr)(timeToRunNextCharacterControllerDataCheckPTR.ToInt64() + 0x10), 100000000.0f); } else { var doublecheck = Memory.ReadFloat(processHandle, (IntPtr)timeToRunNextCharacterControllerDataCheckPTR.ToInt64() + 0x10); if (doublecheck == 100000000.0f) { //DelayAction.Queue(() => writeCheatosz(processHandle, characterPtr), 5000.0f); writeCheatos(processHandle, characterPtr, false); } } } else { writeCheatos(processHandle, characterPtr, true); } } } else //else most likely the process is dead, clean up { Memory.CloseHandle(processHandle); //close the handle to avoid leaks processHandle = IntPtr.Zero; //set it like this just in case for C# logic gameProcessExists = false; characterPtr = IntPtr.Zero; GameAssembly_dll = IntPtr.Zero; } } }