better viewmodel effect support

This commit is contained in:
rei-2
2026-06-08 16:28:51 -04:00
parent 24d449ced2
commit bfbbe4278c
15 changed files with 113 additions and 114 deletions
@@ -23,7 +23,7 @@ void CCameraWindow::Draw()
}
// Renders another view onto a texture
void CCameraWindow::RenderView(void* ecx, const CViewSetup& pViewSetup)
void CCameraWindow::RenderView(void* rcx, const CViewSetup& pViewSetup)
{
if (!m_bShouldDraw || !m_pCameraTexture)
return;
@@ -44,12 +44,12 @@ void CCameraWindow::RenderView(void* ecx, const CViewSetup& pViewSetup)
tViewSetup.m_flAspectRatio = float(tViewSetup.width) / float(tViewSetup.height);
tViewSetup.fov = 90;
RenderCustomView(ecx, tViewSetup, m_pCameraTexture);
RenderCustomView(rcx, tViewSetup, m_pCameraTexture);
m_bDrawing = false;
}
void CCameraWindow::RenderCustomView(void* ecx, const CViewSetup& pViewSetup, ITexture* pTexture)
void CCameraWindow::RenderCustomView(void* rcx, const CViewSetup& pViewSetup, ITexture* pTexture)
{
auto pRenderContext = I::MaterialSystem->GetRenderContext();
@@ -57,7 +57,7 @@ void CCameraWindow::RenderCustomView(void* ecx, const CViewSetup& pViewSetup, IT
pRenderContext->SetRenderTarget(pTexture);
static auto CViewRender_RenderView = U::Hooks.m_mHooks["CViewRender_RenderView"];
CViewRender_RenderView->Call<void>(ecx, pViewSetup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_UNSPECIFIED);
CViewRender_RenderView->Call<void>(rcx, pViewSetup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_UNSPECIFIED);
pRenderContext->PopRenderTargetAndViewport();
pRenderContext->Release();
@@ -4,14 +4,14 @@
class CCameraWindow
{
private:
void RenderCustomView(void* ecx, const CViewSetup& pViewSetup, ITexture* pTexture);
void RenderCustomView(void* rcx, const CViewSetup& pViewSetup, ITexture* pTexture);
IMaterial* m_pCameraMaterial;
ITexture* m_pCameraTexture;
public:
void Draw();
void RenderView(void* ecx, const CViewSetup& pViewSetup);
void RenderView(void* rcx, const CViewSetup& pViewSetup);
void Initialize();
void Unload();
+37 -41
View File
@@ -103,7 +103,7 @@ void CChams::Store(CTFPlayer* pLocal)
if (pEntity->IsDormant() || !pEntity->ShouldDraw())
continue;
if (pGroup->m_tChams()
if (pGroup->m_tChams() && !pEntity->IsWearableVM()
&& SDK::IsOnScreen(pEntity, pEntity->IsBaseCombatWeapon() || pEntity->IsWearable()))
m_vEntities.emplace_back(pEntity, pGroup->m_tChams);
@@ -246,7 +246,39 @@ void CChams::RenderHandler(const DrawModelState_t& pState, const ModelRenderInfo
}
}
bool CChams::RenderViewmodel(void* ecx, int flags, int* iReturn)
bool CChams::RenderViewmodel(void* rcx, int flags, int* iReturn)
{
if (!F::Groups.GroupsActive())
return false;
auto pRenderContext = I::MaterialSystem->GetRenderContext();
if (!pRenderContext)
return false;
Group_t* pGroup = nullptr;
if (!F::Groups.GetGroup(reinterpret_cast<CBaseAnimating*>(rcx)->IsValid() ? TargetsEnum::ViewmodelHands : TargetsEnum::ViewmodelWeapon, pGroup) || !pGroup->m_tChams(true))
return false;
Begin();
for (auto& [sName, tColor] : pGroup->m_tChams.Visible)
{
auto pMaterial = F::Materials.GetMaterial(FNV1A::Hash32(sName.c_str()));
F::Materials.SetColor(pMaterial, tColor);
I::ModelRender->ForcedMaterialOverride(pMaterial ? pMaterial->m_pMaterial : nullptr);
bool bFlip = pMaterial && pMaterial->m_bInvertCull ? !G::FlipViewmodels : G::FlipViewmodels;
pRenderContext->CullMode(bFlip ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
static auto CBaseAnimating_InternalDrawModel = U::Hooks.m_mHooks["CBaseAnimating_InternalDrawModel"];
*iReturn = CBaseAnimating_InternalDrawModel->Call<int>(rcx, flags);
}
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
End();
return true;
}
bool CChams::RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld)
{
if (!F::Groups.GroupsActive())
return false;
@@ -267,49 +299,13 @@ bool CChams::RenderViewmodel(void* ecx, int flags, int* iReturn)
F::Materials.SetColor(pMaterial, tColor);
I::ModelRender->ForcedMaterialOverride(pMaterial ? pMaterial->m_pMaterial : nullptr);
if (pMaterial && pMaterial->m_bInvertCull)
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CCW : MATERIAL_CULLMODE_CW);
static auto CBaseAnimating_InternalDrawModel = U::Hooks.m_mHooks["CBaseAnimating_InternalDrawModel"];
*iReturn = CBaseAnimating_InternalDrawModel->Call<int>(ecx, flags);
if (pMaterial && pMaterial->m_bInvertCull)
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
}
End();
return true;
}
bool CChams::RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld)
{
if (!F::Groups.GroupsActive())
return false;
auto pRenderContext = I::MaterialSystem->GetRenderContext();
if (!pRenderContext)
return false;
Group_t* pGroup = nullptr;
if (!F::Groups.GetGroup(TargetsEnum::ViewmodelHands, pGroup) || !pGroup->m_tChams(true))
return false;
Begin();
for (auto& [sName, tColor] : pGroup->m_tChams.Visible)
{
auto pMaterial = F::Materials.GetMaterial(FNV1A::Hash32(sName.c_str()));
F::Materials.SetColor(pMaterial, tColor);
I::ModelRender->ForcedMaterialOverride(pMaterial ? pMaterial->m_pMaterial : nullptr);
if (pMaterial && pMaterial->m_bInvertCull)
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CCW : MATERIAL_CULLMODE_CW);
bool bFlip = pMaterial && pMaterial->m_bInvertCull ? !G::FlipViewmodels : G::FlipViewmodels;
pRenderContext->CullMode(bFlip ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
static auto IVModelRender_DrawModelExecute = U::Hooks.m_mHooks["IVModelRender_DrawModelExecute"];
IVModelRender_DrawModelExecute->Call<void>(I::ModelRender, pState, pInfo, pBoneToWorld);
if (pMaterial && pMaterial->m_bInvertCull)
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
}
pRenderContext->CullMode(MATERIAL_CULLMODE_CCW);
End();
return true;
+1 -1
View File
@@ -32,7 +32,7 @@ public:
void RenderMain();
void RenderHandler(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld);
bool RenderViewmodel(void* ecx, int flags, int* iReturn);
bool RenderViewmodel(void* rcx, int flags, int* iReturn);
bool RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld);
bool m_bRendering = false;
+7 -11
View File
@@ -135,7 +135,7 @@ void CGlow::Store(CTFPlayer* pLocal)
continue;
Color_t tColor = F::Groups.GetColor(pEntity, pGroup);
if (pGroup->m_tGlow()
if (pGroup->m_tGlow() && !pEntity->IsWearableVM()
&& SDK::IsOnScreen(pEntity, pEntity->IsBaseCombatWeapon() || pEntity->IsWearable()))
m_mEntities[pGroup->m_tGlow].emplace_back(pEntity, tColor);
@@ -279,7 +279,7 @@ void CGlow::RenderHandler(const DrawModelState_t& pState, const ModelRenderInfo_
}
}
void CGlow::RenderViewmodel(void* ecx, int flags)
void CGlow::RenderViewmodel(void* rcx, int flags)
{
if (!F::Groups.GroupsActive())
return;
@@ -289,23 +289,22 @@ void CGlow::RenderViewmodel(void* ecx, int flags)
return F::Materials.ReloadMaterials();
Group_t* pGroup = nullptr;
if (!F::Groups.GetGroup(TargetsEnum::ViewmodelWeapon, pGroup) || !pGroup->m_tGlow())
if (!F::Groups.GetGroup(reinterpret_cast<CBaseAnimating*>(rcx)->IsValid() ? TargetsEnum::ViewmodelHands : TargetsEnum::ViewmodelWeapon, pGroup) || !pGroup->m_tGlow())
return;
static auto CBaseAnimating_InternalDrawModel = U::Hooks.m_mHooks["CBaseAnimating_InternalDrawModel"];
const int w = H::Draw.m_nScreenW, h = H::Draw.m_nScreenH;
pRenderContext->CullMode(MATERIAL_CULLMODE_CCW); // glow won't work properly with MATERIAL_CULLMODE_CW
pRenderContext->CullMode(MATERIAL_CULLMODE_CCW); // glow won't work properly with MATERIAL_CULLMODE_CW
FirstBegin(pRenderContext);
CBaseAnimating_InternalDrawModel->Call<int>(ecx, flags);
CBaseAnimating_InternalDrawModel->Call<int>(rcx, flags);
FirstEnd(pRenderContext);
SecondBegin(pRenderContext, w, h);
I::RenderView->SetColorModulation(pGroup->m_tColor);
I::RenderView->SetBlend(pGroup->m_tColor.a / 255.f);
CBaseAnimating_InternalDrawModel->Call<int>(ecx, flags);
CBaseAnimating_InternalDrawModel->Call<int>(rcx, flags);
SecondEnd(pGroup->m_tGlow, pRenderContext, w, h);
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
}
void CGlow::RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld)
@@ -318,13 +317,12 @@ void CGlow::RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInf
return F::Materials.ReloadMaterials();
Group_t* pGroup = nullptr;
if (!F::Groups.GetGroup(TargetsEnum::ViewmodelHands, pGroup) || !pGroup->m_tGlow())
if (!F::Groups.GetGroup(TargetsEnum::ViewmodelWeapon, pGroup) || !pGroup->m_tGlow())
return;
static auto IVModelRender_DrawModelExecute = U::Hooks.m_mHooks["IVModelRender_DrawModelExecute"];
const int w = H::Draw.m_nScreenW, h = H::Draw.m_nScreenH;
pRenderContext->CullMode(MATERIAL_CULLMODE_CCW); // glow won't work properly with MATERIAL_CULLMODE_CW
FirstBegin(pRenderContext);
IVModelRender_DrawModelExecute->Call<void>(I::ModelRender, pState, pInfo, pBoneToWorld);
@@ -334,8 +332,6 @@ void CGlow::RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInf
I::RenderView->SetBlend(pGroup->m_tColor.a / 255.f);
IVModelRender_DrawModelExecute->Call<void>(I::ModelRender, pState, pInfo, pBoneToWorld);
SecondEnd(pGroup->m_tGlow, pRenderContext, w, h);
pRenderContext->CullMode(G::FlipViewmodels ? MATERIAL_CULLMODE_CW : MATERIAL_CULLMODE_CCW);
}
+1 -1
View File
@@ -62,7 +62,7 @@ public:
void RenderSecond();
void RenderHandler(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld);
void RenderViewmodel(void* ecx, int flags);
void RenderViewmodel(void* rcx, int flags);
void RenderViewmodel(const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld);
void Initialize();
+3 -1
View File
@@ -1239,9 +1239,11 @@ void CVisuals::CreateMove(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
#endif
}
void CVisuals::LocalAnimations(CTFPlayer* pLocal, CUserCmd* pCmd, bool bSendPacket)
void CVisuals::LocalAnimations(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, bool bSendPacket)
{
m_vAngles.push_back(pCmd->viewangles);
if (pWeapon)
pWeapon->UpdateAllViewmodelAddons();
auto pAnimState = pLocal->m_PlayerAnimState();
if (!bSendPacket || !pAnimState)
+1 -1
View File
@@ -79,7 +79,7 @@ public:
void RestoreWorldModulation();
void CreateMove(CTFPlayer* pLocal, CTFWeaponBase* pWeapon);
void LocalAnimations(CTFPlayer* pLocal, CUserCmd* pCmd, bool bSendPacket);
void LocalAnimations(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, bool bSendPacket);
};
ADD_FEATURE(CVisuals, Visuals);
@@ -1,19 +0,0 @@
#include "../SDK/SDK.h"
#include "../Features/Resolver/Resolver.h"
MAKE_SIGNATURE(CBaseAnimating_UpdateClientSideAnimation, "client.dll", "48 89 5C 24 ? 57 48 83 EC ? 48 8B D9 E8 ? ? ? ? 48 8B F8 48 85 C0 74 ? 48 8B 00 48 8B CF FF 90 ? ? ? ? 84 C0 75 ? 33 FF 48 3B DF", 0x0);
MAKE_HOOK(CBaseAnimating_UpdateClientSideAnimation, S::CBaseAnimating_UpdateClientSideAnimation(), void,
void* rcx)
{
DEBUG_RETURN(CBaseAnimating_UpdateClientSideAnimation, rcx);
auto pLocal = H::Entities.GetLocal();
auto pPlayer = reinterpret_cast<CTFPlayer*>(rcx);
if ((Vars::Visuals::Removals::Interpolation.Value || F::Resolver.GetAngles(pPlayer)) && !G::UpdatingAnims
|| pPlayer == pLocal && !pLocal->InCond(TF_COND_HALLOWEEN_KART) && !I::EngineClient->IsPlayingDemo())
return;
CALL_ORIGINAL(rcx);
}
@@ -7,7 +7,7 @@ MAKE_SIGNATURE(CBaseViewModel_Interpolate, "client.dll", "48 8B C4 48 89 58 ? 48
MAKE_HOOK(CBaseViewModel_Interpolate, S::CBaseViewModel_Interpolate(), bool,
void* rcx, float& currentTime)
{
DEBUG_RETURN(CBaseEntity_BaseInterpolatePart1, rcx, currentTime);
DEBUG_RETURN(CBaseViewModel_Interpolate, rcx, currentTime);
if (F::Ticks.m_bRecharge)
return true;
+1 -1
View File
@@ -163,7 +163,7 @@ MAKE_HOOK(CHLClient_CreateMove, U::Memory.GetVirtual(I::Client, 21), void,
F::AntiAim.Run(pLocal, pWeapon, pCmd, *pSendPacket);
F::AntiCheatCompatibility.CreateMove(pCmd, pSendPacket);
F::Visuals.CreateMove(pLocal, pWeapon);
F::Visuals.LocalAnimations(pLocal, pCmd, *pSendPacket);
F::Visuals.LocalAnimations(pLocal, pWeapon, pCmd, *pSendPacket);
F::EnginePrediction.End(pLocal, pCmd);
F::Resolver.CreateMove();
F::NoSpreadHitscan.AskForPlayerPerf();
@@ -8,7 +8,7 @@ MAKE_SIGNATURE(CProxyModelGlowColor_OnBind_IsCritBoosted_Call, "client.dll", "48
MAKE_HOOK(CTFPlayerShared_IsCritBoosted, S::CTFPlayerShared_IsCritBoosted(), bool,
void* rcx)
{
DEBUG_RETURN(CTFPlayerShared_UpdateCritBoostEffect, rcx);
DEBUG_RETURN(CTFPlayerShared_IsCritBoosted, rcx);
const auto dwRetAddr = uintptr_t(_ReturnAddress());
const auto dwDesired = S::CProxyModelGlowColor_OnBind_IsCritBoosted_Call();
@@ -0,0 +1,14 @@
#include "../SDK/SDK.h"
#include "../Features/Resolver/Resolver.h"
MAKE_HOOK(CTFPlayer_UpdateClientSideAnimation, S::CTFPlayer_UpdateClientSideAnimation(), void,
void* rcx)
{
DEBUG_RETURN(CTFPlayer_UpdateClientSideAnimation, rcx);
auto pPlayer = reinterpret_cast<CTFPlayer*>(rcx);
if ((!Vars::Visuals::Removals::Interpolation.Value && !F::Resolver.GetAngles(pPlayer) || G::UpdatingAnims)
&& (pPlayer->entindex() != I::EngineClient->GetLocalPlayer() || I::EngineClient->IsPlayingDemo()))
CALL_ORIGINAL(rcx);
}
@@ -5,9 +5,10 @@
#include "../Features/Visuals/Materials/Materials.h"
#include "../Features/Visuals/CameraWindow/CameraWindow.h"
MAKE_SIGNATURE(CBaseAnimating_DrawModel, "client.dll", "4C 8B DC 49 89 5B ? 89 54 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC ? 48 8B 05 ? ? ? ? 48 8D 3D", 0x0);
MAKE_SIGNATURE(CEconEntity_DrawOverriddenViewmodel_DrawModel_Call, "client.dll", "8B 97 ? ? ? ? 85 D2 74 ? 83 FA ? 74 ? 0F B7 EA 4C 8B 05 ? ? ? ? 8B CD 49 83 C0 ? 48 C1 E1 ? 4C 03 C1 74 ? C1 EA ? 41 39 50 ? 75 ? 49 8B 18 BA", 0x0);
MAKE_SIGNATURE(CBaseAnimating_InternalDrawModel, "client.dll", "48 8B C4 55 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 44 8B 81", 0x0);
MAKE_SIGNATURE(CBaseViewModel_DrawModel, "client.dll", "40 53 55 56 48 83 EC ? 80 B9", 0x0);
static bool s_bDrawingViewmodel = false;
MAKE_HOOK(IVModelRender_DrawModelExecute, U::Memory.GetVirtual(I::ModelRender, 19), void,
void* rcx, const DrawModelState_t& pState, const ModelRenderInfo_t& pInfo, matrix3x4* pBoneToWorld)
@@ -26,9 +27,8 @@ MAKE_HOOK(IVModelRender_DrawModelExecute, U::Memory.GetVirtual(I::ModelRender, 1
if (F::Chams.m_mEntities.contains(pInfo.entity_index))
return;
auto pEntity = I::ClientEntityList->GetClientEntity(pInfo.entity_index);
auto pRenderContext = I::MaterialSystem->GetRenderContext();
if (pEntity && pRenderContext && pEntity->GetClassID() == ETFClassID::CTFViewModel)
auto pEntity = I::ClientEntityList->GetClientEntity(pInfo.entity_index)->As<CBaseEntity>();
if (pEntity && pEntity->IsWearableVM() /*pEntity->IsViewmodel()*/)
{
F::Glow.RenderViewmodel(pState, pInfo, pBoneToWorld);
if (F::Chams.RenderViewmodel(pState, pInfo, pBoneToWorld))
@@ -38,36 +38,12 @@ MAKE_HOOK(IVModelRender_DrawModelExecute, U::Memory.GetVirtual(I::ModelRender, 1
CALL_ORIGINAL(rcx, pState, pInfo, pBoneToWorld);
}
static bool s_bDrawingViewmodel = false;
MAKE_HOOK(CBaseAnimating_DrawModel, S::CBaseAnimating_DrawModel(), int,
void* rcx, int flags)
{
DEBUG_RETURN(CBaseAnimating_DrawModel, rcx, flags);
const auto dwRetAddr = uintptr_t(_ReturnAddress());
const auto dwDesired = S::CEconEntity_DrawOverriddenViewmodel_DrawModel_Call();
if (dwRetAddr != dwDesired || I::EngineVGui->IsGameUIVisible() || SDK::CleanScreenshot()
|| F::CameraWindow.m_bDrawing || !F::Materials.m_bLoaded || G::Unload)
return CALL_ORIGINAL(rcx, flags);
s_bDrawingViewmodel = true;
int iReturn = CALL_ORIGINAL(rcx, flags);
s_bDrawingViewmodel = false;
return iReturn;
}
MAKE_HOOK(CBaseAnimating_InternalDrawModel, S::CBaseAnimating_InternalDrawModel(), int,
void* rcx, int flags)
{
DEBUG_RETURN(CBaseAnimating_InternalDrawModel, rcx, flags);
if (!s_bDrawingViewmodel || !(flags & STUDIO_RENDER))
return CALL_ORIGINAL(rcx, flags);
auto pRenderContext = I::MaterialSystem->GetRenderContext();
if (!pRenderContext)
if (!s_bDrawingViewmodel /*|| !(flags & STUDIO_RENDER)*/)
return CALL_ORIGINAL(rcx, flags);
int iReturn;
@@ -76,4 +52,19 @@ MAKE_HOOK(CBaseAnimating_InternalDrawModel, S::CBaseAnimating_InternalDrawModel(
return iReturn;
return CALL_ORIGINAL(rcx, 1);
}
MAKE_HOOK(CBaseViewModel_DrawModel, S::CBaseViewModel_DrawModel(), int,
void* rcx, int flags)
{
DEBUG_RETURN(CBaseAnimating_DrawModel, rcx, flags);
if (s_bDrawingViewmodel || I::EngineVGui->IsGameUIVisible() || SDK::CleanScreenshot()
|| F::CameraWindow.m_bDrawing || !F::Materials.m_bLoaded || G::Unload)
return CALL_ORIGINAL(rcx, flags);
s_bDrawingViewmodel = true;
int iReturn = CALL_ORIGINAL(rcx, flags);
s_bDrawingViewmodel = false;
return iReturn;
}
@@ -134,6 +134,10 @@ public:
return ent;
}
inline bool IsValid()
{
return entindex() != -1;
}
inline bool IsPlayer()
{
return GetClassID() == ETFClassID::CTFPlayer;
@@ -264,6 +268,21 @@ public:
}
return false;
}
inline bool IsWearableVM()
{
return GetClassID() == ETFClassID::CTFWearableVM;
}
inline bool IsViewmodel()
{
switch (GetClassID())
{
case ETFClassID::CBaseViewModel:
case ETFClassID::CTFViewModel:
case ETFClassID::CTFWearableVM:
return true;
}
return false;
}
VIRTUAL(GetPredDescMap, datamap_t*, 15, this);
//VIRTUAL(IsPlayer, bool, 132, this);