Clean up TF2 ext CalcCritical code (bug 5894, r=voided).
This commit is contained in:
parent
c80e0a964f
commit
dde1deb6bc
@ -32,330 +32,169 @@
|
|||||||
#include "criticals.h"
|
#include "criticals.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
IServerGameEnts *gameents = NULL;
|
CritManager g_CritManager;
|
||||||
|
|
||||||
CDetour *calcIsAttackCriticalDetour = NULL;
|
IForward *g_critForward = nullptr;
|
||||||
CDetour *calcIsAttackCriticalMeleeDetour = NULL;
|
|
||||||
CDetour *calcIsAttackCriticalBowDetour = NULL;
|
|
||||||
CDetour *calcIsAttackCriticalKnifeDetour = NULL;
|
|
||||||
CDetour *calcIsAttackCriticalNoCritsDetour = NULL;
|
|
||||||
CDetour *calcIsAttackCriticalNoCritsMeleeDetour = NULL;
|
|
||||||
|
|
||||||
int nextMeleeCritOffset = -1;
|
SH_DECL_MANUALHOOK0(CalcIsAttackCriticalHelper, 0, 0, 0, bool);
|
||||||
|
SH_DECL_MANUALHOOK0(CalcIsAttackCriticalHelperNoCrits, 0, 0, 0, bool);
|
||||||
|
|
||||||
IForward *g_critForward = NULL;
|
const char TF_WEAPON_DATATABLE[] = "DT_TFWeaponBase";
|
||||||
|
|
||||||
enum DetourResult
|
CritManager::CritManager() :
|
||||||
|
m_enabled(false),
|
||||||
|
m_hooksSetup(false)
|
||||||
{
|
{
|
||||||
Result_Ignore,
|
m_entsHooked.Init();
|
||||||
Result_NoCrit,
|
|
||||||
Result_Crit,
|
|
||||||
};
|
|
||||||
|
|
||||||
int CheckBaseHandle(CBaseHandle &hndl)
|
|
||||||
{
|
|
||||||
if (!hndl.IsValid())
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = hndl.GetEntryIndex();
|
|
||||||
|
|
||||||
edict_t *pStoredEdict;
|
|
||||||
|
|
||||||
pStoredEdict = engine->PEntityOfEntIndex(index);
|
|
||||||
|
|
||||||
if (pStoredEdict == NULL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
IServerEntity *pSE = pStoredEdict->GetIServerEntity();
|
|
||||||
|
|
||||||
if (pSE == NULL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSE->GetRefEHandle() != hndl)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DetourResult DetourCallback(CBaseEntity *pEnt, bool bMeleeNoCrits)
|
bool CritManager::TryEnable()
|
||||||
{
|
{
|
||||||
edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)pEnt);
|
if (!m_hooksSetup)
|
||||||
|
|
||||||
if (!pEdict)
|
|
||||||
{
|
{
|
||||||
g_pSM->LogMessage(myself, "Entity Error");
|
int offset;
|
||||||
return Result_Ignore;
|
|
||||||
|
if (!g_pGameConf->GetOffset("CalcIsAttackCriticalHelper", &offset))
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "Failed to find CalcIsAttackCriticalHelper offset");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SH_MANUALHOOK_RECONFIGURE(CalcIsAttackCriticalHelper, offset, 0, 0);
|
||||||
|
|
||||||
|
if (!g_pGameConf->GetOffset("CalcIsAttackCriticalHelperNoCrits", &offset))
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "Failed to find CalcIsAttackCriticalHelperNoCrits offset");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SH_MANUALHOOK_RECONFIGURE(CalcIsAttackCriticalHelperNoCrits, offset, 0, 0);
|
||||||
|
|
||||||
|
m_hooksSetup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = playerhelpers->GetMaxClients() + 1; i < MAX_EDICTS; ++i)
|
||||||
|
{
|
||||||
|
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
|
||||||
|
if (pEntity == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||||
|
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
|
||||||
|
if (!pNetworkable)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
|
||||||
|
m_entsHooked.Set(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enabled = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CritManager::Disable()
|
||||||
|
{
|
||||||
|
int i = m_entsHooked.FindNextSetBit(playerhelpers->GetMaxClients() + 1);
|
||||||
|
for (i; i != -1; i = m_entsHooked.FindNextSetBit(i))
|
||||||
|
{
|
||||||
|
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
|
||||||
|
SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
|
||||||
|
m_entsHooked.Set(i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CritManager::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||||
|
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
|
||||||
|
if (!pNetworkable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
|
||||||
|
m_entsHooked.Set(gamehelpers->EntityToBCompatRef(pEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CritManager::OnEntityDestroyed(CBaseEntity *pEntity)
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int index = gamehelpers->EntityToBCompatRef(pEntity);
|
||||||
|
if (index < 0 || index >= MAX_EDICTS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_entsHooked.IsBitSet(index))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelpers), false);
|
||||||
|
|
||||||
|
m_entsHooked.Set(index, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CritManager::Hook_CalcIsAttackCriticalHelpers()
|
||||||
|
{
|
||||||
|
CBaseEntity *pWeapon = META_IFACEPTR(CBaseEntity);
|
||||||
|
|
||||||
|
// If there's an invalid ent or invalid networkable here, we've got issues elsewhere.
|
||||||
|
|
||||||
|
IServerNetworkable *pNetWeapon = ((IServerUnknown *)pWeapon)->GetNetworkable();
|
||||||
|
ServerClass *pServerClass = pNetWeapon->GetServerClass();
|
||||||
|
if (!pServerClass)
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "Invalid server class on weapon.");
|
||||||
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sm_sendprop_info_t info;
|
sm_sendprop_info_t info;
|
||||||
|
if (!gamehelpers->FindSendPropInfo(pServerClass->GetName(), "m_hOwnerEntity", &info))
|
||||||
if (!gamehelpers->FindSendPropInfo(pEdict->GetNetworkable()->GetServerClass()->GetName(), "m_hOwnerEntity", &info))
|
|
||||||
{
|
{
|
||||||
g_pSM->LogMessage(myself, "Offset Error");
|
g_pSM->LogError(myself, "Could not find m_hOwnerEntity on %s", pServerClass->GetName());
|
||||||
return Result_Ignore;
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_critForward)
|
int returnValue = 0;
|
||||||
|
|
||||||
|
int ownerIndex = -1;
|
||||||
|
CBaseHandle &hndl = *(CBaseHandle *) ((intptr_t)pWeapon + info.actual_offset);
|
||||||
|
CBaseEntity *pHandleEntity = gamehelpers->ReferenceToEntity(hndl.GetEntryIndex());
|
||||||
|
|
||||||
|
if (pHandleEntity != nullptr && hndl == reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
|
||||||
{
|
{
|
||||||
g_pSM->LogMessage(myself, "Invalid Forward");
|
ownerIndex = hndl.GetEntryIndex();
|
||||||
return Result_Ignore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int returnValue=0;
|
g_critForward->PushCell(ownerIndex); //Client index
|
||||||
|
g_critForward->PushCell(gamehelpers->EntityToBCompatRef(pWeapon)); // Weapon index
|
||||||
CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEnt + info.actual_offset);
|
g_critForward->PushString(gamehelpers->GetEntityClassname(pWeapon)); //Weapon classname
|
||||||
int index = CheckBaseHandle(hndl);
|
|
||||||
|
|
||||||
//Skip CTFWeaponBaseMelee::CalcIsAttackCriticalHelperNoCrits if m_iNextMeleeCrit is not 2
|
|
||||||
if (bMeleeNoCrits)
|
|
||||||
{
|
|
||||||
CBaseEntity *pPlayer = UTIL_GetCBaseEntity(index, true);
|
|
||||||
if (pPlayer && *(uint32_t *)((intptr_t)pPlayer + nextMeleeCritOffset) != 2)
|
|
||||||
return Result_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_critForward->PushCell(index); //Client index
|
|
||||||
g_critForward->PushCell(engine->IndexOfEdict(pEdict)); // Weapon index
|
|
||||||
g_critForward->PushString(pEdict->GetClassName()); //Weapon classname
|
|
||||||
g_critForward->PushCellByRef(&returnValue); //return value
|
g_critForward->PushCellByRef(&returnValue); //return value
|
||||||
|
|
||||||
cell_t result = 0;
|
cell_t result = 0;
|
||||||
|
|
||||||
g_critForward->Execute(&result);
|
g_critForward->Execute(&result);
|
||||||
|
|
||||||
if (result)
|
if (result && returnValue)
|
||||||
{
|
{
|
||||||
if (returnValue)
|
RETURN_META_VALUE(MRES_SUPERCEDE, true);
|
||||||
{
|
|
||||||
return Result_Crit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Result_NoCrit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Result_Ignore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperMelee, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, false);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperMelee)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelper, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, false);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelper)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperBow, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, false);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperBow)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperKnife, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, false);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperKnife)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperNoCrits, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, false);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperNoCrits)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER0(CalcIsAttackCriticalHelperNoCritsMelee, bool)
|
|
||||||
{
|
|
||||||
DetourResult result = DetourCallback((CBaseEntity *)this, true);
|
|
||||||
|
|
||||||
if (result == Result_Ignore)
|
|
||||||
{
|
|
||||||
return DETOUR_MEMBER_CALL(CalcIsAttackCriticalHelperNoCritsMelee)();
|
|
||||||
}
|
|
||||||
else if (result == Result_NoCrit)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InitialiseCritDetours()
|
|
||||||
{
|
|
||||||
sm_sendprop_info_t prop;
|
|
||||||
|
|
||||||
calcIsAttackCriticalDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelper, "CalcCritical");
|
|
||||||
calcIsAttackCriticalMeleeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperMelee, "CalcCriticalMelee");
|
|
||||||
calcIsAttackCriticalBowDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperBow, "CalcCriticalBow");
|
|
||||||
calcIsAttackCriticalKnifeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperKnife, "CalcCriticalKnife");
|
|
||||||
calcIsAttackCriticalNoCritsDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperNoCrits, "CalcCriticalNoCrits");
|
|
||||||
calcIsAttackCriticalNoCritsMeleeDetour = DETOUR_CREATE_MEMBER(CalcIsAttackCriticalHelperNoCritsMelee, "CalcCriticalNoCritsMelee");
|
|
||||||
|
|
||||||
bool HookCreated = false;
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalDetour->EnableDetour();
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalMeleeDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalMeleeDetour->EnableDetour();
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalBowDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalBowDetour->EnableDetour();
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalKnifeDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalKnifeDetour->EnableDetour();
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalNoCritsDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalNoCritsDetour->EnableDetour();
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalNoCritsMeleeDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalNoCritsMeleeDetour->EnableDetour();
|
|
||||||
if (!gamehelpers->FindSendPropInfo("CTFPlayer", "m_iNextMeleeCrit", &prop))
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Failed to find m_iNextMeleeCrit prop offset");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nextMeleeCritOffset = prop.actual_offset;
|
|
||||||
HookCreated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HookCreated)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pSM->LogError(myself, "No critical hit forwards could be initialized - Disabled critical hit hooks");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveCritDetours()
|
|
||||||
{
|
|
||||||
if (calcIsAttackCriticalDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalDetour->Destroy();
|
|
||||||
calcIsAttackCriticalDetour = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalMeleeDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalMeleeDetour->Destroy();
|
|
||||||
calcIsAttackCriticalMeleeDetour = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalBowDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalBowDetour->Destroy();
|
|
||||||
calcIsAttackCriticalBowDetour = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calcIsAttackCriticalKnifeDetour != NULL)
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
{
|
|
||||||
calcIsAttackCriticalKnifeDetour->Destroy();
|
|
||||||
calcIsAttackCriticalKnifeDetour = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalNoCritsDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalNoCritsDetour->Destroy();
|
|
||||||
calcIsAttackCriticalNoCritsDetour = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calcIsAttackCriticalNoCritsMeleeDetour != NULL)
|
|
||||||
{
|
|
||||||
calcIsAttackCriticalNoCritsMeleeDetour->Destroy();
|
|
||||||
calcIsAttackCriticalNoCritsMeleeDetour = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,38 @@
|
|||||||
#include <jit/jit_helpers.h>
|
#include <jit/jit_helpers.h>
|
||||||
#include <jit/x86/x86_macros.h>
|
#include <jit/x86/x86_macros.h>
|
||||||
#include "CDetour/detours.h"
|
#include "CDetour/detours.h"
|
||||||
|
#include "ISDKHooks.h"
|
||||||
|
|
||||||
bool InitialiseCritDetours();
|
class CritManager : public ISMEntityListener
|
||||||
void RemoveCritDetours();
|
{
|
||||||
|
public:
|
||||||
|
CritManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool TryEnable();
|
||||||
|
void Disable();
|
||||||
|
|
||||||
|
// ISMEntityListener
|
||||||
|
public:
|
||||||
|
virtual void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
|
||||||
|
virtual void OnEntityDestroyed(CBaseEntity *pEntity);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void HookEntityIfWeapon(CBaseEntity *pEntity);
|
||||||
|
void UnhookEntityIfHooked(CBaseEntity *pEntity);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CritHook
|
||||||
|
bool Hook_CalcIsAttackCriticalHelpers();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_enabled;
|
||||||
|
bool m_hooksSetup;
|
||||||
|
CBitVec<MAX_EDICTS> m_entsHooked;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CritManager g_CritManager;
|
||||||
|
|
||||||
extern IForward *g_critForward;
|
extern IForward *g_critForward;
|
||||||
|
|
||||||
extern IServerGameEnts *gameents;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CRITICALS_H_
|
#endif //_INCLUDE_SOURCEMOD_CRITICALS_H_
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "gameplayrules.h"
|
#include "gameplayrules.h"
|
||||||
#include "teleporter.h"
|
#include "teleporter.h"
|
||||||
#include "CDetour/detours.h"
|
#include "CDetour/detours.h"
|
||||||
|
#include "ISDKHooks.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file extension.cpp
|
* @file extension.cpp
|
||||||
@ -52,6 +53,7 @@ TF2Tools g_TF2Tools;
|
|||||||
IGameConfig *g_pGameConf = NULL;
|
IGameConfig *g_pGameConf = NULL;
|
||||||
|
|
||||||
IBinTools *g_pBinTools = NULL;
|
IBinTools *g_pBinTools = NULL;
|
||||||
|
ISDKHooks *g_pSDKHooks = NULL;
|
||||||
|
|
||||||
SMEXT_LINK(&g_TF2Tools);
|
SMEXT_LINK(&g_TF2Tools);
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||||
|
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
|
||||||
|
|
||||||
char conf_error[255] = "";
|
char conf_error[255] = "";
|
||||||
if (!gameconfs->LoadGameConfigFile("sm-tf2.games", &g_pGameConf, conf_error, sizeof(conf_error)))
|
if (!gameconfs->LoadGameConfigFile("sm-tf2.games", &g_pGameConf, conf_error, sizeof(conf_error)))
|
||||||
@ -151,8 +154,6 @@ bool TF2Tools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool
|
|||||||
|
|
||||||
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
|
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
|
||||||
|
|
||||||
GET_V_IFACE_CURRENT(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
|
|
||||||
|
|
||||||
GET_V_IFACE_CURRENT(GetEngineFactory, m_GameEventManager, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2);
|
GET_V_IFACE_CURRENT(GetEngineFactory, m_GameEventManager, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2);
|
||||||
m_GameEventManager->AddListener(this, "teamplay_restart_round", true);
|
m_GameEventManager->AddListener(this, "teamplay_restart_round", true);
|
||||||
|
|
||||||
@ -177,11 +178,22 @@ void TF2Tools::SDK_OnUnload()
|
|||||||
forwards->ReleaseForward(g_waitingPlayersStartForward);
|
forwards->ReleaseForward(g_waitingPlayersStartForward);
|
||||||
forwards->ReleaseForward(g_waitingPlayersEndForward);
|
forwards->ReleaseForward(g_waitingPlayersEndForward);
|
||||||
forwards->ReleaseForward(g_teleportForward);
|
forwards->ReleaseForward(g_teleportForward);
|
||||||
|
|
||||||
|
if (g_pSDKHooks != nullptr)
|
||||||
|
{
|
||||||
|
g_pSDKHooks->RemoveEntityListener(&g_CritManager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TF2Tools::SDK_OnAllLoaded()
|
void TF2Tools::SDK_OnAllLoaded()
|
||||||
{
|
{
|
||||||
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
||||||
|
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
|
||||||
|
|
||||||
|
if (g_pSDKHooks != nullptr)
|
||||||
|
{
|
||||||
|
g_pSDKHooks->AddEntityListener(&g_CritManager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TF2Tools::RegisterConCommandBase(ConCommandBase *pVar)
|
bool TF2Tools::RegisterConCommandBase(ConCommandBase *pVar)
|
||||||
@ -198,6 +210,7 @@ void TF2Tools::FireGameEvent( IGameEvent *event )
|
|||||||
bool TF2Tools::QueryRunning(char *error, size_t maxlength)
|
bool TF2Tools::QueryRunning(char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
|
SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
|
||||||
|
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -209,6 +222,11 @@ bool TF2Tools::QueryInterfaceDrop(SMInterface *pInterface)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pInterface == g_pSDKHooks)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return IExtensionInterface::QueryInterfaceDrop(pInterface);
|
return IExtensionInterface::QueryInterfaceDrop(pInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +339,7 @@ void TF2Tools::OnPluginLoaded(IPlugin *plugin)
|
|||||||
{
|
{
|
||||||
if (!m_CritDetoursEnabled && g_critForward->GetFunctionCount())
|
if (!m_CritDetoursEnabled && g_critForward->GetFunctionCount())
|
||||||
{
|
{
|
||||||
m_CritDetoursEnabled = InitialiseCritDetours();
|
m_CritDetoursEnabled = g_CritManager.TryEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_IsHolidayDetourEnabled && g_isHolidayForward->GetFunctionCount())
|
if (!m_IsHolidayDetourEnabled && g_isHolidayForward->GetFunctionCount())
|
||||||
@ -353,7 +371,7 @@ void TF2Tools::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
{
|
{
|
||||||
if (m_CritDetoursEnabled && !g_critForward->GetFunctionCount())
|
if (m_CritDetoursEnabled && !g_critForward->GetFunctionCount())
|
||||||
{
|
{
|
||||||
RemoveCritDetours();
|
g_CritManager.Disable();
|
||||||
m_CritDetoursEnabled = false;
|
m_CritDetoursEnabled = false;
|
||||||
}
|
}
|
||||||
if (m_IsHolidayDetourEnabled && !g_isHolidayForward->GetFunctionCount())
|
if (m_IsHolidayDetourEnabled && !g_isHolidayForward->GetFunctionCount())
|
||||||
|
@ -88,6 +88,38 @@ bool UTIL_FindDataTable(SendTable *pTable,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UTIL_ContainsDataTable(SendTable *pTable, const char *name)
|
||||||
|
{
|
||||||
|
const char *pname = pTable->GetName();
|
||||||
|
int props = pTable->GetNumProps();
|
||||||
|
SendProp *prop;
|
||||||
|
SendTable *table;
|
||||||
|
|
||||||
|
if (pname && strcmp(name, pname) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; i < props; i++)
|
||||||
|
{
|
||||||
|
prop = pTable->GetProp(i);
|
||||||
|
|
||||||
|
if ((table = prop->GetDataTable()) != NULL)
|
||||||
|
{
|
||||||
|
pname = table->GetName();
|
||||||
|
if (pname && strcmp(name, pname) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UTIL_ContainsDataTable(table, name))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ServerClass *UTIL_FindServerClass(const char *classname)
|
ServerClass *UTIL_FindServerClass(const char *classname)
|
||||||
{
|
{
|
||||||
ServerClass *sc = gamedll->GetAllServerClasses();
|
ServerClass *sc = gamedll->GetAllServerClasses();
|
||||||
|
@ -49,6 +49,8 @@ bool UTIL_FindDataTable(SendTable *pTable,
|
|||||||
sm_sendprop_info_t *info,
|
sm_sendprop_info_t *info,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
|
|
||||||
|
bool UTIL_ContainsDataTable(SendTable *pTable, const char *name);
|
||||||
|
|
||||||
ServerClass *UTIL_FindServerClass(const char *classname);
|
ServerClass *UTIL_FindServerClass(const char *classname);
|
||||||
|
|
||||||
CBaseEntity *UTIL_GetCBaseEntity(int num, bool onlyPlayers);
|
CBaseEntity *UTIL_GetCBaseEntity(int num, bool onlyPlayers);
|
||||||
|
@ -36,48 +36,6 @@
|
|||||||
"linux" "@_ZN15CTFPlayerShared8DisguiseEiiP9CTFPlayerb"
|
"linux" "@_ZN15CTFPlayerShared8DisguiseEiiP9CTFPlayerb"
|
||||||
"mac" "@_ZN15CTFPlayerShared8DisguiseEiiP9CTFPlayerb"
|
"mac" "@_ZN15CTFPlayerShared8DisguiseEiiP9CTFPlayerb"
|
||||||
}
|
}
|
||||||
"CalcCritical"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN13CTFWeaponBase26CalcIsAttackCriticalHelperEv"
|
|
||||||
"mac" "@_ZN13CTFWeaponBase26CalcIsAttackCriticalHelperEv"
|
|
||||||
"windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x6A\x00\x68\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\x6A\x00\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x50\xE8\x2A\x2A\x2A\x2A\x8B\xF8\x83\xC4\x2A\x85\xFF\x74\x2A\x8B"
|
|
||||||
}
|
|
||||||
"CalcCriticalMelee"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN18CTFWeaponBaseMelee26CalcIsAttackCriticalHelperEv"
|
|
||||||
"mac" "@_ZN18CTFWeaponBaseMelee26CalcIsAttackCriticalHelperEv"
|
|
||||||
"windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x8B\xD8\x85\xDB\x74\x10"
|
|
||||||
}
|
|
||||||
"CalcCriticalBow"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN14CTFCompoundBow26CalcIsAttackCriticalHelperEv"
|
|
||||||
"mac" "@_ZN14CTFCompoundBow26CalcIsAttackCriticalHelperEv"
|
|
||||||
"windows" "\xE8\x2A\x2A\x2A\x2A\x85\xC0\x74\x2A\x8D\x88\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A\xB0"
|
|
||||||
}
|
|
||||||
"CalcCriticalKnife"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN8CTFKnife26CalcIsAttackCriticalHelperEv"
|
|
||||||
"mac" "@_ZN8CTFKnife26CalcIsAttackCriticalHelperEv"
|
|
||||||
"windows" "\x8B\x81\x54\x07\x00\x00\x83\xF8\xFF\x74\x2A\x8B\x15\x2A\x2A\x2A\x2A\x8B\xC8\x81\xE1\xFF\x0F\x00\x00\x03\xC9\x8D\x4C\xCA\x04\xC1\xE8\x0C\x39\x41\x04\x75\x2A\x8B\x01"
|
|
||||||
}
|
|
||||||
"CalcCriticalNoCrits"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN13CTFWeaponBase33CalcIsAttackCriticalHelperNoCritsEv"
|
|
||||||
"mac" "@_ZN13CTFWeaponBase33CalcIsAttackCriticalHelperNoCritsEv"
|
|
||||||
"windows" "\x56\x6A\x00\x68\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\x6A\x00\xE8\x2A\x2A\x2A\x2A\x50\xE8\x2A\x2A\x2A\x2A\x8B\xF0\x83\xC4\x14\x85\xF6\x74\x2A"
|
|
||||||
}
|
|
||||||
"CalcCriticalNoCritsMelee"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"linux" "@_ZN18CTFWeaponBaseMelee33CalcIsAttackCriticalHelperNoCritsEv"
|
|
||||||
"mac" "@_ZN18CTFWeaponBaseMelee33CalcIsAttackCriticalHelperNoCritsEv"
|
|
||||||
"windows" "\x56\x57\x8B\xF9\xE8\x2A\x2A\x2A\x2A\x8B\xF0\x85\xF6\x74\x2A\x8B\x06\x8B\x90\x40\x01\x00\x00\x8B\xCE\xFF\xD2\x84\xC0\x75\x2A\x5F\x32\xC0\x5E\xC3\x83\xBE\x80\x1D\x00\x00\x02"
|
|
||||||
}
|
|
||||||
"Regenerate"
|
"Regenerate"
|
||||||
{
|
{
|
||||||
"library" "server"
|
"library" "server"
|
||||||
@ -157,6 +115,18 @@
|
|||||||
"linux" "325"
|
"linux" "325"
|
||||||
"mac" "325"
|
"mac" "325"
|
||||||
}
|
}
|
||||||
|
"CalcIsAttackCriticalHelper"
|
||||||
|
{
|
||||||
|
"windows" "381"
|
||||||
|
"linux" "388"
|
||||||
|
"mac" "388"
|
||||||
|
}
|
||||||
|
"CalcIsAttackCriticalHelperNoCrits"
|
||||||
|
{
|
||||||
|
"windows" "382"
|
||||||
|
"linux" "389"
|
||||||
|
"mac" "389"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user