Skip to content

Commit

Permalink
Add bxt_ch_trigger_tp_keeps_momentum (#502)
Browse files Browse the repository at this point in the history
* Add bxt_ch_trigger_tp_keeps_momentum

* changes suggested
  • Loading branch information
khanghugo authored Jul 12, 2024
1 parent b77164d commit 712bc7c
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 4 deletions.
6 changes: 5 additions & 1 deletion BunnymodXT/cvars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,11 @@
X(bxt_ch_checkpoint_onground_only, "0") \
X(bxt_ch_fix_sticky_slide, "0") \
X(bxt_ch_fix_sticky_slide_offset, "0.01") \
X(bxt_ch_noclip_speed, "0")
X(bxt_ch_noclip_speed, "0") \
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")

class CVarWrapper
{
Expand Down
146 changes: 143 additions & 3 deletions BunnymodXT/modules/ServerDLL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ extern "C" int __cdecl _ZN11CBaseEntity9IsInWorldEv(void *thisptr)
{
return ServerDLL::HOOKED_CBaseEntity__IsInWorld_Linux(thisptr);
}

extern "C" void __cdecl _ZN12CBaseTrigger13TeleportTouchEP11CBaseEntity(void* thisptr, void* pOther)
{
return ServerDLL::HOOKED_CBaseTrigger__TeleportTouch_Linux(thisptr, pOther);
}
#endif

void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* moduleBase, size_t moduleLength, bool needToIntercept)
Expand Down Expand Up @@ -172,7 +177,9 @@ void ServerDLL::Hook(const std::wstring& moduleName, void* moduleHandle, void* m
ORIG_PM_Duck, HOOKED_PM_Duck,
ORIG_PM_UnDuck, HOOKED_PM_UnDuck,
ORIG_CBaseEntity__IsInWorld, HOOKED_CBaseEntity__IsInWorld,
ORIG_CBaseEntity__IsInWorld_Linux, HOOKED_CBaseEntity__IsInWorld_Linux);
ORIG_CBaseEntity__IsInWorld_Linux, HOOKED_CBaseEntity__IsInWorld_Linux,
ORIG_CBaseTrigger__TeleportTouch, HOOKED_CBaseTrigger__TeleportTouch,
ORIG_CBaseTrigger__TeleportTouch_Linux, HOOKED_CBaseTrigger__TeleportTouch_Linux);
}
}

Expand Down Expand Up @@ -227,7 +234,9 @@ void ServerDLL::Unhook()
ORIG_PM_Duck,
ORIG_PM_UnDuck,
ORIG_CBaseEntity__IsInWorld,
ORIG_CBaseEntity__IsInWorld_Linux);
ORIG_CBaseEntity__IsInWorld_Linux,
ORIG_CBaseTrigger__TeleportTouch,
ORIG_CBaseTrigger__TeleportTouch_Linux);
}

Clear();
Expand Down Expand Up @@ -301,6 +310,8 @@ void ServerDLL::Clear()
ORIG_PM_UnDuck = nullptr;
ORIG_CBaseEntity__IsInWorld = nullptr;
ORIG_CBaseEntity__IsInWorld_Linux = nullptr;
ORIG_CBaseTrigger__TeleportTouch = nullptr;
ORIG_CBaseTrigger__TeleportTouch_Linux = nullptr;
ppmove = nullptr;
offPlayerIndex = 0;
offOldbuttons = 0;
Expand Down Expand Up @@ -1554,6 +1565,19 @@ void ServerDLL::FindStuff()
}
}

{
ORIG_CBaseTrigger__TeleportTouch = reinterpret_cast<_CBaseTrigger__TeleportTouch>(MemUtils::GetSymbolAddress(m_Handle, "?TeleportTouch@CBaseTrigger@@QAEXPAVCBaseEntity@@@Z"));
if (ORIG_CBaseTrigger__TeleportTouch)
EngineDevMsg("[server dll] Found CBaseTrigger::TriggerTouch at %p.\n", ORIG_CBaseTrigger__TeleportTouch);
else {
ORIG_CBaseTrigger__TeleportTouch_Linux = reinterpret_cast<_CBaseTrigger__TeleportTouch_Linux>(MemUtils::GetSymbolAddress(m_Handle, "_ZN12CBaseTrigger13TeleportTouchEP11CBaseEntity"));
if (ORIG_CBaseTrigger__TeleportTouch_Linux)
EngineDevMsg("[server dll] Found CBaseTrigger::TriggerTouch [Linux] at %p.\n", ORIG_CBaseTrigger__TeleportTouch_Linux);
else
EngineDevWarning("[server dll] Could not find CBaseTrigger::TriggerTouch.\n");
}
}

if (!pEngfuncs)
{
pEngfuncs = reinterpret_cast<enginefuncs_t*>(MemUtils::GetSymbolAddress(m_Handle, "g_engfuncs"));
Expand Down Expand Up @@ -1617,6 +1641,12 @@ void ServerDLL::RegisterCVarsAndCommands()
REG(bxt_cof_allow_skipping_all_cutscenes);
if (ORIG_PM_Move)
REG(bxt_ch_noclip_speed);
if (ORIG_CBaseTrigger__TeleportTouch || ORIG_CBaseTrigger__TeleportTouch_Linux) {
REG(bxt_ch_trigger_tp_keeps_momentum);
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_splits_print);
REG(bxt_splits_print_times_at_end);
Expand Down Expand Up @@ -3347,4 +3377,114 @@ HOOK_DEF_1(ServerDLL, int, __cdecl, CBaseEntity__IsInWorld_Linux, void*, thisptr
return ORIG_CBaseEntity__IsInWorld_Linux(thisptr);
}

#undef ALERT
bool ServerDLL::IsPlayer(edict_t *ent)
{
// https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/player.cpp#L2850

auto &hw = HwDLL::GetInstance();

if (strcmp(hw.GetString(ent->v.classname), "player") != 0)
return false;

if (!(ent->v.flags & FL_CLIENT))
return false;

if (pEngfuncs && hw.ppGlobals)
{
int index = pEngfuncs->pfnIndexOfEdict(ent);

if ((index < 1) || (index > hw.ppGlobals->maxClients)) // gGlobalVariables.maxClients = svs.maxclients
return false;
}

return true;
}

void TriggerTpKeepsMomentumRestore(Vector prev_vel, Vector prev_view, Vector prev_angles, Vector prev_basevelocity, entvars_t *pev, enginefuncs_t *pEngfuncs)
{
// Set velocity before viewangles because viewangles will mess with the velocity angle for redirection
if (CVars::bxt_ch_trigger_tp_keeps_momentum_velocity.GetBool()) {
if (CVars::bxt_ch_trigger_tp_keeps_momentum_velocity_redirect.GetBool()) {
// https://github.com/fireblizzard/agmod/blob/bf06e4ffd31c1427784685118820e15552803bcb/dlls/triggers.cpp#L1935
// After teleportation, pevToucher has the same viewangles as pentTarget.
Vector vecAngles = Vector(0, pev->v_angle.y, 0);
Vector vecForward;

pEngfuncs->pfnAngleVectors(vecAngles, vecForward, nullptr, nullptr);

// For velocity
float xy_vel = prev_vel.Length2D();

pev->velocity.x = vecForward.x * xy_vel;
pev->velocity.y = vecForward.y * xy_vel;

// For base velocity
float xy_basevel = prev_basevelocity.Length2D();

pev->basevelocity.x = vecForward.x * xy_basevel;
pev->basevelocity.y = vecForward.y * xy_basevel;
} else {
pev->velocity = prev_vel;
pev->basevelocity = prev_basevelocity;
}
}

if (CVars::bxt_ch_trigger_tp_keeps_momentum_viewangles.GetBool()) {
// In HLSDK, due to some inheritance stuffs, pevToucher's viewangles is changed differently.
// In and only in TeleportTouch, pev->fixangle is set to 1.
// If not set back to 0, we cannot set our viewangles, due to inheritance stuffs.
pev->fixangle = 0;
pev->v_angle = prev_view;
pev->angles = prev_angles;
}
}

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();

entvars_t *pev = *reinterpret_cast<entvars_t**>(reinterpret_cast<uintptr_t>(pOther) + 4);
Vector prev_vel;
Vector prev_view;
Vector prev_angles;
Vector prev_basevelocity;

if (pev) {
prev_vel = pev->velocity;
prev_view = pev->v_angle;
prev_angles = pev->angles;
prev_basevelocity = pev->basevelocity;
}

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);
}
}

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();

entvars_t *pev = *reinterpret_cast<entvars_t**>(reinterpret_cast<uintptr_t>(pOther) + 4);
Vector prev_vel;
Vector prev_view;
Vector prev_angles;
Vector prev_basevelocity;

if (pev) {
prev_vel = pev->velocity;
prev_view = pev->v_angle;
prev_angles = pev->angles;
prev_basevelocity = pev->basevelocity;
}

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);
}
}

#undef ALERT
4 changes: 4 additions & 0 deletions BunnymodXT/modules/ServerDLL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class ServerDLL : public IHookableDirFilter
HOOK_DECL(void, __fastcall, CTriggerCamera__FollowTarget, void* thisptr)
HOOK_DECL(int, __fastcall, CBaseEntity__IsInWorld, void* thisptr)
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)

public:
static ServerDLL& GetInstance()
Expand Down Expand Up @@ -117,6 +119,8 @@ class ServerDLL : public IHookableDirFilter

void GiveNamedItem(entvars_t *pev, int istr);

bool IsPlayer(edict_t *ent);

private:
ServerDLL() : IHookableDirFilter({ L"dlls", L"cl_dlls"}) {};
ServerDLL(const ServerDLL&);
Expand Down

0 comments on commit 712bc7c

Please sign in to comment.