From 7ed59798b0fd88d81cd013def592b14f009129c0 Mon Sep 17 00:00:00 2001 From: khang Date: Fri, 12 Jul 2024 14:27:05 -0400 Subject: [PATCH 1/4] Add bxt_ch_trigger_tp_landmark --- BunnymodXT/cvars.hpp | 3 +- BunnymodXT/modules/HwDLL.cpp | 1 + BunnymodXT/modules/ServerDLL.cpp | 101 ++++++++++++++++++++++++++++++- BunnymodXT/modules/ServerDLL.hpp | 5 ++ 4 files changed, 106 insertions(+), 4 deletions(-) diff --git a/BunnymodXT/cvars.hpp b/BunnymodXT/cvars.hpp index c218ecf9..6c1d0834 100644 --- a/BunnymodXT/cvars.hpp +++ b/BunnymodXT/cvars.hpp @@ -241,7 +241,8 @@ X(bxt_ch_trigger_tp_keeps_momentum, "0") \ X(bxt_ch_trigger_tp_keeps_momentum_velocity, "1") \ X(bxt_ch_trigger_tp_keeps_momentum_velocity_redirect, "0") \ - X(bxt_ch_trigger_tp_keeps_momentum_viewangles, "1") + X(bxt_ch_trigger_tp_keeps_momentum_viewangles, "1") \ + X(bxt_ch_trigger_tp_landmark, "0") class CVarWrapper { diff --git a/BunnymodXT/modules/HwDLL.cpp b/BunnymodXT/modules/HwDLL.cpp index a776233c..7f8dbd89 100644 --- a/BunnymodXT/modules/HwDLL.cpp +++ b/BunnymodXT/modules/HwDLL.cpp @@ -7672,6 +7672,7 @@ HOOK_DEF_3(HwDLL, int, __cdecl, SV_SpawnServer, int, bIsDemo, char*, server, cha if (ret) { Interprocess::WriteMapChange(CustomHud::GetTime(), server); lastLoadedMap = server; + ServerDLL::GetInstance().ClearTPLandmarks(); } if (insideHost_Loadgame_f) { diff --git a/BunnymodXT/modules/ServerDLL.cpp b/BunnymodXT/modules/ServerDLL.cpp index 9534da8a..39a6de70 100644 --- a/BunnymodXT/modules/ServerDLL.cpp +++ b/BunnymodXT/modules/ServerDLL.cpp @@ -114,6 +114,11 @@ extern "C" void __cdecl _ZN12CBaseTrigger13TeleportTouchEP11CBaseEntity(void* th { return ServerDLL::HOOKED_CBaseTrigger__TeleportTouch_Linux(thisptr, pOther); } + +extern "C" void __cdecl _Z16DispatchKeyValueP7edict_sP14KeyValueData_s(edict_t* pentKeyvalue, KeyValueData* pkvd) +{ + return ServerDLL::HOOKED_DispatchKeyValue(pentKeyvalue, pkvd); +} #endif void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* moduleBase, size_t moduleLength, bool needToIntercept) @@ -180,7 +185,8 @@ void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* m ORIG_CBaseEntity__IsInWorld, HOOKED_CBaseEntity__IsInWorld, ORIG_CBaseEntity__IsInWorld_Linux, HOOKED_CBaseEntity__IsInWorld_Linux, ORIG_CBaseTrigger__TeleportTouch, HOOKED_CBaseTrigger__TeleportTouch, - ORIG_CBaseTrigger__TeleportTouch_Linux, HOOKED_CBaseTrigger__TeleportTouch_Linux); + ORIG_CBaseTrigger__TeleportTouch_Linux, HOOKED_CBaseTrigger__TeleportTouch_Linux, + ORIG_DispatchKeyValue, HOOKED_DispatchKeyValue); } } @@ -237,7 +243,8 @@ void ServerDLL::Unhook() ORIG_CBaseEntity__IsInWorld, ORIG_CBaseEntity__IsInWorld_Linux, ORIG_CBaseTrigger__TeleportTouch, - ORIG_CBaseTrigger__TeleportTouch_Linux); + ORIG_CBaseTrigger__TeleportTouch_Linux, + ORIG_DispatchKeyValue); } Clear(); @@ -296,6 +303,7 @@ void ServerDLL::Clear() ORIG_CBaseEntity__FireBullets = nullptr; ORIG_DispatchSpawn = nullptr; ORIG_DispatchTouch = nullptr; + ORIG_DispatchKeyValue = nullptr; ORIG_CBaseEntity__FireBullets_Linux = nullptr; ORIG_CBaseEntity__FireBulletsPlayer = nullptr; ORIG_CBaseEntity__FireBulletsPlayer_Linux = nullptr; @@ -361,6 +369,8 @@ void ServerDLL::Clear() offm_fStamina = 0; offm_old_iAmmo = 0; offm_iPlayerSaveLock = 0; + + tpLandmarks.clear(); } bool ServerDLL::CanHook(const std::wstring& moduleFullName) @@ -1223,6 +1233,7 @@ void ServerDLL::FindStuff() ORIG_DispatchSpawn = reinterpret_cast<_DispatchSpawn>(MemUtils::GetSymbolAddress(m_Handle, "_Z13DispatchSpawnP7edict_s")); ORIG_DispatchTouch = reinterpret_cast<_DispatchTouch>(MemUtils::GetSymbolAddress(m_Handle, "_Z13DispatchTouchP7edict_sS0_")); + ORIG_DispatchKeyValue = reinterpret_cast<_DispatchKeyValue>(MemUtils::GetSymbolAddress(m_Handle, "_Z16DispatchKeyValueP7edict_sP14KeyValueData_s")); ORIG_ClientCommand = reinterpret_cast<_ClientCommand>(MemUtils::GetSymbolAddress(m_Handle, "_Z13ClientCommandP7edict_s")); ORIG_PlayerPostThink = reinterpret_cast<_PlayerPostThink>(MemUtils::GetSymbolAddress(m_Handle, "_Z15PlayerPostThinkP7edict_s")); ORIG_PM_Move = reinterpret_cast<_PM_Move>(MemUtils::GetSymbolAddress(m_Handle, "PM_Move")); @@ -1230,10 +1241,11 @@ void ServerDLL::FindStuff() ORIG_CmdStart = reinterpret_cast<_CmdStart>(MemUtils::GetSymbolAddress(m_Handle, "_Z8CmdStartPK7edict_sPK9usercmd_sj")); ORIG_CmdEnd = reinterpret_cast<_CmdEnd>(MemUtils::GetSymbolAddress(m_Handle, "_Z6CmdEndPK7edict_s")); - if (ORIG_DispatchSpawn && ORIG_DispatchTouch && ORIG_ClientCommand && ORIG_PlayerPostThink && + if (ORIG_DispatchSpawn && ORIG_DispatchTouch && ORIG_DispatchKeyValue && ORIG_ClientCommand && ORIG_PlayerPostThink && ORIG_PM_Move && ORIG_AddToFullPack && ORIG_CmdStart && ORIG_CmdEnd) { EngineDevMsg("[server dll] Found DispatchSpawn at %p.\n", ORIG_DispatchSpawn); EngineDevMsg("[server dll] Found DispatchTouch at %p.\n", ORIG_DispatchTouch); + EngineDevMsg("[server dll] Found DispatchKeyValue at %p.\n", ORIG_DispatchKeyValue); EngineDevMsg("[server dll] Found ClientCommand at %p.\n", ORIG_ClientCommand); EngineDevMsg("[server dll] Found PlayerPostThink at %p.\n", ORIG_PlayerPostThink); EngineDevMsg("[server dll] Found PM_Move at %p.\n", ORIG_PM_Move); @@ -1248,10 +1260,12 @@ void ServerDLL::FindStuff() // Gets our hooked addresses on Windows. ORIG_DispatchSpawn = funcs.pfnSpawn; ORIG_DispatchTouch = funcs.pfnTouch; + ORIG_DispatchKeyValue = funcs.pfnKeyValue; ORIG_ClientCommand = funcs.pfnClientCommand; ORIG_PlayerPostThink = funcs.pfnPlayerPostThink; EngineDevMsg("[server dll] Found DispatchSpawn at %p.\n", ORIG_DispatchSpawn); EngineDevMsg("[server dll] Found DispatchTouch at %p.\n", ORIG_DispatchTouch); + EngineDevMsg("[server dll] Found DispatchKeyValue at %p.\n", ORIG_DispatchKeyValue); EngineDevMsg("[server dll] Found ClientCommand at %p.\n", ORIG_ClientCommand); EngineDevMsg("[server dll] Found PlayerPostThink at %p.\n", ORIG_PlayerPostThink); if (INTERFACE_VERSION == 140) @@ -1647,6 +1661,7 @@ void ServerDLL::RegisterCVarsAndCommands() REG(bxt_ch_trigger_tp_keeps_momentum_velocity); REG(bxt_ch_trigger_tp_keeps_momentum_velocity_redirect); REG(bxt_ch_trigger_tp_keeps_momentum_viewangles); + REG(bxt_ch_trigger_tp_landmark); } REG(bxt_splits_print); @@ -3440,10 +3455,76 @@ void TriggerTpKeepsMomentumRestore(Vector prev_vel, Vector prev_view, Vector pre } } +HOOK_DEF_2(ServerDLL, void, __cdecl, DispatchKeyValue, edict_t*, pentKeyvalue, KeyValueData*, pkvd) +{ + if (pkvd && pentKeyvalue + && pkvd->szClassName // some entities don't have classname, this avoids crash. + && pkvd->szKeyName && pkvd->szValue // just to make sure + && !strcmp(pkvd->szClassName, "trigger_teleport") + && !strcmp(pkvd->szKeyName, "landmark") + ) { + + edict_t *edicts; + HwDLL::GetInstance().GetEdicts(&edicts); + const auto index = pentKeyvalue - edicts; + + tpLandmarks[index] = pkvd->szValue; + // Don't set pkvd->fHandled = 1, + // as some games could handle the same cases for the same entities, + // which means you won't give the game a chance to read that data! + // -- _Smiley + // pkvd->fHandled = 1; + } + + ORIG_DispatchKeyValue(pentKeyvalue, pkvd); +} + +// std::optional is at least C++17 :DDDDDDDDDDDDDDDDDDDDDDD +std::tuple TriggerTpLandmarkBefore(bool enabled, entvars_t *this_pev, entvars_t *pev, enginefuncs_t *pEngfuncs) +{ + if (!enabled) + return std::make_tuple(false, Vector()); + + const auto index = ServerDLL::GetInstance().pEngfuncs->pfnIndexOfEdict(this_pev->pContainingEntity); + const auto tpLandmarks = ServerDLL::GetInstance().tpLandmarks; + + if (!tpLandmarks.count(index)) + return std::make_tuple(false, Vector()); + + const auto landmarkName = tpLandmarks.at(index); + const edict_t *landmark = pEngfuncs->pfnFindEntityByString(NULL, "targetname", landmarkName.c_str()); + + if (HwDLL::GetInstance().IsValidEdict(landmark)) + return std::make_tuple(true, Vector(pev->origin) - Vector(landmark->v.origin)); + + return std::make_tuple(false, Vector()); +} + +void TriggerTpLandmarkAfter(entvars_t *pev, Vector offset) +{ + pev->origin = pev->origin + offset; + // have to offset by some HULL because of origin z diff + const auto is_duck = pev->button & (IN_DUCK) || pev->flags & (FL_DUCKING); + const Vector VEC_HULL_MIN(-16, -16, -36); + const Vector VEC_DUCK_HULL_MIN(-16, -16, -18); + const auto hull_offset = is_duck ? VEC_DUCK_HULL_MIN : VEC_HULL_MIN; + + pev->origin[2] += hull_offset[2]; + // https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/triggers.cpp#L1908 + pev->origin[2] -= 1; +} + +void ServerDLL::ClearTPLandmarks() +{ + tpLandmarks.clear(); +} + HOOK_DEF_3(ServerDLL, void, __fastcall, CBaseTrigger__TeleportTouch, void*, thisptr, int, edx, void*, pOther) { auto is_bxt_ch_trigger_tp_keeps_momentum_enabled = CVars::sv_cheats.GetBool() && CVars::bxt_ch_trigger_tp_keeps_momentum.GetBool(); + auto is_bxt_ch_trigger_tp_landmark_enabled = CVars::sv_cheats.GetBool() && CVars::bxt_ch_trigger_tp_landmark.GetBool() && HwDLL::GetInstance().ppGlobals; + entvars_t *this_pev = *reinterpret_cast(reinterpret_cast(thisptr) + 4); entvars_t *pev = *reinterpret_cast(reinterpret_cast(pOther) + 4); Vector prev_vel; Vector prev_view; @@ -3457,17 +3538,25 @@ HOOK_DEF_3(ServerDLL, void, __fastcall, CBaseTrigger__TeleportTouch, void*, this prev_basevelocity = pev->basevelocity; } + const auto landmark_info = TriggerTpLandmarkBefore(is_bxt_ch_trigger_tp_landmark_enabled, this_pev, pev, pEngfuncs); + ORIG_CBaseTrigger__TeleportTouch(thisptr, edx, pOther); if (is_bxt_ch_trigger_tp_keeps_momentum_enabled && pev && pEngfuncs && IsPlayer(pev->pContainingEntity)) { TriggerTpKeepsMomentumRestore(prev_vel, prev_vel, prev_angles, prev_basevelocity, pev, pEngfuncs); } + + if (is_bxt_ch_trigger_tp_landmark_enabled && std::get<0>(landmark_info)) { + TriggerTpLandmarkAfter(pev, std::get<1>(landmark_info)); + } } HOOK_DEF_2(ServerDLL, void, __cdecl, CBaseTrigger__TeleportTouch_Linux, void*, thisptr, void*, pOther) { auto is_bxt_ch_trigger_tp_keeps_momentum_enabled = CVars::sv_cheats.GetBool() && CVars::bxt_ch_trigger_tp_keeps_momentum.GetBool(); + auto is_bxt_ch_trigger_tp_landmark_enabled = CVars::sv_cheats.GetBool() && CVars::bxt_ch_trigger_tp_landmark.GetBool() && pEngfuncs && HwDLL::GetInstance().ppGlobals; + entvars_t *this_pev = *reinterpret_cast(reinterpret_cast(thisptr) + 4); entvars_t *pev = *reinterpret_cast(reinterpret_cast(pOther) + 4); Vector prev_vel; Vector prev_view; @@ -3481,11 +3570,17 @@ HOOK_DEF_2(ServerDLL, void, __cdecl, CBaseTrigger__TeleportTouch_Linux, void*, t prev_basevelocity = pev->basevelocity; } + const auto landmark_info = TriggerTpLandmarkBefore(is_bxt_ch_trigger_tp_landmark_enabled, this_pev, pev, pEngfuncs); + ORIG_CBaseTrigger__TeleportTouch_Linux(thisptr, pOther); if (is_bxt_ch_trigger_tp_keeps_momentum_enabled && pev && pEngfuncs && IsPlayer(pev->pContainingEntity)) { TriggerTpKeepsMomentumRestore(prev_vel, prev_vel, prev_angles, prev_basevelocity, pev, pEngfuncs); } + + if (is_bxt_ch_trigger_tp_landmark_enabled && std::get<0>(landmark_info)) { + TriggerTpLandmarkAfter(pev, std::get<1>(landmark_info)); + } } #undef ALERT \ No newline at end of file diff --git a/BunnymodXT/modules/ServerDLL.hpp b/BunnymodXT/modules/ServerDLL.hpp index 44a93e8f..28245b97 100644 --- a/BunnymodXT/modules/ServerDLL.hpp +++ b/BunnymodXT/modules/ServerDLL.hpp @@ -66,6 +66,7 @@ class ServerDLL : public IHookableDirFilter HOOK_DECL(int, __cdecl, CBaseEntity__IsInWorld_Linux, void* thisptr) HOOK_DECL(void, __fastcall, CBaseTrigger__TeleportTouch, void* thisptr, int edx, void* pOther) HOOK_DECL(void, __cdecl, CBaseTrigger__TeleportTouch_Linux, void* thisptr, void* pOther) + HOOK_DECL(void, __cdecl, DispatchKeyValue, edict_t* pentKeyvalue, KeyValueData* pkvd) public: static ServerDLL& GetInstance() @@ -248,4 +249,8 @@ class ServerDLL : public IHookableDirFilter float ch_noclip_vel_prev_maxspeed; float ch_noclip_vel_prev_clientmaxspeed; + +public: + std::unordered_map tpLandmarks; + void ClearTPLandmarks(); }; From d0b7592775c852bec222aa2ef65e2e61571202a1 Mon Sep 17 00:00:00 2001 From: khang Date: Fri, 12 Jul 2024 14:35:12 -0400 Subject: [PATCH 2/4] clear landmark without any conditions --- BunnymodXT/modules/HwDLL.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BunnymodXT/modules/HwDLL.cpp b/BunnymodXT/modules/HwDLL.cpp index 7f8dbd89..1a680cfa 100644 --- a/BunnymodXT/modules/HwDLL.cpp +++ b/BunnymodXT/modules/HwDLL.cpp @@ -7669,10 +7669,12 @@ HOOK_DEF_0(HwDLL, void, __cdecl, R_DrawSkyBox) HOOK_DEF_3(HwDLL, int, __cdecl, SV_SpawnServer, int, bIsDemo, char*, server, char*, startspot) { auto ret = ORIG_SV_SpawnServer(bIsDemo, server, startspot); + + ServerDLL::GetInstance().ClearTPLandmarks(); + if (ret) { Interprocess::WriteMapChange(CustomHud::GetTime(), server); lastLoadedMap = server; - ServerDLL::GetInstance().ClearTPLandmarks(); } if (insideHost_Loadgame_f) { From e0c154b46d6a5820058a37c378e9f54974da8d0f Mon Sep 17 00:00:00 2001 From: khang Date: Mon, 15 Jul 2024 08:13:01 -0400 Subject: [PATCH 3/4] changes suggested --- BunnymodXT/modules/ServerDLL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BunnymodXT/modules/ServerDLL.cpp b/BunnymodXT/modules/ServerDLL.cpp index 39a6de70..64c5147a 100644 --- a/BunnymodXT/modules/ServerDLL.cpp +++ b/BunnymodXT/modules/ServerDLL.cpp @@ -3504,7 +3504,7 @@ void TriggerTpLandmarkAfter(entvars_t *pev, Vector offset) { pev->origin = pev->origin + offset; // have to offset by some HULL because of origin z diff - const auto is_duck = pev->button & (IN_DUCK) || pev->flags & (FL_DUCKING); + const auto is_duck = pev->bInDuck || pev->flags & (FL_DUCKING); const Vector VEC_HULL_MIN(-16, -16, -36); const Vector VEC_DUCK_HULL_MIN(-16, -16, -18); const auto hull_offset = is_duck ? VEC_DUCK_HULL_MIN : VEC_HULL_MIN; From c81bbb24fe8746e1922aa8ed01bd55e7684adf62 Mon Sep 17 00:00:00 2001 From: khang Date: Sat, 27 Jul 2024 14:53:47 -0400 Subject: [PATCH 4/4] changes requested --- BunnymodXT/modules/ServerDLL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/BunnymodXT/modules/ServerDLL.cpp b/BunnymodXT/modules/ServerDLL.cpp index 64c5147a..62c5bc37 100644 --- a/BunnymodXT/modules/ServerDLL.cpp +++ b/BunnymodXT/modules/ServerDLL.cpp @@ -3505,8 +3505,6 @@ void TriggerTpLandmarkAfter(entvars_t *pev, Vector offset) pev->origin = pev->origin + offset; // have to offset by some HULL because of origin z diff const auto is_duck = pev->bInDuck || pev->flags & (FL_DUCKING); - const Vector VEC_HULL_MIN(-16, -16, -36); - const Vector VEC_DUCK_HULL_MIN(-16, -16, -18); const auto hull_offset = is_duck ? VEC_DUCK_HULL_MIN : VEC_HULL_MIN; pev->origin[2] += hull_offset[2];