#include "CharacterUnmanaged.h" #include using namespace NosSmoothCore; const BYTE WALK_OBJECT_PATTERN[] = { 0x33, 0xC9, 0x8B, 0x55, 0xFC, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 }; const BYTE WALK_FUNCTION_PATTERN[] = { 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xEC, 0x53, 0x56, 0x57, 0x66, 0x89, 0x4D, 0xFA }; LPCSTR WALK_OBJECT_MASK = "xxxxxx????x????"; LPCSTR WALK_FUNCTION_MASK = "xxxxxxxxxxxxx"; void CharacterWalkDetourIn() { DWORD position = 0; __asm { pushad pushfd mov position, edx } bool isAccepted = CharacterUnmanaged::GetInstance()->ExecuteWalkCallback(position); __asm { popfd popad } if (isAccepted) { CharacterUnmanaged::GetInstance()->Walk(position); } } // Detour entrypoint // declspec naked to not mess up the stack void __declspec(naked) CharacterWalkDetour() { unsigned int returnPush; __asm { pop eax pop ebx mov returnPush, eax // we have to push this value on the stack before returning } CharacterWalkDetourIn(); __asm { push returnPush ret } } CharacterUnmanaged::CharacterUnmanaged() { } void CharacterUnmanaged::Setup(ModuleHook moduleHook) { auto walkFunction = moduleHook.FindPattern(WALK_FUNCTION_PATTERN, WALK_FUNCTION_MASK); auto walkObject = *(unsigned int*)(moduleHook.FindPattern(WALK_OBJECT_PATTERN, WALK_OBJECT_MASK) + 0x6); if (walkFunction == 0) { throw "Could not find walk function."; } if (walkObject == 0) { throw "Could not find player object."; } _walkFunctionAddress = walkFunction; _characterObjectAddress = walkObject; } void CharacterUnmanaged::SetWalkCallback(NativeWalkCallback walkCallback) { _walkCallback = walkCallback; DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour); DetourTransactionCommit(); } void CharacterUnmanaged::Walk(DWORD position) { unsigned int walkFunction = _walkFunctionAddress; unsigned int characterObject = _characterObjectAddress; __asm { push 1 xor ecx, ecx mov edx, position mov eax, dword ptr ds : [characterObject] mov eax, dword ptr ds : [eax] call walkFunction } } void CharacterUnmanaged::ResetHooks() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour); DetourTransactionCommit(); } bool CharacterUnmanaged::ExecuteWalkCallback(const DWORD position) { if (_walkCallback != nullptr) { return _walkCallback(position); } return true; }