From 094a6e4fa57e2b30d46ecdcf0a1238f8c5b8d6fb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 23 Jan 2023 02:22:51 +0100 Subject: [PATCH] Initial hitbox drawing implementation Currently only hooked up to lag compensation code. Will be hooked up to 'sv_showhitboxes' in the future (drawing hitboxes of all animating). --- r5dev/game/server/baseanimating.cpp | 91 +++++++++++++++++++++++++++++ r5dev/game/server/baseanimating.h | 44 ++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 r5dev/game/server/baseanimating.cpp diff --git a/r5dev/game/server/baseanimating.cpp b/r5dev/game/server/baseanimating.cpp new file mode 100644 index 00000000..18197930 --- /dev/null +++ b/r5dev/game/server/baseanimating.cpp @@ -0,0 +1,91 @@ +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: Base class for all animating characters and objects. +// +//===========================================================================// +#include "core/stdafx.h" +#include "baseanimating.h" +#include "engine/modelinfo.h" +#include "public/idebugoverlay.h" + +static Vector3D hullcolor[8] = +{ + Vector3D(1.0, 1.0, 1.0), + Vector3D(1.0, 0.5, 0.5), + Vector3D(0.5, 1.0, 0.5), + Vector3D(1.0, 1.0, 0.5), + Vector3D(0.5, 0.5, 1.0), + Vector3D(1.0, 0.5, 1.0), + Vector3D(0.5, 1.0, 1.0), + Vector3D(1.0, 1.0, 1.0) +}; + +//----------------------------------------------------------------------------- +// Purpose: Send the current hitboxes for this model to the client ( to compare with +// r_drawentities 3 client side boxes ). +// WARNING: This uses a ton of bandwidth, only use on a listen server +//----------------------------------------------------------------------------- +void CBaseAnimating::DrawServerHitboxes(float duration /*= 0.0f*/) +{ + if (!m_pStudioHdr && g_pModelInfoServer->GetModel(m_nModelIndex)) + { + UpdateModelPtr(); + if (!m_pStudioHdr) + { + return; + } + } + + mstudiohitboxset_t* set = m_pStudioHdr->pHitboxSet(m_nHitboxSet); + if (!set) + return; + + matrix3x4_t transforms; + + int r = 0; + int g = 0; + int b = 255; + + for (int i = 0; i < set->numhitboxes; i++) + { + mstudiobbox_t* pBox = set->pHitbox(i); + + int j = (pBox->group % 8); + + r = (int)(255.0f * hullcolor[j][0]); + g = (int)(255.0f * hullcolor[j][1]); + b = (int)(255.0f * hullcolor[j][2]); + + HitboxToWorldTransforms(pBox->bone, &transforms); + g_pDebugOverlay->AddBoxOverlay(transforms, pBox->bbmin, pBox->bbmax, r, g, b, 0, true, duration); + } +} + +void CBaseAnimating::HitboxToWorldTransforms(uint32_t iBone, matrix3x4_t* transforms) +{ + const static int index = 285; + CallVFunc(index, this, iBone, transforms); +} + +//----------------------------------------------------------------------------- +// Purpose: sets studio pointer to an updated studiomdl cache +//----------------------------------------------------------------------------- +void CBaseAnimating::UpdateModelPtr() +{ + // Populates the 'm_pStudioHdr' field. + v_CBaseAnimating__UpdateModelPtr(this); +} + +void DrawServerHitboxes(CBaseAnimating* thisp, float duration) +{ + thisp->DrawServerHitboxes(duration); +} + +void BaseAnimating_Attach() +{ + DetourAttach(&v_CBaseAnimating__DrawServerHitboxes, &DrawServerHitboxes); +} +void BaseAnimating_Detach() +{ + DetourDetach(&v_CBaseAnimating__DrawServerHitboxes, &DrawServerHitboxes); +} \ No newline at end of file diff --git a/r5dev/game/server/baseanimating.h b/r5dev/game/server/baseanimating.h index 86c2a9c7..45e32069 100644 --- a/r5dev/game/server/baseanimating.h +++ b/r5dev/game/server/baseanimating.h @@ -16,6 +16,15 @@ class CBaseAnimating : public CBaseEntity { +public: + void DrawServerHitboxes(float duration = 0.0f); + void UpdateModelPtr(); + + void HitboxToWorldTransforms(uint32_t iBone, matrix3x4_t* transforms); + + float GetModelScale() const { return m_flModelScale; } + +protected: char gap_b04[8]; // Aligns properly in IDA and generated code after setting from 12 to 8. bool m_markedForServerInterpolation; bool m_animRemoveFromServerInterpolationNextFrame; @@ -126,5 +135,40 @@ class CBaseAnimating : public CBaseEntity char gap_11E4[12]; // TODO: this might belong to CBaseAnimatingOverlay! }; +inline CMemory p_CBaseAnimating__UpdateModelPtr; +inline auto v_CBaseAnimating__UpdateModelPtr = p_CBaseAnimating__UpdateModelPtr.RCast(); + +inline CMemory p_CBaseAnimating__DrawServerHitboxes; +inline auto v_CBaseAnimating__DrawServerHitboxes = p_CBaseAnimating__DrawServerHitboxes.RCast(); + +void BaseAnimating_Attach(); +void BaseAnimating_Detach(); + +/////////////////////////////////////////////////////////////////////////////// +class VBaseAnimating : public IDetour +{ + virtual void GetAdr(void) const + { + spdlog::debug("| FUN: CBaseAnimating::UpdateModelPtr : {:#18x} |\n", p_CBaseAnimating__UpdateModelPtr.GetPtr()); + spdlog::debug("| FUN: CBaseAnimating::DrawServerHitboxes : {:#18x} |\n", p_CBaseAnimating__DrawServerHitboxes.GetPtr()); + spdlog::debug("+----------------------------------------------------------------+\n"); + } + virtual void GetFun(void) const + { + p_CBaseAnimating__UpdateModelPtr = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 41 56 48 83 EC 20 0F BF 41 58"); + v_CBaseAnimating__UpdateModelPtr = p_CBaseAnimating__UpdateModelPtr.RCast(); + + p_CBaseAnimating__DrawServerHitboxes = g_GameDll.FindPatternSIMD("41 57 48 81 EC ?? ?? ?? ?? 48 83 B9 ?? ?? ?? ?? ?? 4C 8B F9"); // !FIXME NOT COMPAT WITH S0~S2! + v_CBaseAnimating__DrawServerHitboxes = p_CBaseAnimating__DrawServerHitboxes.RCast(); + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Attach(void) const { } + virtual void Detach(void) const { } +}; +/////////////////////////////////////////////////////////////////////////////// + +REGISTER(VBaseAnimating); #endif // BASEANIMATING_H +