From db0aa13d591113c5efcbee66ccc2f088f50acc37 Mon Sep 17 00:00:00 2001 From: idapro92 Date: Thu, 16 Apr 2026 23:07:53 -0400 Subject: [PATCH 1/2] Added ngl and iw2 support for project velocity --- codxe.vcxproj | 10 +- .../iw2/mp/components/project_velocity.cpp | 94 +++++++++++++++++++ src/game/iw2/mp/components/project_velocity.h | 31 ++++++ src/game/iw2/mp/main.cpp | 2 + .../ngl/mp/components/project_velocity.cpp | 70 ++++++++++++++ src/game/ngl/mp/components/project_velocity.h | 31 ++++++ src/game/ngl/mp/main.cpp | 24 +++++ src/game/ngl/mp/main.h | 17 ++++ src/pch.h | 2 + src/plugin_manager.cpp | 8 ++ src/version.h | 2 +- 11 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 src/game/iw2/mp/components/project_velocity.cpp create mode 100644 src/game/iw2/mp/components/project_velocity.h create mode 100644 src/game/ngl/mp/components/project_velocity.cpp create mode 100644 src/game/ngl/mp/components/project_velocity.h create mode 100644 src/game/ngl/mp/main.cpp create mode 100644 src/game/ngl/mp/main.h diff --git a/codxe.vcxproj b/codxe.vcxproj index 01a54a1..08e2351 100644 --- a/codxe.vcxproj +++ b/codxe.vcxproj @@ -80,9 +80,13 @@ + + + + @@ -148,7 +152,7 @@ - + @@ -184,11 +188,15 @@ + + + + diff --git a/src/game/iw2/mp/components/project_velocity.cpp b/src/game/iw2/mp/components/project_velocity.cpp new file mode 100644 index 0000000..83e6cec --- /dev/null +++ b/src/game/iw2/mp/components/project_velocity.cpp @@ -0,0 +1,94 @@ +#include "pch.h" +#include "project_velocity.h" +#include + +namespace iw2 { +namespace mp { + +uint32_t NOP_INST = 0x60000000; + +// Logic for the math +void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) +{ + const float EPSILON = 0.001f; + float normalZ = normal[2]; + float speedXY = (in[0] * in[0]) + (in[1] * in[1]); + + if (normalZ < EPSILON || speedXY <= 0.0f) { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; + return; + } + + float dotNormalXY = (in[0] * normal[0]) + (in[1] * normal[1]); + float projRatio = -dotNormalXY / normalZ; + float projSq = (in[2] * in[2]) + speedXY; + float divisor = speedXY + (projRatio * projRatio); + + if (divisor > 0.0f) { + float scale = sqrtf(projSq / divisor); + if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = projRatio * scale; + return; + } + } + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; +} + +static uint32_t make_bl(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li | 1u; +} + +void project_velocity::install_patch() { + uint32_t funcAddr = (uint32_t)(void*)&PM_ProjectVelocity; + + // Explicitly cast the value to (uint32_t) to ensure the compiler + // treats it as a raw bit pattern before assigning it to the volatile pointer. + *(volatile uint32_t *)PV_Config::CallToStubAddr = (uint32_t)NOP_INST; + + volatile uint32_t* stub = (volatile uint32_t*)PV_Config::StubAddr; + uint16_t hi = (uint16_t)((funcAddr >> 16) & 0xFFFF); + uint16_t lo = (uint16_t)(funcAddr & 0xFFFF); + + stub[0] = 0x3D800000 | hi; + stub[1] = 0x618C0000 | lo; + stub[2] = 0x7D8903A6; + stub[3] = 0x4E800420; + + *(volatile uint32_t*)PV_Config::PatchAddr = make_bl(PV_Config::PatchAddr, PV_Config::StubAddr); +} + +void remove_clip_velocity(int count) +{ + // The header is 12 bytes. Since we are using uint32_t (4 bytes), + // we move back exactly 3 "indices". + const int headerOpCount = 3; + + volatile uint32_t* patchBase = reinterpret_cast(PV_Config::PatchAddr); + + // 1. Write the 12-byte header BEFORE the patch address + // Pointer arithmetic: patchBase - 3 is PatchAddr - 0xC (12 bytes) + volatile uint32_t* headerStart = patchBase - headerOpCount; + + headerStart[0] = 0x7FE3FB78; //r31->r3 + headerStart[1] = 0x388100A4; //sp+A4->r4 + headerStart[2] = 0x7FE5FB78; //r31->r5 + + // 2. NOP out the instructions starting AT the patch address + for (int i = 0; i < count; i++) + { + patchBase[i] = NOP_INST; + } +} + +project_velocity::project_velocity() { + remove_clip_velocity(18); + install_patch(); +} + +project_velocity::~project_velocity() {} + +} // namespace mp +} // namespace iw2 \ No newline at end of file diff --git a/src/game/iw2/mp/components/project_velocity.h b/src/game/iw2/mp/components/project_velocity.h new file mode 100644 index 0000000..1d3d616 --- /dev/null +++ b/src/game/iw2/mp/components/project_velocity.h @@ -0,0 +1,31 @@ +#pragma once +#include + +namespace iw2 { +namespace mp { + + // Move Config here. In older C++, using an anonymous enum is a + // "clean" way to define global constants without storage class issues. + namespace PV_Config { + static const uint32_t PatchAddr = 0x8248B178; // Location of clip_velocity (or where project_velocity should be called) + static const uint32_t StubAddr = 0x824550B8; // Location of unused function in XEX (find one) + static const uint32_t CallToStubAddr = 0x82455F74; // Location of calls to unused function + } + + typedef float vec3_t[3]; + + class project_velocity : public Module { + public: + project_velocity(); + virtual ~project_velocity(); + + private: + void install_patch(); + project_velocity(const project_velocity&); + project_velocity& operator=(const project_velocity&); + }; + + void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out); + +} // namespace mp +} // namespace iw2 \ No newline at end of file diff --git a/src/game/iw2/mp/main.cpp b/src/game/iw2/mp/main.cpp index 827f597..89a8b2f 100644 --- a/src/game/iw2/mp/main.cpp +++ b/src/game/iw2/mp/main.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "components/g_scr_main.h" #include "components/scr_parser.h" +#include "components/project_velocity.h" #include "main.h" namespace iw2 @@ -14,6 +15,7 @@ IW2_MP_Plugin::IW2_MP_Plugin() RegisterModule(new Config()); RegisterModule(new g_scr_main()); RegisterModule(new scr_parser()); + RegisterModule(new project_velocity()); } IW2_MP_Plugin::~IW2_MP_Plugin() diff --git a/src/game/ngl/mp/components/project_velocity.cpp b/src/game/ngl/mp/components/project_velocity.cpp new file mode 100644 index 0000000..c00248d --- /dev/null +++ b/src/game/ngl/mp/components/project_velocity.cpp @@ -0,0 +1,70 @@ +#include "pch.h" +#include "project_velocity.h" +#include + +namespace ngl { +namespace mp { + +// Logic for the math +void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) +{ + const float EPSILON = 0.001f; + float normalZ = normal[2]; + float speedXY = (in[0] * in[0]) + (in[1] * in[1]); + + if (normalZ < EPSILON || speedXY <= 0.0f) { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; + return; + } + + float dotNormalXY = (in[0] * normal[0]) + (in[1] * normal[1]); + float projRatio = -dotNormalXY / normalZ; + float projSq = (in[2] * in[2]) + speedXY; + float divisor = speedXY + (projRatio * projRatio); + + if (divisor > 0.0f) { + float scale = sqrtf(projSq / divisor); + if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = projRatio * scale; + return; + } + } + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; +} + +static uint32_t make_bl(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li | 1u; +} + +void project_velocity::install_patch() { + uint32_t funcAddr = (uint32_t)(void*)&PM_ProjectVelocity; + + uint32_t NOP_INST = 0x60000000; + + // Explicitly cast the value to (uint32_t) to ensure the compiler + // treats it as a raw bit pattern before assigning it to the volatile pointer. + *(volatile uint32_t *)PV_Config::CallToStubAddr = (uint32_t)NOP_INST; + + volatile uint32_t* stub = (volatile uint32_t*)PV_Config::StubAddr; + uint16_t hi = (uint16_t)((funcAddr >> 16) & 0xFFFF); + uint16_t lo = (uint16_t)(funcAddr & 0xFFFF); + + stub[0] = 0x3D800000 | hi; + stub[1] = 0x618C0000 | lo; + stub[2] = 0x7D8903A6; + stub[3] = 0x4E800420; + + *(volatile uint32_t*)PV_Config::PatchAddr = make_bl(PV_Config::PatchAddr, PV_Config::StubAddr); +} + +project_velocity::project_velocity() { + install_patch(); +} + +project_velocity::~project_velocity() {} + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/components/project_velocity.h b/src/game/ngl/mp/components/project_velocity.h new file mode 100644 index 0000000..62c397d --- /dev/null +++ b/src/game/ngl/mp/components/project_velocity.h @@ -0,0 +1,31 @@ +#pragma once +#include + +namespace ngl { +namespace mp { + + // Move PV_Config here. In older C++, using an anonymous enum is a + // "clean" way to define global constants without storage class issues. + namespace PV_Config { + static const uint32_t PatchAddr = 0x8246E1E0; // Location of clip_velocity (or where project_velocity should be called) + static const uint32_t StubAddr = 0x8244C1C8; // Location of unused function in XEX (find one) + static const uint32_t CallToStubAddr = 0x82466704; // Location of calls to unused function + } + + typedef float vec3_t[3]; + + class project_velocity : public Module { + public: + project_velocity(); + virtual ~project_velocity(); + + private: + void install_patch(); + project_velocity(const project_velocity&); + project_velocity& operator=(const project_velocity&); + }; + + void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out); + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/main.cpp b/src/game/ngl/mp/main.cpp new file mode 100644 index 0000000..25fbf3b --- /dev/null +++ b/src/game/ngl/mp/main.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "main.h" +#include "components/project_velocity.h" + +namespace ngl +{ +namespace mp +{ + +NGL_MP_Plugin::NGL_MP_Plugin() +{ + DbgPrint("NGL MP Plugin initialized\n"); + + //install_patch(); + RegisterModule(new project_velocity()); +} + +NGL_MP_Plugin::~NGL_MP_Plugin() +{ + DbgPrint("NGL MP Plugin shutting down\n"); +} + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/main.h b/src/game/ngl/mp/main.h new file mode 100644 index 0000000..dbab00c --- /dev/null +++ b/src/game/ngl/mp/main.h @@ -0,0 +1,17 @@ +#pragma once + +#include "plugin.h" + +namespace ngl +{ +namespace mp +{ +class NGL_MP_Plugin : public Plugin +{ + + public: + NGL_MP_Plugin(); + ~NGL_MP_Plugin(); +}; +} // namespace mp +} // namespace ngl diff --git a/src/pch.h b/src/pch.h index c420dc1..f07dab0 100644 --- a/src/pch.h +++ b/src/pch.h @@ -44,6 +44,8 @@ #include "common/branding.h" #include "common/config.h" +#include "game/ngl/mp/main.h" + // IW2-specific includes #include "game/iw2/sp/main.h" #include "game/iw2/sp/structs.h" diff --git a/src/plugin_manager.cpp b/src/plugin_manager.cpp index 49123da..caa49db 100644 --- a/src/plugin_manager.cpp +++ b/src/plugin_manager.cpp @@ -146,6 +146,14 @@ const GameInfo GAME_INFO[] = { "Call of Duty: Modern Warfare 3 MP Title Update #24", &CreatePlugin, }, + { + 0x415607E1, + 0x45B56A5C,// Mon Jan 22 20 : 52 : 28 2007 + "codmp_xenonf.xex", + "NGL MP TU3", + "Call of Duty: 3 Title Update #3", + &CreatePlugin, + }, }; const GameInfo *FindGameInfo(DWORD title_id, DWORD timestamp) diff --git a/src/version.h b/src/version.h index 2078852..2e59f06 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ // Auto-generated version header #pragma once -#define BUILD_NUMBER 0 +#define BUILD_NUMBER 249 From 1ced790008bd11d734e0c6ba58e1e0a57f9fcf1e Mon Sep 17 00:00:00 2001 From: idapro92 Date: Fri, 17 Apr 2026 22:39:16 -0400 Subject: [PATCH 2/2] Refactor pv-support to use Detour --- .../iw2/mp/components/project_velocity.cpp | 87 ++++++++++--------- src/game/iw2/mp/components/project_velocity.h | 18 ++-- .../ngl/mp/components/project_velocity.cpp | 46 ++++++---- src/game/ngl/mp/components/project_velocity.h | 18 ++-- 4 files changed, 91 insertions(+), 78 deletions(-) diff --git a/src/game/iw2/mp/components/project_velocity.cpp b/src/game/iw2/mp/components/project_velocity.cpp index 83e6cec..766046d 100644 --- a/src/game/iw2/mp/components/project_velocity.cpp +++ b/src/game/iw2/mp/components/project_velocity.cpp @@ -5,10 +5,13 @@ namespace iw2 { namespace mp { -uint32_t NOP_INST = 0x60000000; +// Global detour object +Detour PM_ProjectVelocity_Detour; -// Logic for the math -void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) +const uint32_t NOP_INST = 0x60000000; + +// The Hook function that the Detour will point to +void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out) { const float EPSILON = 0.001f; float normalZ = normal[2]; @@ -26,6 +29,7 @@ void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) if (divisor > 0.0f) { float scale = sqrtf(projSq / divisor); + // FIXED: Added logical OR operators if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { out[0] = in[0] * scale; out[1] = in[1] * scale; @@ -33,62 +37,61 @@ void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) return; } } + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } +// Simple helper to build the branch-link (bl) instruction static uint32_t make_bl(uint32_t current, uint32_t target) { uint32_t li = (target - current) & 0x03FFFFFC; return (18u << 26) | li | 1u; } -void project_velocity::install_patch() { - uint32_t funcAddr = (uint32_t)(void*)&PM_ProjectVelocity; - - // Explicitly cast the value to (uint32_t) to ensure the compiler - // treats it as a raw bit pattern before assigning it to the volatile pointer. - *(volatile uint32_t *)PV_Config::CallToStubAddr = (uint32_t)NOP_INST; - - volatile uint32_t* stub = (volatile uint32_t*)PV_Config::StubAddr; - uint16_t hi = (uint16_t)((funcAddr >> 16) & 0xFFFF); - uint16_t lo = (uint16_t)(funcAddr & 0xFFFF); - - stub[0] = 0x3D800000 | hi; - stub[1] = 0x618C0000 | lo; - stub[2] = 0x7D8903A6; - stub[3] = 0x4E800420; - - *(volatile uint32_t*)PV_Config::PatchAddr = make_bl(PV_Config::PatchAddr, PV_Config::StubAddr); +// Simple helper to build the unconditional branch (b) instruction +static uint32_t make_b(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li; } -void remove_clip_velocity(int count) -{ - // The header is 12 bytes. Since we are using uint32_t (4 bytes), - // we move back exactly 3 "indices". - const int headerOpCount = 3; - - volatile uint32_t* patchBase = reinterpret_cast(PV_Config::PatchAddr); - - // 1. Write the 12-byte header BEFORE the patch address - // Pointer arithmetic: patchBase - 3 is PatchAddr - 0xC (12 bytes) - volatile uint32_t* headerStart = patchBase - headerOpCount; - - headerStart[0] = 0x7FE3FB78; //r31->r3 - headerStart[1] = 0x388100A4; //sp+A4->r4 - headerStart[2] = 0x7FE5FB78; //r31->r5 - - // 2. NOP out the instructions starting AT the patch address - for (int i = 0; i < count; i++) - { - patchBase[i] = NOP_INST; +void project_velocity::install_patch() { + // 1. NOP out the original call to the dummy function + *(volatile uint32_t*)PV_Config::CallToDummyAddr = NOP_INST; + + // 2. Initialize the Detour on the DummyAddr + // This redirects any call to DummyAddr to our PM_ProjectVelocity_Hook + PM_ProjectVelocity_Detour = Detour(reinterpret_cast(PV_Config::DummyAddr), reinterpret_cast(PM_ProjectVelocity_Hook)); + PM_ProjectVelocity_Detour.Install(); + + // 3. Write the inline argument setup and call at PatchAddr + volatile uint32_t* patch = (volatile uint32_t*)PV_Config::PatchAddr; + + // Setup Arguments + patch[0] = 0x7FE3FB78; // mr r3, r31 + patch[1] = 0x388100A4; // addi r4, r1, 0xA4 + patch[2] = 0x7FE5FB78; // mr r5, r31 + + // Call the hooked DummyAddr (where our Detour is waiting) + uint32_t blAddr = PV_Config::PatchAddr + (3 * 4); + patch[3] = make_bl(blAddr, PV_Config::DummyAddr); + + // Jump past the rest of the original logic (18 instructions total) + uint32_t bAddr = PV_Config::PatchAddr + (4 * 4); + uint32_t targetAddr = PV_Config::PatchAddr + (18 * 4); + patch[4] = make_b(bAddr, targetAddr); + + // Clear the remaining original instructions + for (int i = 5; i < 18; i++) { + patch[i] = NOP_INST; } } project_velocity::project_velocity() { - remove_clip_velocity(18); install_patch(); } -project_velocity::~project_velocity() {} +project_velocity::~project_velocity() { + PM_ProjectVelocity_Detour.Remove(); +} } // namespace mp } // namespace iw2 \ No newline at end of file diff --git a/src/game/iw2/mp/components/project_velocity.h b/src/game/iw2/mp/components/project_velocity.h index 1d3d616..15c7274 100644 --- a/src/game/iw2/mp/components/project_velocity.h +++ b/src/game/iw2/mp/components/project_velocity.h @@ -1,18 +1,20 @@ #pragma once -#include +#include "pch.h" namespace iw2 { namespace mp { - // Move Config here. In older C++, using an anonymous enum is a - // "clean" way to define global constants without storage class issues. + typedef float vec_t; + typedef vec_t vec3_t[3]; + namespace PV_Config { - static const uint32_t PatchAddr = 0x8248B178; // Location of clip_velocity (or where project_velocity should be called) - static const uint32_t StubAddr = 0x824550B8; // Location of unused function in XEX (find one) - static const uint32_t CallToStubAddr = 0x82455F74; // Location of calls to unused function + static const uint32_t PatchAddr = 0x8248B178; // Location where we should call our dummy function + static const uint32_t DummyAddr = 0x824550B8; // In COD2 there is no call to clip_velocity so we will use a dummy function address (and hook to it) + static const uint32_t CallToDummyAddr = 0x82455F74; // Location of calls to unused function } - typedef float vec3_t[3]; + // Forward declaration using float* to avoid array-size decay errors + void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out); class project_velocity : public Module { public: @@ -25,7 +27,5 @@ namespace mp { project_velocity& operator=(const project_velocity&); }; - void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out); - } // namespace mp } // namespace iw2 \ No newline at end of file diff --git a/src/game/ngl/mp/components/project_velocity.cpp b/src/game/ngl/mp/components/project_velocity.cpp index c00248d..5439219 100644 --- a/src/game/ngl/mp/components/project_velocity.cpp +++ b/src/game/ngl/mp/components/project_velocity.cpp @@ -5,8 +5,13 @@ namespace ngl { namespace mp { -// Logic for the math -void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) +// Global detour object +Detour PM_ProjectVelocity_Detour; + +const uint32_t NOP_INST = 0x60000000; + +// The Hook function that the Detour will point to +void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out) { const float EPSILON = 0.001f; float normalZ = normal[2]; @@ -24,6 +29,7 @@ void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) if (divisor > 0.0f) { float scale = sqrtf(projSq / divisor); + // FIXED: Added logical OR operators if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { out[0] = in[0] * scale; out[1] = in[1] * scale; @@ -31,40 +37,44 @@ void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out) return; } } + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } +// Simple helper to build the branch-link (bl) instruction static uint32_t make_bl(uint32_t current, uint32_t target) { uint32_t li = (target - current) & 0x03FFFFFC; return (18u << 26) | li | 1u; } -void project_velocity::install_patch() { - uint32_t funcAddr = (uint32_t)(void*)&PM_ProjectVelocity; +// Simple helper to build the unconditional branch (b) instruction +//static uint32_t make_b(uint32_t current, uint32_t target) { +// uint32_t li = (target - current) & 0x03FFFFFC; +// return (18u << 26) | li; +//} - uint32_t NOP_INST = 0x60000000; - - // Explicitly cast the value to (uint32_t) to ensure the compiler - // treats it as a raw bit pattern before assigning it to the volatile pointer. - *(volatile uint32_t *)PV_Config::CallToStubAddr = (uint32_t)NOP_INST; +void project_velocity::install_patch() { + // 1. NOP out the original call to the dummy function + *(volatile uint32_t*)PV_Config::CallToDummyAddr = NOP_INST; - volatile uint32_t* stub = (volatile uint32_t*)PV_Config::StubAddr; - uint16_t hi = (uint16_t)((funcAddr >> 16) & 0xFFFF); - uint16_t lo = (uint16_t)(funcAddr & 0xFFFF); + // 2. Initialize the Detour on the DummyAddr + // This redirects any call to DummyAddr to our PM_ProjectVelocity_Hook + PM_ProjectVelocity_Detour = Detour(reinterpret_cast(PV_Config::DummyAddr), reinterpret_cast(PM_ProjectVelocity_Hook)); + PM_ProjectVelocity_Detour.Install(); - stub[0] = 0x3D800000 | hi; - stub[1] = 0x618C0000 | lo; - stub[2] = 0x7D8903A6; - stub[3] = 0x4E800420; + // 3. Write the inline argument setup and call at PatchAddr + volatile uint32_t* patch = (volatile uint32_t*)PV_Config::PatchAddr; - *(volatile uint32_t*)PV_Config::PatchAddr = make_bl(PV_Config::PatchAddr, PV_Config::StubAddr); + patch[0] = make_bl(PV_Config::PatchAddr, PV_Config::DummyAddr); } project_velocity::project_velocity() { install_patch(); } -project_velocity::~project_velocity() {} +project_velocity::~project_velocity() { + PM_ProjectVelocity_Detour.Remove(); +} } // namespace mp } // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/components/project_velocity.h b/src/game/ngl/mp/components/project_velocity.h index 62c397d..94e8fdf 100644 --- a/src/game/ngl/mp/components/project_velocity.h +++ b/src/game/ngl/mp/components/project_velocity.h @@ -1,18 +1,20 @@ #pragma once -#include +#include "pch.h" namespace ngl { namespace mp { - // Move PV_Config here. In older C++, using an anonymous enum is a - // "clean" way to define global constants without storage class issues. + typedef float vec_t; + typedef vec_t vec3_t[3]; + namespace PV_Config { - static const uint32_t PatchAddr = 0x8246E1E0; // Location of clip_velocity (or where project_velocity should be called) - static const uint32_t StubAddr = 0x8244C1C8; // Location of unused function in XEX (find one) - static const uint32_t CallToStubAddr = 0x82466704; // Location of calls to unused function + static const uint32_t PatchAddr = 0x8246E1E0; // Location where we should call our dummy function + static const uint32_t DummyAddr = 0x8244C1C8; // In COD2 there is no call to clip_velocity so we will use a dummy function address (and hook to it) + static const uint32_t CallToDummyAddr = 0x82466704; // Location of calls to unused function } - typedef float vec3_t[3]; + // Forward declaration using float* to avoid array-size decay errors + void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out); class project_velocity : public Module { public: @@ -25,7 +27,5 @@ namespace mp { project_velocity& operator=(const project_velocity&); }; - void PM_ProjectVelocity(vec3_t in, vec3_t normal, vec3_t out); - } // namespace mp } // namespace ngl \ No newline at end of file