Skip to content

Commit

Permalink
Fix issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Frozen-H2O committed Nov 20, 2024
1 parent f46dc01 commit 82e3f7b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 72 deletions.
9 changes: 0 additions & 9 deletions src/detours.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@

#include "tier0/memdbgon.h"


extern CGlobalVars *gpGlobals;
extern CGameEntitySystem *g_pEntitySystem;
extern IGameEventManager2 *g_gameEventManager;
Expand Down Expand Up @@ -685,14 +684,6 @@ bool InitDetours(CGameConfig *gameConfig)

FOR_EACH_VEC(g_vecDetours, i)
{
if (!V_strcmp(g_vecDetours[i]->GetName(), "CEntityIOOutput_FireOutputInternal"))
{
// Check if features needing this detour are actually enabled.
// If not, leave this detour disabled for CS# compatibility
if (!IsButtonWatchEnabled())
continue;
}

if (!g_vecDetours[i]->CreateDetour(gameConfig))
success = false;

Expand Down
1 change: 1 addition & 0 deletions src/detours.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "cdetour.h"
#include <utlsymbollarge.h>


class CCheckTransmitInfo;
class IRecipientFilter;
class ISoundEmitterSystemBase;
Expand Down
113 changes: 50 additions & 63 deletions src/entities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

// #define ENTITY_HANDLER_ASSERTION

extern CCSGameRules* g_pGameRules;

class InputData_t
{
public:
Expand Down Expand Up @@ -724,15 +726,60 @@ void EntityHandler_OnEntitySpawned(CBaseEntity* pEntity)
CPointViewControlHandler::OnCreated(pEntity);
}

std::map <int, bool> mapRecentEnts;
CDetour<decltype(Detour_CEntityIOOutput_FireOutputInternal)>* CEntityIOOutput_FireOutputInternal = nullptr;
using IOCallback = std::function<void(const CEntityIOOutput*, CEntityInstance*, CEntityInstance*, const CVariant*, float)>;
// Add callback functions to this map that wish to hook into Detour_CEntityIOOutput_FireOutputInternal
// to make it more modular/cleaner than shoving everything into the detour (buttonwatch, entwatch, etc.)
std::map<std::string, IOCallback> mapIOFunctions;
void FASTCALL Detour_CEntityIOOutput_FireOutputInternal(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEntityInstance* pCaller, const CVariant* value, float flDelay)
{
for (const auto& [name, cb] : mapIOFunctions)
cb(pThis, pActivator, pCaller, value, flDelay);

(*CEntityIOOutput_FireOutputInternal)(pThis, pActivator, pCaller, value, flDelay);
}

// Tries to setup Detour_CEntityIOOutput_FireOutputInternal if it is not already setup.
// Returns true if detour is usable, otherwise false.
bool SetupFireOutputInternalDetour()
{
if (CEntityIOOutput_FireOutputInternal != nullptr)
return true;

CEntityIOOutput_FireOutputInternal = new CDetour(Detour_CEntityIOOutput_FireOutputInternal, "CEntityIOOutput_FireOutputInternal");
if (!CEntityIOOutput_FireOutputInternal->CreateDetour(g_GameConfig))
{
Msg("Failed to detour CEntityIOOutput_FireOutputInternal\n");
delete CEntityIOOutput_FireOutputInternal;
CEntityIOOutput_FireOutputInternal = nullptr;
return false;
}
CEntityIOOutput_FireOutputInternal->EnableDetour();
return true;
}

CON_COMMAND_F(cs2f_enable_button_watch, "CS# BREAKS IF THIS IS EVER ENABLED. Whether to enable button watch or not.", FCVAR_LINKED_CONCOMMAND | FCVAR_SPONLY | FCVAR_PROTECTED)
{
if (args.ArgC() < 2)
{
Msg("%s %i\n", args[0], IsButtonWatchEnabled());
return;
}

if (!V_StringToBool(args[1], false) || !SetupFireOutputInternalDetour())
mapIOFunctions.erase("buttonwatch");
else if (!IsButtonWatchEnabled())
mapIOFunctions["buttonwatch"] = ButtonWatch;
}

bool IsButtonWatchEnabled()
{
return std::any_of(vecIOFunctions.begin(), vecIOFunctions.end(), [](IOCallback& cb) {
return cb.target<decltype(ButtonWatch)>() == &ButtonWatch;
return std::any_of(mapIOFunctions.begin(), mapIOFunctions.end(), [](const auto& p) {
return p.first == "buttonwatch";
});
}

std::map <int, bool> mapRecentEnts;
void ButtonWatch(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEntityInstance* pCaller, const CVariant* value, float flDelay)
{
if (!IsButtonWatchEnabled() || V_stricmp(pThis->m_pDesc->m_pName, "OnPressed") ||
Expand Down Expand Up @@ -783,64 +830,4 @@ void ButtonWatch(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEnt
mapRecentEnts.erase(iIndex);
return -1.0f;
});
}

extern CCSGameRules* g_pGameRules;
// Tries to setup Detour_CEntityIOOutput_FireOutputInternal if it is not already setup.
// Returns true if detour is usable, otherwise false.
bool SetupFireOutputInternalDetour()
{
if (CEntityIOOutput_FireOutputInternal != nullptr)
return true;

CEntityIOOutput_FireOutputInternal = new CDetour(Detour_CEntityIOOutput_FireOutputInternal, "CEntityIOOutput_FireOutputInternal");
if (!CEntityIOOutput_FireOutputInternal->CreateDetour(g_GameConfig))
{
Msg("Failed to detour CEntityIOOutput_FireOutputInternal\n");
delete CEntityIOOutput_FireOutputInternal;
CEntityIOOutput_FireOutputInternal = nullptr;
return false;
}
CEntityIOOutput_FireOutputInternal->EnableDetour();
return true;
}

CON_COMMAND_F(cs2f_enable_button_watch, "CS# BREAKS IF THIS IS EVER ENABLED. Whether to enable button watch or not.", FCVAR_LINKED_CONCOMMAND | FCVAR_SPONLY | FCVAR_PROTECTED)
{
if (args.ArgC() < 2)
{
Msg("%s %b\n", args[0], IsButtonWatchEnabled());
return;
}

if (!V_StringToBool(args[1], false) || !SetupFireOutputInternalDetour())
{
vecIOFunctions.erase(std::remove_if(vecIOFunctions.begin(), vecIOFunctions.end(), [](const IOCallback& cb) {
return cb.target<decltype(ButtonWatch)>() == &ButtonWatch;
}), vecIOFunctions.end());
}
else if (!IsButtonWatchEnabled())
{
vecIOFunctions.push_back(ButtonWatch);
}
}

using IOCallback = std::function<void(const CEntityIOOutput*, CEntityInstance*, CEntityInstance*, const CVariant*, float)>;
// Add callback functions to this vector that wish to hook into Detour_CEntityIOOutput_FireOutputInternal
// to make it more modular/cleaner than shoving everything into the detour
std::vector<IOCallback> vecIOFunctions;
void FASTCALL Detour_CEntityIOOutput_FireOutputInternal(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEntityInstance* pCaller, const CVariant* value, float flDelay)
{
#ifdef DEBUG
// pCaller can absolutely be null. Needs to be checked
if(pCaller)
ConMsg("Output %s fired on %s\n", pThis->m_pDesc->m_pName, pCaller->GetClassname());
else
ConMsg("Output %s fired with no caller\n", pThis->m_pDesc->m_pName);
#endif

for (const auto& cb : vecIOFunctions)
cb(pThis, pActivator, pCaller, value, flDelay);

(*CEntityIOOutput_FireOutputInternal)(pThis, pActivator, pCaller, value, flDelay);
}

0 comments on commit 82e3f7b

Please sign in to comment.