Skip to content

Commit

Permalink
Migrate To SourceHooks
Browse files Browse the repository at this point in the history
Use SourceHooks instead of game events.
  • Loading branch information
caxanga334 committed May 15, 2024
1 parent 1a551df commit afabac7
Show file tree
Hide file tree
Showing 23 changed files with 429 additions and 225 deletions.
1 change: 1 addition & 0 deletions PackageScript
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ CopyFiles('extension', 'addons/sourcemod/extensions',
CopyFiles('gamedata/navbot.games', 'addons/sourcemod/gamedata/navbot.games',
[ 'common.games.txt',
'game.dod.txt',
'game.tf.txt',
'master.games.txt'
]
)
Expand Down
3 changes: 2 additions & 1 deletion extension/AMBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ sourceFiles = [
'sdkports/debugoverlay_shared.cpp',
'sdkports/studio.cpp',
'sdkports/gametrace_server.cpp',
'sdkports/sdk_ehandle.cpp',
'entities/baseentity.cpp',
'entities/basecombatchar.cpp',
'entities/basecombatweapon.cpp',
Expand All @@ -35,7 +36,6 @@ sourceFiles = [
# Utility
'util/BaseEntity.cpp',
'util/EntityUtils.cpp',
'util/Handle.cpp',
'util/SimpleException.cpp',
'util/UtilTrace.cpp',
'util/entprops.cpp',
Expand All @@ -56,6 +56,7 @@ sourceFiles = [
'bot/interfaces/path/meshnavigator.cpp',
'bot/basebot.cpp',
'bot/basebot_debug.cpp',
'bot/basebot_hooks.cpp',
'concommands_bots.cpp',
'concommands_debug.cpp',
# TF2 Bot
Expand Down
13 changes: 11 additions & 2 deletions extension/bot/basebot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
#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 <sdkports/sdk_takedamageinfo.h>
#include "basebot.h"

extern CGlobalVars* gpGlobals;
Expand Down Expand Up @@ -216,6 +215,9 @@ CBaseBot::CBaseBot(edict_t* edict) : CBaseExtPlayer(edict),
m_debugtextoffset = 0;
m_weapons.reserve(MAX_WEAPONS);
m_weaponupdatetimer = 5;
m_shhooks.reserve(32);

AddHooks();
}

CBaseBot::~CBaseBot()
Expand All @@ -226,6 +228,13 @@ CBaseBot::~CBaseBot()
delete m_basebehavior;
m_interfaces.clear();
m_listeners.clear();

for (auto& hook : m_shhooks)
{
SH_REMOVE_HOOK_ID(hook);
}

m_shhooks.clear();
}

std::vector<IEventListener*>* CBaseBot::GetListenerVector()
Expand Down
23 changes: 22 additions & 1 deletion extension/bot/basebot.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <queue>
#include <string>

#include <IGameConfigs.h>
#include <extplayer.h>
#include <bot/interfaces/playercontrol.h>
#include <bot/interfaces/movement.h>
Expand All @@ -30,6 +31,19 @@ class CBaseBot : public CBaseExtPlayer, public IEventListener
CBaseBot(edict_t* edict);
~CBaseBot() override;

static bool InitHooks(SourceMod::IGameConfig* gd_navbot, SourceMod::IGameConfig* gd_sdkhooks);

private:
void AddHooks();

void Hook_Spawn();
void Hook_Touch(CBaseEntity* pOther);
int Hook_OnTakeDamage_Alive(const CTakeDamageInfo& info);
void Hook_Event_Killed(const CTakeDamageInfo& info);
void Hook_Event_KilledOther(CBaseEntity* pVictim, const CTakeDamageInfo& info);

public:

// Event propagation
std::vector<IEventListener*>* GetListenerVector() override;

Expand Down Expand Up @@ -80,7 +94,9 @@ class CBaseBot : public CBaseExtPlayer, public IEventListener
virtual void Spawn();
// Called on the first spawn call
virtual void FirstSpawn();
// Called when the player_death event is fired for this bot
// Called when this bot touches another entity
virtual void Touch(CBaseEntity* pOther) {}
// Called when this bot dies
virtual void Killed() {}
// Called by the OnTakeDamage_Alive hook.
virtual void OnTakeDamage_Alive(const CTakeDamageInfo& info);
Expand Down Expand Up @@ -179,6 +195,9 @@ class CBaseBot : public CBaseExtPlayer, public IEventListener
protected:
bool m_isfirstspawn;

// Adds a SourceHook Hook into the hook list to be removed when this is destroyed
void AddSourceHookID(int hookID) { m_shhooks.push_back(hookID); }

private:
int m_nextupdatetime;
int m_joingametime; // delay between joingame attempts
Expand All @@ -200,6 +219,8 @@ class CBaseBot : public CBaseExtPlayer, public IEventListener
std::vector<CBotWeapon> m_weapons;
int m_weaponupdatetimer;
Vector m_homepos; // Position where the bot spawned
std::vector<int> m_shhooks; // IDs of SourceHook's hooks
IntervalTimer m_burningtimer;

void ExecuteQueuedCommands();
};
Expand Down
95 changes: 95 additions & 0 deletions extension/bot/basebot_hooks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <extension.h>
#include <sdkports/sdk_takedamageinfo.h>
#include "basebot.h"

SH_DECL_MANUALHOOK0_void(CBaseBot_Spawn, 0, 0, 0)
SH_DECL_MANUALHOOK1_void(CBaseBot_Touch, 0, 0, 0, CBaseEntity*);
SH_DECL_MANUALHOOK1(CBaseBot_OnTakeDamage_Alive, 0, 0, 0, int, const CTakeDamageInfo&)
SH_DECL_MANUALHOOK1_void(CBaseBot_Event_Killed, 0, 0, 0, const CTakeDamageInfo&)
SH_DECL_MANUALHOOK2_void(CBaseBot_Event_KilledOther, 0, 0, 0, CBaseEntity*, const CTakeDamageInfo&)

bool CBaseBot::InitHooks(SourceMod::IGameConfig* gd_navbot, SourceMod::IGameConfig* gd_sdkhooks)
{
int offset = 0;

if (!gd_sdkhooks->GetOffset("Spawn", &offset)) { return false; }
SH_MANUALHOOK_RECONFIGURE(CBaseBot_Spawn, offset, 0, 0);

if (!gd_sdkhooks->GetOffset("Touch", &offset)) { return false; }
SH_MANUALHOOK_RECONFIGURE(CBaseBot_Touch, offset, 0, 0);

if (!gd_sdkhooks->GetOffset("OnTakeDamage_Alive", &offset)) { return false; }
SH_MANUALHOOK_RECONFIGURE(CBaseBot_OnTakeDamage_Alive, offset, 0, 0);

if (!gd_navbot->GetOffset("Event_Killed", &offset)) { return false; }
SH_MANUALHOOK_RECONFIGURE(CBaseBot_Event_Killed, offset, 0, 0);

if (!gd_navbot->GetOffset("Event_KilledOther", &offset)) { return false; }
SH_MANUALHOOK_RECONFIGURE(CBaseBot_Event_KilledOther, offset, 0, 0);

return true;
}

// TO-DO: Move the PlayerRunCMD hook to here too!

void CBaseBot::AddHooks()
{
CBaseEntity* ifaceptr = GetEntity();

#ifdef EXT_DEBUG
if (ifaceptr == nullptr)
{
smutils->LogError(myself, "CBaseBot::AddHooks NULL CBaseEntity!");
}
#endif // EXT_DEBUG

// Add hooks for this bot instance, hooks are removed on the destructor
m_shhooks.push_back(SH_ADD_MANUALHOOK(CBaseBot_Spawn, ifaceptr, SH_MEMBER(this, &CBaseBot::Hook_Spawn), false));
m_shhooks.push_back(SH_ADD_MANUALHOOK(CBaseBot_Touch, ifaceptr, SH_MEMBER(this, &CBaseBot::Hook_Touch), false));
m_shhooks.push_back(SH_ADD_MANUALHOOK(CBaseBot_OnTakeDamage_Alive, ifaceptr, SH_MEMBER(this, &CBaseBot::Hook_OnTakeDamage_Alive), false));
m_shhooks.push_back(SH_ADD_MANUALHOOK(CBaseBot_Event_Killed, ifaceptr, SH_MEMBER(this, &CBaseBot::Hook_Event_Killed), false));
m_shhooks.push_back(SH_ADD_MANUALHOOK(CBaseBot_Event_KilledOther, ifaceptr, SH_MEMBER(this, &CBaseBot::Hook_Event_KilledOther), false));
}

void CBaseBot::Hook_Spawn()
{
Spawn();
RETURN_META(MRES_IGNORED);
}

void CBaseBot::Hook_Touch(CBaseEntity* pOther)
{
Touch(pOther);
OnContact(pOther);
RETURN_META(MRES_IGNORED);
}

int CBaseBot::Hook_OnTakeDamage_Alive(const CTakeDamageInfo& info)
{
if (info.GetDamageType() & DMG_BURN)
{
if (!m_burningtimer.HasStarted() || m_burningtimer.IsGreaterThen(1.0f))
{
m_burningtimer.Start();
OnIgnited(info);
}
}


OnTakeDamage_Alive(info);
OnInjured(info);
RETURN_META_VALUE(MRES_IGNORED, 0);
}

void CBaseBot::Hook_Event_Killed(const CTakeDamageInfo& info)
{
Killed();
OnKilled(info);
RETURN_META(MRES_IGNORED);
}

void CBaseBot::Hook_Event_KilledOther(CBaseEntity* pVictim, const CTakeDamageInfo& info)
{
OnOtherKilled(pVictim, info);
RETURN_META(MRES_IGNORED);
}
47 changes: 38 additions & 9 deletions extension/bot/interfaces/event_listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class CBaseBot;
class CPath;
class CBaseEntity;
class Vector;
class CTakeDamageInfo;
struct edict_t;

// Interface for receiving events
Expand Down Expand Up @@ -40,9 +41,11 @@ class IEventListener
virtual void OnUnstuck(); // bot was stuck and is no longer stuck
virtual void OnMoveToFailure(CPath* path, MovementFailureType reason);
virtual void OnMoveToSuccess(CPath* path);
virtual void OnInjured(edict_t* attacker = nullptr); // when the bot takes damage
virtual void OnKilled(edict_t* attacker = nullptr); // when the bot is killed
virtual void OnOtherKilled(edict_t* victim, edict_t* attacker = nullptr); // when another player gets killed
virtual void OnContact(CBaseEntity* pOther); // Something touched the bot
virtual void OnIgnited(const CTakeDamageInfo& info); // The bot is on fire and/or taking fire damage
virtual void OnInjured(const CTakeDamageInfo& info); // when the bot takes damage
virtual void OnKilled(const CTakeDamageInfo& info); // when the bot is killed
virtual void OnOtherKilled(CBaseEntity* pVictim, const CTakeDamageInfo& info); // when another player gets killed
virtual void OnSight(edict_t* subject); // when the bot spots an entity
virtual void OnLostSight(edict_t* subject); // when the bot loses sight of an entity
virtual void OnSound(edict_t* source, const Vector& position, SoundType type, const int volume); // when the bot hears an entity
Expand Down Expand Up @@ -113,41 +116,67 @@ inline void IEventListener::OnMoveToSuccess(CPath* path)
}
}

inline void IEventListener::OnInjured(edict_t* attacker)
inline void IEventListener::OnContact(CBaseEntity* pOther)
{
auto vec = GetListenerVector();

if (vec)
{
for (auto listener : *vec)
{
listener->OnInjured(attacker);
listener->OnContact(pOther);
}
}
}

inline void IEventListener::OnKilled(edict_t* attacker)
inline void IEventListener::OnIgnited(const CTakeDamageInfo& info)
{
auto vec = GetListenerVector();

if (vec)
{
for (auto listener : *vec)
{
listener->OnKilled(attacker);
listener->OnIgnited(info);
}
}
}

inline void IEventListener::OnOtherKilled(edict_t* victim, edict_t* attacker)
inline void IEventListener::OnInjured(const CTakeDamageInfo& info)
{
auto vec = GetListenerVector();

if (vec)
{
for (auto listener : *vec)
{
listener->OnOtherKilled(victim, attacker);
listener->OnInjured(info);
}
}
}

inline void IEventListener::OnKilled(const CTakeDamageInfo& info)
{
auto vec = GetListenerVector();

if (vec)
{
for (auto listener : *vec)
{
listener->OnKilled(info);
}
}
}

inline void IEventListener::OnOtherKilled(CBaseEntity* pVictim, const CTakeDamageInfo& info)
{
auto vec = GetListenerVector();

if (vec)
{
for (auto listener : *vec)
{
listener->OnOtherKilled(pVictim, info);
}
}
}
Expand Down
Loading

0 comments on commit afabac7

Please sign in to comment.