From d5d9e27ccaf4f684986a72dd1961676fa7d3e930 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 22 Dec 2021 21:32:09 +0100 Subject: [PATCH 1/2] Added elevators (dvar controlled) --- src/client/game/dvars.cpp | 2 ++ src/client/game/dvars.hpp | 2 ++ src/client/game/structs.hpp | 19 ++++++++++++++++++- src/client/game/symbols.hpp | 8 +++++++- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index e2c31f6e..27c65c95 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -21,6 +21,8 @@ namespace dvars game::dvar_t* cg_legacyCrashHandling; + game::dvar_t* g_enableElevators = nullptr; + std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain) { if (domain.vector.min == -FLT_MAX) diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index f65b21e5..6d9f8614 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -22,6 +22,8 @@ namespace dvars extern game::dvar_t* cg_legacyCrashHandling; + extern game::dvar_t* g_enableElevators; + extern std::vector dvar_list; std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain); diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 3eaf0d67..a839e160 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -915,7 +915,24 @@ namespace game uint64_t streams[4]; const char* name; }; - + + struct Bounds + { + vec3_t midPoint; + vec3_t halfSize; + }; + + struct pmove_t + { + }; + + struct trace_t + { + char __pad0[0x29]; + bool allsolid; // Confirmed in CM_PositionTestCapsuleInTriangle + bool startsolid; // Confirmed in PM_JitterPoint + }; + namespace hks { struct GenericChunkHeader diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index fea2f668..9b66eba1 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -45,7 +45,8 @@ namespace game Dvar_RegisterString{0x618170}; WEAK symbol Dvar_RegisterVec4{0x6185F0}; - WEAK symbol Dvar_ValueToString{0x61B8F0}; + WEAK symbol Dvar_DisplayableValue{0x618EA0}; + WEAK symbol Dvar_ValueToString{0x61B8F0}; WEAK symbol Dvar_SetCommand{0x61A5C0}; WEAK symbol Dvar_SetFromStringFromSource{0x61A910}; @@ -122,6 +123,11 @@ namespace game WEAK symbol UI_SafeTranslateString{0x5A2930}; WEAK symbol UI_PlayLocalSoundAlias{0x606080}; + WEAK symbol PM_playerTrace{0x68F0A0}; + WEAK symbol PM_trace{0x68F1D0}; + WEAK symbol longjmp{0x89EED0}; WEAK symbol _setjmp{0x8EC2E0}; From 8deae532deccb9ce8c4fdda0d28351f4e6cd04f3 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 22 Dec 2021 21:36:55 +0100 Subject: [PATCH 2/2] Added actual file --- src/client/component/gameplay.cpp | 72 +++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/client/component/gameplay.cpp diff --git a/src/client/component/gameplay.cpp b/src/client/component/gameplay.cpp new file mode 100644 index 00000000..7c054bda --- /dev/null +++ b/src/client/component/gameplay.cpp @@ -0,0 +1,72 @@ +#include +#include "loader/component_loader.hpp" + +#include "game/game.hpp" +#include "game/dvars.hpp" + +#include + +namespace gameplay +{ + namespace + { + utils::hook::detour pm_player_trace_hook; + + void pm_player_trace_stub(game::pmove_t* pm, game::trace_t* trace, const float* f3, + const float* f4, const game::Bounds* bounds, int a6, int a7) + { + pm_player_trace_hook.invoke(pm, trace, f3, f4, bounds, a6, a7); + + // By setting startsolid to false we allow the player to clip through solid objects above their head + if (dvars::g_enableElevators->current.enabled) + { + trace->startsolid = false; + } + } + + void pm_trace_stub(utils::hook::assembler& a) + { + const auto stand = a.newLabel(); + const auto allsolid = a.newLabel(); + + a.call(rsi); // Game code + + a.push(rax); + + a.mov(rax, qword_ptr(reinterpret_cast(&dvars::g_enableElevators))); + a.mov(al, byte_ptr(rax, 0x10)); + a.cmp(al, 1); + + a.pop(rax); + + a.jz(stand); // Always stand up + + a.cmp(byte_ptr(rsp, 0x89), 0); // Game code trace[0].allsolid == false + a.jnz(allsolid); + + a.bind(stand); + a.jmp(0x6878CD_b); + + a.bind(allsolid); + a.jmp(0x6878D4_b); + } + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + dvars::g_enableElevators = dvars::register_bool("g_enableElevators", false, + game::DvarFlags::DVAR_FLAG_NONE, true); + + // Influence PM_JitterPoint code flow so the trace->startsolid checks are 'ignored' + pm_player_trace_hook.create(0x068F0A0_b, &pm_player_trace_stub); + + // If g_enableElevators is 1 the 'ducked' flag will always be removed from the player state + utils::hook::jump(0x6878C1_b, utils::hook::assemble(pm_trace_stub), true); + } + }; +} + +REGISTER_COMPONENT(gameplay::component)