Skip to content

Commit

Permalink
Experimental Hook
Browse files Browse the repository at this point in the history
  • Loading branch information
caxanga334 committed May 14, 2024
1 parent 62543ac commit 1a551df
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 26 deletions.
6 changes: 6 additions & 0 deletions extension/bot/basebot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
#include <util/helpers.h>
#include <util/entprops.h>
#include <util/librandom.h>
#include <util/Handle.h>
#include <bot/interfaces/base_interface.h>
#include <bot/interfaces/knownentity.h>
#include <bot/interfaces/playerinput.h>
#include <bot/interfaces/tasks.h>
#include <bot/interfaces/path/meshnavigator.h>
#include <mods/basemod.h>
#include <tier1/convar.h>
#include <takedamageinfo.h>
#include "basebot.h"

extern CGlobalVars* gpGlobals;
Expand Down Expand Up @@ -561,6 +563,10 @@ void CBaseBot::FirstSpawn()
{
}

void CBaseBot::OnTakeDamage_Alive(const CTakeDamageInfo& info)
{
}

/**
* @brief Selects weapon by using the IBotController::SetActiveWeapon function.
* This will call BCC's Weapon_Create, make sure the bot actually owns the weapon you want or the bot will magically get one.
Expand Down
2 changes: 2 additions & 0 deletions extension/bot/basebot.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class CBaseBot : public CBaseExtPlayer, public IEventListener
virtual void FirstSpawn();
// Called when the player_death event is fired for this bot
virtual void Killed() {}
// Called by the OnTakeDamage_Alive hook.
virtual void OnTakeDamage_Alive(const CTakeDamageInfo& info);
// Called to check if the bot can join the game
virtual bool CanJoinGame() { return true; }
// Called to check if the bot has joined a team and should be considerated as playing
Expand Down
114 changes: 91 additions & 23 deletions extension/extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,16 @@

// Need this for CUserCmd class definition
#include <usercmd.h>
#include <util/Handle.h>
#include <takedamageinfo.h>

/**
* @file extension.cpp
* @brief Implement extension code here.
*/



CGlobalVars* gpGlobals = nullptr;
IVDebugOverlay* debugoverlay = nullptr;
// IVEngineServer* engine = nullptr;
Expand Down Expand Up @@ -87,14 +91,14 @@ SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool);

// SDKs that requires a runplayercommand hook

SH_DECL_MANUALHOOK2_void(MH_PlayerRunCommand, 0, 0, 0, CUserCmd*, IMoveHelper*);

SH_DECL_MANUALHOOK2_void(MH_PlayerRunCommand, 0, 0, 0, CUserCmd*, IMoveHelper*)
SH_DECL_MANUALHOOK1(MH_CBasePlayer_OnTakeDamage_Alive, 0, 0, 0, int, const CTakeDamageInfo&)

SMEXT_LINK(&g_NavBotExt);

namespace Utils
{
inline void CreateDataDirectory(const char* mod)
inline static void CreateDataDirectory(const char* mod)
{
char fullpath[PLATFORM_MAX_PATH + 1];
smutils->BuildPath(SourceMod::Path_SM, fullpath, sizeof(fullpath), "data/navbot/%s", mod);
Expand All @@ -116,7 +120,7 @@ namespace Utils
}
}

inline void CreateConfigDirectory(const char* mod)
inline static void CreateConfigDirectory(const char* mod)
{
char fullpath[PLATFORM_MAX_PATH + 1];
smutils->BuildPath(SourceMod::Path_SM, fullpath, sizeof(fullpath), "configs/navbot/%s", mod);
Expand All @@ -138,7 +142,7 @@ namespace Utils
}
}

inline void CopyBotCmdtoUserCmd(CUserCmd* ucmd, CBotCmd* bcmd)
inline static void CopyBotCmdtoUserCmd(CUserCmd* ucmd, CBotCmd* bcmd)
{
ucmd->command_number = bcmd->command_number;
ucmd->tick_count = bcmd->tick_count;
Expand All @@ -158,6 +162,7 @@ bool NavBotExt::SDK_OnLoad(char* error, size_t maxlen, bool late)
{
extension = this;
m_hookruncmd = false;
m_hasbaseplayerhooks = true; // we will always hook these, set to false on gamedata failure
m_gamedata = nullptr;
randomgen->ReSeed(); // set the initial seed based on the clock

Expand Down Expand Up @@ -203,18 +208,31 @@ bool NavBotExt::SDK_OnLoad(char* error, size_t maxlen, bool late)
}
}

gameconfs->CloseGameConfigFile(gamedata);
SH_MANUALHOOK_RECONFIGURE(MH_PlayerRunCommand, offset, 0, 0);
gameconfs->CloseGameConfigFile(gamedata);
gamedata = nullptr;


if (gameconfs->LoadGameConfigFile("sdkhooks.games", &gamedata, error, maxlen))
{
offset = 0;
if (gamedata->GetOffset("OnTakeDamage_Alive", &offset))
{
SH_MANUALHOOK_RECONFIGURE(MH_CBasePlayer_OnTakeDamage_Alive, offset, 0, 0);
}
else
{
m_hasbaseplayerhooks = false;
smutils->LogError(myself, "Failed to get CBaseEntity::OnTakeDamage_Alive vtable offset from SDKHooks gamedata!");
}
}

// This stuff needs to be after any load failures so we don't causes other stuff to crash
ConVar_Register(0, this);
playerhelpers->AddClientListener(this);
sharesys->AddDependency(myself, "bintools.ext", true, true);
sharesys->AddDependency(myself, "sdktools.ext", true, true);
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);

return true;
}

Expand Down Expand Up @@ -278,9 +296,17 @@ bool NavBotExt::SDK_OnMetamodLoad(ISmmAPI* ismm, char* error, size_t maxlen, boo
GET_V_IFACE_CURRENT(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
GET_V_IFACE_CURRENT(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION);

#ifndef __linux__
#ifdef WIN32
GET_V_IFACE_CURRENT(GetEngineFactory, debugoverlay, IVDebugOverlay, VDEBUG_OVERLAY_INTERFACE_VERSION);
#else
GET_V_IFACE_CURRENT(GetEngineFactory, debugoverlay, IVDebugOverlay, VDEBUG_OVERLAY_INTERFACE_VERSION);
#endif

if (!debugoverlay && !engine->IsDedicatedServer())
{
// Report if debug overlay is not available on a Linux listen server
smutils->LogError(myself, "Failed to get %s interface. NavMesh drawing will be unavailable.", VDEBUG_OVERLAY_INTERFACE_VERSION);
}
#endif // WIN32

GET_V_IFACE_CURRENT(GetServerFactory, botmanager, IBotManager, INTERFACEVERSION_PLAYERBOTMANAGER);

Expand Down Expand Up @@ -319,31 +345,41 @@ void NavBotExt::OnClientPutInServer(int client)
{
extmanager->OnClientPutInServer(client);

#ifdef HOOK_PLAYERRUNCMD
CBaseEntity* baseent = nullptr;
UtilHelpers::IndexToAThings(client, &baseent, nullptr);

if (baseent != nullptr)
{
SH_ADD_MANUALHOOK(MH_PlayerRunCommand, baseent, SH_MEMBER(this, &NavBotExt::Hook_PlayerRunCommand), false);
}
#endif // HOOK_PLAYERRUNCMD
if (m_hookruncmd)
{
SH_ADD_MANUALHOOK(MH_PlayerRunCommand, baseent, SH_MEMBER(this, &NavBotExt::Hook_PlayerRunCommand), false);
}

if (m_hasbaseplayerhooks)
{
SH_ADD_MANUALHOOK(MH_CBasePlayer_OnTakeDamage_Alive, baseent, SH_MEMBER(this, &NavBotExt::Hook_CBaseEntity_OnTakeDamage_Alive), false);
}
}
}

void NavBotExt::OnClientDisconnecting(int client)
{
extmanager->OnClientDisconnect(client);

#ifdef HOOK_PLAYERRUNCMD
CBaseEntity* baseent = nullptr;
UtilHelpers::IndexToAThings(client, &baseent, nullptr);

if (baseent != nullptr)
{
SH_REMOVE_MANUALHOOK(MH_PlayerRunCommand, baseent, SH_MEMBER(this, &NavBotExt::Hook_PlayerRunCommand), false);
if (m_hookruncmd)
{
SH_REMOVE_MANUALHOOK(MH_PlayerRunCommand, baseent, SH_MEMBER(this, &NavBotExt::Hook_PlayerRunCommand), false);
}

if (m_hasbaseplayerhooks)
{
SH_REMOVE_MANUALHOOK(MH_CBasePlayer_OnTakeDamage_Alive, baseent, SH_MEMBER(this, &NavBotExt::Hook_CBaseEntity_OnTakeDamage_Alive), false);
}
}
#endif // HOOK_PLAYERRUNCMD
}

void NavBotExt::Hook_GameFrame(bool simulating)
Expand Down Expand Up @@ -373,19 +409,51 @@ void NavBotExt::Hook_PlayerRunCommand(CUserCmd* usercmd, IMoveHelper* movehelper
RETURN_META(MRES_IGNORED);
}

static CBaseBot* bot;
CBaseBot* bot;
CBaseEntity* player = META_IFACEPTR(CBaseEntity);
int index = gamehelpers->EntityToBCompatRef(player);

bot = extmanager->GetBotByIndex(index);

if (bot != nullptr)
{
static CBotCmd* cmd;
cmd = bot->GetUserCommand();

CBotCmd* cmd = bot->GetUserCommand();
Utils::CopyBotCmdtoUserCmd(usercmd, cmd);
}

RETURN_META(MRES_IGNORED);
}
}

int NavBotExt::Hook_CBaseEntity_OnTakeDamage_Alive(const CTakeDamageInfo& info)
{
CBaseEntity* victim = META_IFACEPTR(CBaseEntity);
int index = gamehelpers->EntityToBCompatRef(victim);

CBaseBot* bot = extmanager->GetBotByIndex(index);

if (bot)
{
bot->OnTakeDamage_Alive(info);
}

#ifdef EXT_DEBUG
CBaseEntity* attacker = info.GetAttacker();
CBaseEntity* inflictor = info.GetInflictor();

char message[256]{};

if (attacker)
{
auto classname = gamehelpers->GetEntityClassname(attacker);

if (classname && classname[0])
{
ke::SafeSprintf(message, sizeof(message), "%p <%s> %p", attacker, classname, inflictor);
}
}

rootconsole->ConsolePrint("%s", message);
#endif // EXT_DEBUG

RETURN_META_VALUE(MRES_IGNORED, 0);
}
3 changes: 3 additions & 0 deletions extension/extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

class CUserCmd;
class IMoveHelper;
class CTakeDamageInfo;

/**
* @file extension.h
Expand Down Expand Up @@ -279,12 +280,14 @@ class NavBotExt : public SDKExtension, public IConCommandBaseAccessor, public So

void Hook_GameFrame(bool simulating);
void Hook_PlayerRunCommand(CUserCmd* usercmd, IMoveHelper* movehelper) const;
int Hook_CBaseEntity_OnTakeDamage_Alive(const CTakeDamageInfo& info);

inline bool ShouldCallRunPlayerCommand() const { return !m_hookruncmd; }
inline SourceMod::IGameConfig* GetExtensionGameData() { return m_gamedata; }

private:
bool m_hookruncmd;
bool m_hasbaseplayerhooks; // true if we have gamedata for ontakedamage and other hooks
SourceMod::IGameConfig* m_gamedata;
};

Expand Down
1 change: 1 addition & 0 deletions extension/extplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class CNavArea;
class CBaseBot;
class CTakeDamageInfo;

#include <eiface.h>
#include <iplayerinfo.h>
Expand Down
7 changes: 4 additions & 3 deletions extension/util/Handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <basehandle.h>

class CBaseEntity;

// -------------------------------------------------------------------------------------------------- //
// CHandle.
// -------------------------------------------------------------------------------------------------- //
Expand Down Expand Up @@ -46,7 +48,7 @@ class CHandle: public CBaseHandle {
}

void Set(const T* pVal) {
CBaseHandle::Set(dynamic_cast<const IHandleEntity*>(pVal));
CBaseHandle::Set(reinterpret_cast<const IHandleEntity*>(pVal));
}
operator T*() {
return Get();
Expand Down Expand Up @@ -78,7 +80,6 @@ class CHandle: public CBaseHandle {
}
};



typedef CHandle<CBaseEntity> EHANDLE;

#endif /* UTILS_VALVE_NAVMESH_HANDLE_H_ */

0 comments on commit 1a551df

Please sign in to comment.