-
Notifications
You must be signed in to change notification settings - Fork 1
Plugin examples
Karol Szuster edited this page Apr 26, 2022
·
4 revisions
This the minimum code to have loadable metamod plugin.
#include <IAnubis.hpp>
#include <ILogger.hpp>
#include <game/ILibrary.hpp>
#include <engine/ILibrary.hpp>
class Plugin : public Anubis::IPlugin
{
public:
Anubis::InterfaceVersion getInterfaceVersion() const
{
return Anubis::IAnubis::VERSION;
}
std::string_view getName() const
{
return "Minimal plugin";
}
std::string_view getVersion() const
{
return "1.0";
}
std::string_view getDate() const
{
return __DATE__;
}
std::string_view getAuthor() const
{
return "Anubis Dev Team";
}
std::string_view getUrl() const
{
return "https://github.com/Amaroq7/Anubis";
}
Type getType() const
{
return Type::Extension;
}
};
nstd::observer_ptr<Anubis::IAnubis> gApi;
nstd::observer_ptr<Anubis::Game::ILibrary> gGame;
nstd::observer_ptr<Anubis::Engine::ILibrary> gEng;
std::unique_ptr<Anubis::ILogger> gLogger;
/* The following functions are exported from the plugin */
namespace Anubis
{
nstd::observer_ptr<IPlugin> Query()
{
static auto pluginInfo = std::make_unique<Plugin>();
return pluginInfo;
}
bool Init(nstd::observer_ptr<IAnubis> api)
{
gApi = api;
gGame = gApi->getGame(Game::ILibrary::VERSION);
gEng = gApi->getEngine(Engine::ILibrary::VERSION);
gLogger = gApi->getLogger(ILogger::VERSION);
gLogger->setLogTag("TEST");
gLogger->setLogLevel(LogLevel::Debug);
return true;
}
void Shutdown()
{
gLogger.reset();
}
}
This example shows how to hook ClientCmd func. It prints info about the 1st argument of the say command.
#include <IAnubis.hpp>
#include <game/ILibrary.hpp>
#include <game/IHooks.hpp>
#include <engine/ILibrary.hpp>
#include <engine/IEdict.hpp>
class Plugin : public Anubis::IPlugin
{
public:
Anubis::InterfaceVersion getInterfaceVersion() const
{
return Anubis::IAnubis::VERSION;
}
std::string_view getName() const
{
return "Example";
}
std::string_view getVersion() const
{
return "1.0";
}
std::string_view getDate() const
{
return __DATE__;
}
std::string_view getAuthor() const
{
return "Author";
}
std::string_view getUrl() const
{
return "URL";
}
Type getType() const
{
return Type::Extension;
}
};
nstd::observer_ptr<Anubis::IAnubis> gApi;
nstd::observer_ptr<Anubis::Game::ILibrary> gGame;
nstd::observer_ptr<Anubis::Engine::ILibrary> gEng;
std::unique_ptr<Anubis::ILogger> gLogger;
nstd::observer_ptr<Anubis::IHookInfo> gOnClientCmdHook;
void OnClientCmd(nstd::observer_ptr<Anubis::Game::IClientCmdHook> hook, nstd::observer_ptr<Anubis::Engine::IEdict> e)
{
// pre stuff
// ...
/**
* Calls the next hook in the chain.
* callOriginal() will call the original funcs omitting other plugins' hooks.
* If no callNext or callOriginal is called then the original func won't be called resulting in no commands sent to the gamedll.
* This can to useful to f.e. hide commands on the say.
*/
hook->callNext(e);
// post stuff
if (gEng->cmdArgv(0, Anubis::FuncCallType::Direct) == "say")
{
using namespace std::string_literals;
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "Client "s + std::to_string(e->getIndex()));
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "say: "s + gEng->cmdArgv(1, Anubis::FuncCallType::Direct).data());
}
}
/* The following functions are exported from the plugin */
namespace Anubis
{
nstd::observer_ptr<IPlugin> Query()
{
static auto pluginInfo = std::make_unique<Plugin>();
return pluginInfo;
}
bool Init(nstd::observer_ptr<IAnubis> api)
{
gApi = api;
gGame = gApi->getGame(Game::ILibrary::VERSION);
gEng = gApi->getEngine(Engine::ILibrary::VERSION);
gLogger = gApi->getLogger(ILogger::VERSION);
gLogger->setLogTag("TEST");
gLogger->setLogLevel(LogLevel::Debug);
gOnClientCmdHook = gGame->getHooks()->clientCmd()->registerHook(OnClientCmd, HookPriority::Default);
return true;
}
void Shutdown()
{
gGame->getHooks()->clientCmd()->unregisterHook(gOnClientCmdHook);
}
}
This example demonstrates how to hook virutal func of CBasePlayer class. It also shows how to disable/enable hook using say command.
#include <IAnubis.hpp>
#include <game/IEntitiesHooks.hpp>
#include <game/ILibrary.hpp>
#include <game/IHooks.hpp>
#include <game/IBasePlayer.hpp>
#include <engine/ITraceResult.hpp>
#include <engine/IEdict.hpp>
#include <engine/ILibrary.hpp>
class Plugin : public Anubis::IPlugin
{
public:
Anubis::InterfaceVersion getInterfaceVersion() const
{
return Anubis::IAnubis::VERSION;
}
std::string_view getName() const
{
return "Example";
}
std::string_view getVersion() const
{
return "1.0";
}
std::string_view getDate() const
{
return __DATE__;
}
std::string_view getAuthor() const
{
return "Author";
}
std::string_view getUrl() const
{
return "URL";
}
Type getType() const
{
return Type::Extension;
}
};
nstd::observer_ptr<Anubis::IAnubis> gApi;
nstd::observer_ptr<Anubis::Game::ILibrary> gGame;
nstd::observer_ptr<Anubis::Engine::ILibrary> gEng;
std::unique_ptr<Anubis::ILogger> gLogger;
nstd::observer_ptr<Anubis::IHookInfo> gOnClientCmdHook;
nstd::observer_ptr<Anubis::IHookInfo> gCBasePlayerTakeDamageHook;
bool OnCBasePlayerTakeDamage(nstd::observer_ptr<Anubis::Game::IBasePlayerTakeDamageHook> hook,
nstd::observer_ptr<Anubis::Game::IBasePlayer> plr,
nstd::observer_ptr<Anubis::Game::IBaseEntity> pevInflictor,
nstd::observer_ptr<Anubis::Game::IBaseEntity> pevAttacker,
float &dmg, Anubis::Game::DmgType bits)
{
bool result = hook->callNext(plr, pevInflictor, pevAttacker, dmg, bits);
using namespace std::string_literals;
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "this: "s + std::to_string(plr->edict()->getIndex()));
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "pevInflictor: "s + std::to_string(pevInflictor->getIndex()));
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "pevAttacker: "s + std::to_string(pevAttacker->getIndex()));
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "dmg: "s + std::to_string(dmg));
gLogger->logMsg(Anubis::LogDest::Console, Anubis::LogLevel::Info, "bits: "s + std::to_string(bits));
return result;
}
void OnClientCmd(nstd::observer_ptr<Anubis::Game::IClientCmdHook> hook, nstd::observer_ptr<Anubis::Engine::IEdict> e)
{
if (gEng->cmdArgv(0, Anubis::FuncCallType::Direct) == "say")
{
if (gEng->cmdArgv(1, Anubis::FuncCallType::Direct) == "/on")
{
gCBasePlayerTakeDamageHook->setState(Anubis::IHookInfo::State::Enabled);
return;
}
else if (gEng->cmdArgv(1, Anubis::FuncCallType::Direct) == "/off")
{
gCBasePlayerTakeDamageHook->setState(Anubis::IHookInfo::State::Disabled);
return;
}
}
hook->callNext(e);
}
std::int32_t onSpawn(nstd::observer_ptr<Anubis::Game::IBasePlayerSpawnHook> hook, nstd::observer_ptr<Anubis::Engine::IEdict> e)
{
static bool init = false;
if (init)
return hook->callNext(ed);
gCBasePlayerTakeDamageHook = gGame->getCBasePlayerHooks()->takeDamage()->registerHook(OnCBasePlayerTakeDamage, Anubis::HookPriority::Default);
init = true;
return hook->callNext(ed);
}
namespace Anubis
{
nstd::observer_ptr<IPlugin> Query()
{
static auto pluginInfo = std::make_unique<Plugin>();
return pluginInfo;
}
bool Init(nstd::observer_ptr<IAnubis> api)
{
gApi = api;
gGame = gApi->getGame(Game::ILibrary::VERSION);
gEng = gApi->getEngine(Engine::ILibrary::VERSION);
gLogger = gApi->getLogger(ILogger::VERSION);
gLogger->setLogTag("TEST");
gLogger->setLogLevel(LogLevel::Debug);
gOnClientCmdHook = gGame->getHooks()->clientCmd()->registerHook(OnClientCmd, HookPriority::Default);
return true;
}
void InstallVHooks()
{
gGame->getCBasePlayerHooks()->spawn()->registerHook(onSpawn, HookPriority::Default);
}
void Shutdown()
{
gGame->getHooks()->clientCmd()->unregisterHook(gOnClientCmdHook);
gGame->getCBasePlayerHooks()->takeDamage()->unregisterHook(gCBasePlayerTakeDamageHook);
}
}