From 98a61ee9ed300731d9a5a2b8dd6889697f157728 Mon Sep 17 00:00:00 2001 From: Edo Date: Mon, 26 Dec 2022 15:14:22 +0100 Subject: [PATCH] [Debug]: Draw lines from riot shield (#670) --- src/Components/Modules/Bullet.cpp | 80 ++++++++++++++++++++++++++++++ src/Components/Modules/Bullet.hpp | 17 +++++++ src/Components/Modules/Debug.cpp | 36 +++++++------- src/Components/Modules/Debug.hpp | 6 +-- src/Components/Modules/Gamepad.cpp | 2 +- src/Game/Client.cpp | 8 +++ src/Game/Client.hpp | 5 ++ src/Game/Functions.cpp | 4 +- src/Game/Functions.hpp | 10 +++- src/Game/Game.cpp | 7 +++ src/Game/Game.hpp | 5 ++ 11 files changed, 155 insertions(+), 25 deletions(-) diff --git a/src/Components/Modules/Bullet.cpp b/src/Components/Modules/Bullet.cpp index 881cef52..d3310830 100644 --- a/src/Components/Modules/Bullet.cpp +++ b/src/Components/Modules/Bullet.cpp @@ -6,6 +6,14 @@ namespace Components Dvar::Var Bullet::BGSurfacePenetration; Game::dvar_t* Bullet::BGBulletRange; + float Bullet::ContactPointSave[3]; + float Bullet::VCSave[3]; + float Bullet::CalcRicochetSave[3]; + + float Bullet::ColorYellow[] = {1.0f, 1.0f, 0.0f, 1.0f}; + float Bullet::ColorBlue[] = {0.0f, 0.0f, 1.0f, 1.0f}; + float Bullet::ColorOrange[] = {1.0f, 0.7f, 0.0f, 1.0f}; + float Bullet::BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType) { assert(weapDef); @@ -48,6 +56,63 @@ namespace Components *pHoldrand = static_cast(std::rand()); } + void Bullet::BulletRicochet_Save(const float* contactPoint) + { + std::memcpy(ContactPointSave, contactPoint, sizeof(float[3])); + } + + __declspec(naked) void Bullet::BulletRicochet_Stub() + { + __asm + { + pushad + push [esp + 0x20 + 0xC] + call BulletRicochet_Save + add esp, 0x4 + popad + + // Game's code + sub esp, 0x4C + push ebp + mov ebp, dword ptr [esp + 0x60] + + push 0x5D5B08 + ret + } + } + + void Bullet::_VectorMA_Stub(float* va, float scale, float* vb, float* vc) + { + vc[0] = va[0] + scale * vb[0]; + vc[1] = va[1] + scale * vb[1]; + vc[2] = va[2] + scale * vb[2]; + + std::memcpy(VCSave, vc, sizeof(float[3])); + } + + void Bullet::CalcRicochet_Stub(const float* incoming, const float* normal, float* result) + { + Utils::Hook::Call(0x5D59F0)(incoming, normal, result); + std::memcpy(CalcRicochetSave, result, sizeof(float[3])); + } + + int Bullet::Bullet_Fire_Stub(Game::gentity_s* attacker, [[maybe_unused]] float spread, Game::weaponParms* wp, Game::gentity_s* weaponEnt, Game::PlayerHandIndex hand, int gameTime) + { + float tmp[3]; + + Game::G_DebugStar(ContactPointSave, ColorYellow); + + tmp[0] = (CalcRicochetSave[0] * 100.0f) + VCSave[0]; + tmp[1] = (CalcRicochetSave[1] * 100.0f) + VCSave[1]; + tmp[2] = (CalcRicochetSave[2] * 100.0f) + VCSave[1]; + + Game::G_DebugLineWithDuration(VCSave, tmp, ColorOrange, 1, 100); + Game::G_DebugStar(tmp, ColorBlue); + + // Set the spread to 0 when drawing + return Game::Bullet_Fire(attacker, 0.0f, wp, weaponEnt, hand, gameTime); + } + Bullet::Bullet() { BGSurfacePenetration = Dvar::Register("bg_surfacePenetration", 0.0f, @@ -59,5 +124,20 @@ namespace Components Utils::Hook(0x440340, Bullet_FireStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x440368, BG_srand_Hk, HOOK_CALL).install()->quick(); + + std::memset(ContactPointSave, 0, sizeof(float[3])); + std::memset(VCSave, 0, sizeof(float[3])); + std::memset(CalcRicochetSave, 0, sizeof(float[3])); + +#ifdef DEBUG_RIOT_SHIELD + Utils::Hook(0x5D5B00, BulletRicochet_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x5D5B00 + 5, 3); + + Utils::Hook(0x5D5BBA, CalcRicochet_Stub, HOOK_CALL).install()->quick(); + + Utils::Hook(0x5D5BD7, _VectorMA_Stub, HOOK_CALL).install()->quick(); + + Utils::Hook(0x5D5C0B, Bullet_Fire_Stub, HOOK_CALL).install()->quick(); +#endif } } diff --git a/src/Components/Modules/Bullet.hpp b/src/Components/Modules/Bullet.hpp index 84083e3b..8a0abed4 100644 --- a/src/Components/Modules/Bullet.hpp +++ b/src/Components/Modules/Bullet.hpp @@ -12,10 +12,27 @@ namespace Components // Can't use Var class inside assembly stubs static Game::dvar_t* BGBulletRange; + static float ContactPointSave[]; + static float VCSave[]; + static float CalcRicochetSave[]; + + static float ColorYellow[]; + static float ColorBlue[]; + static float ColorOrange[]; + static float BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType); static void Bullet_FireStub(); static void BG_srand_Hk(unsigned int* pHoldrand); + + static void BulletRicochet_Save(const float* contactPoint); + static void BulletRicochet_Stub(); + + static void CalcRicochet_Stub(const float* incoming, const float* normal, float* result); + + static void _VectorMA_Stub(float* va, float scale, float* vb, float* vc); + + static int Bullet_Fire_Stub(Game::gentity_s* attacker, float spread, Game::weaponParms* wp, Game::gentity_s* weaponEnt, Game::PlayerHandIndex hand, int gameTime); }; } diff --git a/src/Components/Modules/Debug.cpp b/src/Components/Modules/Debug.cpp index e35024c7..9e742f22 100644 --- a/src/Components/Modules/Debug.cpp +++ b/src/Components/Modules/Debug.cpp @@ -94,15 +94,15 @@ namespace Components "EF_SOFT", }; - const char Debug::strButtons[] = + const char Debug::StrButtons[] = { '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\0' }; - const char Debug::strTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain."; + const char Debug::StrTemplate[] = "%s: %s All those moments will be lost in time, like tears in rain."; - const float Debug::colorWhite[] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float Debug::ColorWhite[] = {1.0f, 1.0f, 1.0f, 1.0f}; std::string Debug::BuildPMFlagsString(const Game::playerState_s* ps) { @@ -163,19 +163,19 @@ namespace Components auto* const font2 = Game::UI_GetFontHandle(scrPlace, 6, MY_SCALE2); Game::UI_DrawText(scrPlace, "Client View of Flags", maxChars, font2, -60.0f, 0, 1, 1, - MY_SCALE2, colorWhite, 1); + MY_SCALE2, ColorWhite, 1); const auto pmf = BuildPMFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pmf.data(), maxChars, font1, 30.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto pof = BuildPOFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pof.data(), maxChars, font1, 350.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto plf = BuildPLFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, plf.data(), maxChars, font1, 350.0f, 250.0f, 1, 1, MY_SCALE_2, ColorWhite, 3); const auto pef = BuildPEFlagsString(&cgameGlob->predictedPlayerState); - Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, colorWhite, 3); + Game::UI_DrawText(scrPlace, pef.data(), maxChars, font1, 525.0f, MY_Y, 1, 1, MY_SCALE_2, ColorWhite, 3); } void Debug::CG_DrawDebugPlayerHealth(const int localClientNum) @@ -221,25 +221,25 @@ namespace Components auto* const font5 = Game::UI_GetFontHandle(scrPlace, 5, 0.4f); auto* const font6 = Game::UI_GetFontHandle(scrPlace, 6, 0.4f); - sprintf_s(strFinal, strTemplate, font1->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font1->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font1, MY_X, 10.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font2->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font2->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font2, MY_X, 35.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font3->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font3->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font3, MY_X, 60.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font5->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font5->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font5, MY_X, 85.0f, 1, 1, 0.4f, ColorWhite, 3); - sprintf_s(strFinal, strTemplate, font6->fontName, strButtons); + sprintf_s(strFinal, StrTemplate, font6->fontName, StrButtons); Game::UI_FilterStringForButtonAnimation(strFinal, sizeof(strFinal)); - Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, colorWhite, 3); + Game::UI_DrawText(scrPlace, strFinal, std::numeric_limits::max(), font6, MY_X, 110.0f, 1, 1, 0.4f, ColorWhite, 3); } void Debug::CG_DrawDebugOverlays_Hk(const int localClientNum) diff --git a/src/Components/Modules/Debug.hpp b/src/Components/Modules/Debug.hpp index eb846014..ac18b2c5 100644 --- a/src/Components/Modules/Debug.hpp +++ b/src/Components/Modules/Debug.hpp @@ -19,8 +19,8 @@ namespace Components static const char* PLFlagsValues[]; static const char* PEFlagsValues[]; - static const char strButtons[]; - static const char strTemplate[]; + static const char StrButtons[]; + static const char StrTemplate[]; static constexpr auto MY_SCALE2 = 0.5f; static constexpr auto MY_SCALE_2 = 0.201f; @@ -28,7 +28,7 @@ namespace Components static constexpr auto MY_X = -25.0f; static constexpr auto MY_Y = 20.0f; - static const float colorWhite[]; + static const float ColorWhite[]; static std::string BuildPMFlagsString(const Game::playerState_s* ps); static std::string BuildPOFlagsString(const Game::playerState_s* ps); diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index e352a28a..edb34245 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -751,7 +751,7 @@ namespace Components -yawRight }; - Game::cgArray[0].selectedLocationAngle = Game::AngleNormalize360(Game::vectoyaw(&vec)); + Game::cgArray[0].selectedLocationAngle = Game::AngleNormalize360(Game::vectoryaw(&vec)); Game::cgArray[0].selectedAngleLocation[0] = Game::cgArray[0].selectedLocation[0]; Game::cgArray[0].selectedAngleLocation[1] = Game::cgArray[0].selectedLocation[1]; } diff --git a/src/Game/Client.cpp b/src/Game/Client.cpp index 2eef16be..2a690e29 100644 --- a/src/Game/Client.cpp +++ b/src/Game/Client.cpp @@ -25,6 +25,7 @@ namespace Game CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50); CL_WriteDemoClientArchive_t CL_WriteDemoClientArchive = CL_WriteDemoClientArchive_t(0x5A8020); CL_WriteDemoMessage_t CL_WriteDemoMessage = CL_WriteDemoMessage_t(0x4707C0); + CL_AddDebugStarWithText_t CL_AddDebugStarWithText = CL_AddDebugStarWithText_t(0x4D03C0); float* cl_angles = reinterpret_cast(0xB2F8D0); @@ -79,4 +80,11 @@ namespace Game assert(clients[localClientNum].alwaysFalse == false); return &clients[localClientNum]; } + + void CL_AddDebugStar(const float* point, const float* color, int duration, int fromServer) + { + static const float MY_NULLTEXTCOLOR[] = {0.0f, 0.0f, 0.0f, 0.0f}; + + CL_AddDebugStarWithText(point, color, MY_NULLTEXTCOLOR, nullptr, 1.0f, duration, fromServer); + } } diff --git a/src/Game/Client.hpp b/src/Game/Client.hpp index 2f722c7a..13c96884 100644 --- a/src/Game/Client.hpp +++ b/src/Game/Client.hpp @@ -71,6 +71,9 @@ namespace Game typedef void(*CL_WriteDemoMessage_t)(void (*write)(const void*, int, int), int serverMessageSequence, unsigned char* data, int len, int localClientNum); extern CL_WriteDemoMessage_t CL_WriteDemoMessage; + typedef void(*CL_AddDebugStarWithText_t)(const float* point, const float* starColor, const float* textColor, const char* string, float fontsize, int duration, int fromServer); + extern CL_AddDebugStarWithText_t CL_AddDebugStarWithText; + extern float* cl_angles; extern clientConnection_t* clientConnections; @@ -89,4 +92,6 @@ namespace Game extern voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum); extern clientUIActive_t* CL_GetLocalClientUIGlobals(int localClientNum); extern clientActive_t* CL_GetLocalClientGlobals(int localClientNum); + + extern void CL_AddDebugStar(const float* point, const float* color, int duration, int fromServer); } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index a87789a6..c641e670 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -206,8 +206,9 @@ namespace Game Win_GetLanguage_t Win_GetLanguage = Win_GetLanguage_t(0x45CBA0); Vec3UnpackUnitVec_t Vec3UnpackUnitVec = Vec3UnpackUnitVec_t(0x45CA90); - vectoyaw_t vectoyaw = vectoyaw_t(0x45AD10); + vectoryaw_t vectoryaw = vectoryaw_t(0x45AD10); AngleNormalize360_t AngleNormalize360 = AngleNormalize360_t(0x438DC0); + _VectorMA_t _VectorMA = _VectorMA_t(0x5084D0); unzClose_t unzClose = unzClose_t(0x41BF20); @@ -226,6 +227,7 @@ namespace Game AimAssist_ApplyAutoMelee_t AimAssist_ApplyAutoMelee = AimAssist_ApplyAutoMelee_t(0x56A360); Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire = Weapon_RocketLauncher_Fire_t(0x424680); + Bullet_Fire_t Bullet_Fire = Bullet_Fire_t(0x4402C0); Jump_ClearState_t Jump_ClearState = Jump_ClearState_t(0x04B3890); PM_playerTrace_t PM_playerTrace = PM_playerTrace_t(0x458980); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6f84f841..45ed25bf 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -470,12 +470,15 @@ namespace Game typedef void(*Vec3UnpackUnitVec_t)(PackedUnitVec, vec3_t*); extern Vec3UnpackUnitVec_t Vec3UnpackUnitVec; - typedef float(*vectoyaw_t)(vec2_t* vec); - extern vectoyaw_t vectoyaw; + typedef float(*vectoryaw_t)(vec2_t* vec); + extern vectoryaw_t vectoryaw; typedef float(*AngleNormalize360_t)(float val); extern AngleNormalize360_t AngleNormalize360; + typedef void(*_VectorMA_t)(float* va, float scale, float* vb, float* vc); + extern _VectorMA_t _VectorMA; + typedef void(*unzClose_t)(void* handle); extern unzClose_t unzClose; @@ -509,6 +512,9 @@ namespace Game typedef gentity_s*(*Weapon_RocketLauncher_Fire_t)(gentity_s* ent, unsigned int weaponIndex, float spread, weaponParms* wp, const float* gunVel, lockonFireParms* lockParms, bool magicBullet); extern Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire; + typedef int(*Bullet_Fire_t)(gentity_s* attacker, float spread, weaponParms* wp, gentity_s* weaponEnt, PlayerHandIndex hand, int gameTime); + extern Bullet_Fire_t Bullet_Fire; + typedef void(*Jump_ClearState_t)(playerState_s* ps); extern Jump_ClearState_t Jump_ClearState; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index a4fd994d..750c2ccf 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -14,6 +14,8 @@ namespace Game G_LocalizedStringIndex_t G_LocalizedStringIndex = G_LocalizedStringIndex_t(0x4582F0); + G_DebugLineWithDuration_t G_DebugLineWithDuration = G_DebugLineWithDuration_t(0x4C3280); + gentity_t* g_entities = reinterpret_cast(0x18835D8); const char* origErrorMsg = reinterpret_cast(0x79B124); @@ -24,4 +26,9 @@ namespace Game assert(index < MAX_MODELS); return cached_models[index]; } + + void G_DebugStar(const float* point, const float* color) + { + CL_AddDebugStar(point, color, 20, 1); + } } diff --git a/src/Game/Game.hpp b/src/Game/Game.hpp index d094afb9..458d6b20 100644 --- a/src/Game/Game.hpp +++ b/src/Game/Game.hpp @@ -43,6 +43,9 @@ namespace Game typedef int(*G_LocalizedStringIndex_t)(const char* string); extern G_LocalizedStringIndex_t G_LocalizedStringIndex; + typedef void(*G_DebugLineWithDuration_t)(const float* start, const float* end, const float* color, int depthTest, int duration); + extern G_DebugLineWithDuration_t G_DebugLineWithDuration; + constexpr std::size_t MAX_GENTITIES = 2048; constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1; extern gentity_t* g_entities; @@ -50,4 +53,6 @@ namespace Game extern const char* origErrorMsg; extern XModel* G_GetModel(int index); + + extern void G_DebugStar(const float* point, const float* color); }