diff --git a/dlls/hamsandwich/Makefile b/dlls/hamsandwich/Makefile index 96f9512e..b933dbe6 100644 --- a/dlls/hamsandwich/Makefile +++ b/dlls/hamsandwich/Makefile @@ -2,7 +2,7 @@ # Makefile written by David "BAILOPAN" Anderson HLSDK = ../../../hlsdk -MM_ROOT = ../../../metamod/metamod +MM_ROOT = ../../metamod/metamod ### EDIT BELOW FOR OTHER PROJECTS ### @@ -27,7 +27,11 @@ OBJECTS = sdk/amxxmodule.cpp FileParser.cpp amxxapi.cpp hooks.cpp \ tableentries/VTableManager.cpp tableentries/TakeDamage.cpp tableentries/Use.cpp \ tableentries/Blocked.cpp tableentries/Killed.cpp tableentries/Respawn.cpp \ tableentries/Restart.cpp tableentries/AddPoints.cpp tableentries/AddPointsToTeam.cpp \ - +tableentries/AddPlayerItem.cpp tableentries/RemovePlayerItem.cpp tableentries/IsPlayer.cpp \ +tableentries/BloodColor.cpp tableentries/ObjectCaps.cpp tableentries/Classify.cpp \ +tableentries/IsInWorld.cpp tableentries/IsNetClient.cpp tableentries/IsSneaking.cpp \ +tableentries/IsMoving.cpp tableentries/IsBSPModel.cpp tableentries/IsAlive.cpp \ +tableentries/GetToggleState.cpp tableentries/Think.cpp tableentries/Touch.cpp #natives.cpp vtable.cpp diff --git a/dlls/hamsandwich/amxxapi.cpp b/dlls/hamsandwich/amxxapi.cpp index 546f38e8..e0e1bf40 100644 --- a/dlls/hamsandwich/amxxapi.cpp +++ b/dlls/hamsandwich/amxxapi.cpp @@ -107,6 +107,22 @@ void HAM_CallInitialization(void) VTINIT(Restart); VTINIT(AddPoints); VTINIT(AddPointsToTeam); + VTINIT(AddPlayerItem); + VTINIT(RemovePlayerItem); + VTINIT(BloodColor); + VTINIT(Classify); + VTINIT(GetToggleState); + VTINIT(IsAlive); + VTINIT(IsBSPModel); + VTINIT(IsInWorld); + VTINIT(IsMoving); + VTINIT(IsNetClient); + VTINIT(IsPlayer); + VTINIT(IsSneaking); + VTINIT(ObjectCaps); + VTINIT(Think); + VTINIT(Touch); + #undef VTINIT } diff --git a/dlls/hamsandwich/hamsandwich.h b/dlls/hamsandwich/hamsandwich.h index c8f694ac..bc8a8acd 100644 --- a/dlls/hamsandwich/hamsandwich.h +++ b/dlls/hamsandwich/hamsandwich.h @@ -47,6 +47,22 @@ enum HAMHooks HAM_Respawn, HAM_Restart, HAM_TakeHealth, + HAM_AddPlayerItem, + HAM_RemovePlayerItem, + HAM_BloodColor, + HAM_Classify, + HAM_GetToggleState, + HAM_IsAlive, + HAM_IsBSPModel, + HAM_IsInWorld, + HAM_IsMoving, + HAM_IsNetClient, + HAM_IsPlayer, + HAM_IsSneaking, + HAM_ObjectCaps, + HAM_Think, + HAM_Touch, + HAM_END_DONT_USE_ME }; diff --git a/dlls/hamsandwich/include/hamsandwich.inc b/dlls/hamsandwich/include/hamsandwich.inc index 86745253..5938afbf 100644 --- a/dlls/hamsandwich/include/hamsandwich.inc +++ b/dlls/hamsandwich/include/hamsandwich.inc @@ -16,114 +16,74 @@ #include #endif -/** - * Ham Sandwich general usage - * - - * Mods supported: - * cs: - * * 1.6 - legimate, most up to date version - * * linux 32bit and windows - * * czero - legimate, most up to date version - * * linux 32bit and windows - * * czero untested, theoretically it should work - * dod: - * * whatever the most up to date legitimate version is (1.3?) - * * linux and windows - * * windows untested, should work - * tfc: - * * whatever most up to date legitimate version is - * * linux and windows - * * windows untested, should work - * ns: - * * 3.2 beta 2 - * * linux and windows - * * windows untested, should work - * ts: - * * 2.1 - * * linux and windows - * * windows untested, should work - * sven: - * * 3.0 - * * windows - * * windows untested, should work - * - - * The module will automatically use the relevant function depending - * on what game mod is loaded. You only have to tell it to do the damage. - * - - * Be VERY VERY careful. I check _NO_ bounds in any of the natives - * Also, these call the game's private function, and I do not have - * the time nor desire to figure out the quirks of each mod's function - * - - * The USE natives haven't been tested yet, but should work! - * - - * The only mod I tested the windows version of takedamage - * for was cs 1.6. It's much easier for me to test linux. - */ +native ham_addplayeritem(idPlayer,idItem); +native ham_eaddplayeritem(idPlayer,idItem); -/** - * Calls the mod's private damage routine. - * - - * parameters: - * id: index of the entity that is to be damaged - * - * inflictor: the entity that is "doing the damage" (eg a weapon) - * - * attacker: the entity who controls the inflictor (eg weapon holder) - * - * damage: how much damage to do to the victim - * - * type: bitmask of damage flags. Most mods do not - * follow the standard HLSDK damage flags, so - * you may have to do some testing! - * The only flags I figured out were CS related: - * * (1<<6) = no slowdown on damage - * * (1<<13) = always gib - * * (1<<12) = never gib - * - * - - * Note: Setting damage to a ridiculously high value can mess up - * some mods! - */ -native hs_takedamage(id,inflictor,attacker,Float:damage,type); -native hs_etakedamage(id,inflictor,attacker,Float:damage,type); +native ham_addpoints(idEntity,points,bool:allownegative); +native ham_eaddpoints(idEntity,points,bool:allownegative); +native ham_addpointstoteam(idEntity,points,bool:allownegative); +native ham_eaddpointstoteam(idEntity,points,bool:allownegative); -/** - * Calls the mod's private use routine. - * - - * parameters: - * id: index of the entity that is to be used - * - * activator: the entity that is "doing the use" (eg a trigger_multiple) - * - * caller: the entity who controls the activator (eg the player who trigger the trigger_multiple) - * - * use_type: how to use the entity - * TYPICAL settings in HLSDK are: - * 0 = USE_OFF - turns the object "off" - * 1 = USE_ON - turns the object "on" - * 2 = USE_SET - sets the object use state (uses the value flag) - * 3 = USE_TOGGLE - toggles the state (from on->off and off->on) - * - * use_value: set when USE_SET is invoked - * TYPICALLY USE_SET is only used for players using an object - * when he begins using it, the use_value is set to 1.0 - * when he's done using it, the use_value is set to 0.0 - * - * - - * NOTE: This native was not tested at all beyond theory tests! - */ -native hs_use(id,activator,caller,use_type,Float:use_value); -native hs_euse(id,activator,caller,use_type,Float:use_value); +native ham_blocked(idEntity,idOther); +native ham_eblocked(idEntity,idOther); -native hs_killed(id,attacker,gib); -native hs_ekilled(id,attacker,gib); -native hs_blocked(id,other); -native hs_eblocked(id,other); -native hs_respawn(id); -native hs_erespawn(id); -native hs_restart(id); -native hs_erestart(id); +native ham_bloodcolor(idEntity); +native ham_ebloodcolor(idEntity); + +native ham_classify(idEntity); +native ham_eclassify(idEntity); + +native ham_gettogglestate(idEntity); +native ham_egettogglestate(idEntity); + +native ham_isalive(idEntity); +native ham_eisalive(idEntity); + +native ham_isbspmodel(idEntity); +native ham_eisbspmodel(idEntity); + +native ham_isinworld(idEntity); +native ham_eisinworld(idEntity); + +native ham_isnetclient(idEntity); +native ham_eisnetclient(idEntity); + +native ham_isplayer(idEntity); +native ham_eisplayer(idEntity); + +native ham_issneaking(idEntity); +native ham_eissneaking(idEntity); + +native ham_killed(idEntity,idAttacker,iGib); +native ham_ekilled(idEntity,idAttacker,iGib); + +native ham_objectcaps(idEntity); +native ham_eobjectcaps(idEntity); + +native ham_removeplayeritem(idEntity,idItem); +native ham_eremoveplayeritem(idEntity,idItem); + +native ham_respawn(idEntity); +native ham_erespawn(idEntity); + +native ham_restart(idEntity); +native ham_erestart(idEntity); + +native ham_takedamage(idEntity,idInflictor,idAttacker,Float:damage,dmgtype); +native ham_etakedamage(idEntity,idInflictor,idAttacker,Float:damage,dmgtype); + +native ham_takehealth(idEntity,Float:health,dmgtype); +native ham_etakehealth(idEntity,Float:health,dmgtype); + +native ham_think(idEntity); +native ham_ethink(idEntity); + +native ham_touch(idEntity,idOther); +native ham_etouch(idEntity,idOther); + +native ham_use(idEntity,idActivator,idCaller,use_type,Float:value); +native ham_euse(idEntity,idActivator,idCaller,use_type,Float:value); @@ -136,34 +96,6 @@ enum HAM_SUPERCEDE }; -/** - * Forwards all takedamage routines that would occur to the given - * classname to the public provided. - * - * Parameters are: - * function(IDVictim, IDInflictor, IDAttacker, Float:Damage, DamageType) - * - * Note: For now, this will also intercept calls to hs_takedamage - * that is very likely to change shortly in the future. - */ -native register_takedamage(const classname[], const function[], post=0); - -/** - * Forwards all use routines that would occur to the given - * classname to the public provided. - * - * Parameters are: - * function(IDUsed, IDActivator, IDCaller, UseType, Float:UseValue) - * - * Note: For now, this will also intercept calls to hs_use - * that is very likely to change shortly in the future. - */ -native register_use(const classname[], const function[], post=0); - -native register_killed(const classname[], const function[], post=0); -native register_blocked(const classname[], const function[], post=0); -native hs_register_respawn(const classname[], const function[], post=0); -native hs_register_restart(const classname[], const function[], post=0); enum HAMHooks @@ -177,11 +109,28 @@ enum HAMHooks HAM_Respawn, HAM_Restart, HAM_TakeHealth, + HAM_AddPlayerItem, + HAM_RemovePlayerItem, + HAM_BloodColor, + HAM_Classify, + HAM_GetToggleState, + HAM_IsAlive, + HAM_IsBSPModel, + HAM_IsInWorld, + HAM_IsMoving, + HAM_IsNetClient, + HAM_IsPlayer, + HAM_IsSneaking, + HAM_ObjectCaps, + HAM_Think, + HAM_Touch, + HAM_END_DONT_USE_ME }; native ham_register(HAMHooks:hook, const classname[], const function[], post=0); + public __fatal_ham_error(const reason[]) { set_fail_state(reason); diff --git a/dlls/hamsandwich/tableentries/AddPlayerItem.cpp b/dlls/hamsandwich/tableentries/AddPlayerItem.cpp new file mode 100644 index 00000000..aebc0190 --- /dev/null +++ b/dlls/hamsandwich/tableentries/AddPlayerItem.cpp @@ -0,0 +1,371 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableAddPlayerItem +#define ThisEntries AddPlayerItemEntries + +#define ThisKey "addplayeritem" +#define ThisNative "ham_addplayeritem" +#define ThisENative "ham_eaddplayeritem" +#define ThisRegisterID HAM_AddPlayerItem +#define ThisParamCount 1 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0, /*fastcall buffer*/ + INDEXENT_NEW(params[2])->pvPrivateData /*item*/ + ); +#else + return reinterpret_cast(func)( + pthis, /*this*/ + INDEXENT_NEW(params[2])->pvPrivateData /*item*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall1( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + INDEXENT_NEW(params[3])->pvPrivateData /*item*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*item*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param inflictor Damage inflictor. + * @param attacker The attacker who caused the inflictor to damage the victim. + * @param damage How much damage was caused. + * @param type Damage type (usually in bitmask form). + * @return Unsure. Does not appear to be used. + */ +int ThisVTable::Execute(void *pthis, void *item) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + int iItem=PrivateToIndex(item); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0,item); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis,item); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis,item); +} diff --git a/dlls/hamsandwich/tableentries/AddPoints.cpp b/dlls/hamsandwich/tableentries/AddPoints.cpp index 14021fa4..5a3ab6f8 100644 --- a/dlls/hamsandwich/tableentries/AddPoints.cpp +++ b/dlls/hamsandwich/tableentries/AddPoints.cpp @@ -14,8 +14,8 @@ #define ThisVTable VTableAddPoints #define ThisEntries AddPointsEntries #define ThisKey "addpoints" -#define ThisNative "hs_addpoints" -#define ThisENative "hs_eaddpoints" +#define ThisNative "ham_addpoints" +#define ThisENative "ham_eaddpoints" #define ThisRegisterID HAM_AddPoints #define ThisParamCount 0 #define ThisVoidCall 1 @@ -359,5 +359,5 @@ void ThisVTable::Execute(void *pthis,int points, int allownegative) }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative) { - VTMan.AddPointsEntries[id]->Execute(pthis,points,allownegative); + VTMan.ThisEntries[id]->Execute(pthis,points,allownegative); } diff --git a/dlls/hamsandwich/tableentries/AddPointsToTeam.cpp b/dlls/hamsandwich/tableentries/AddPointsToTeam.cpp index fa65f3dd..d65aa992 100644 --- a/dlls/hamsandwich/tableentries/AddPointsToTeam.cpp +++ b/dlls/hamsandwich/tableentries/AddPointsToTeam.cpp @@ -14,8 +14,8 @@ #define ThisVTable VTableAddPointsToTeam #define ThisEntries AddPointsToTeamEntries #define ThisKey "addpointstoteam" -#define ThisNative "hs_addpointstoteam" -#define ThisENative "hs_eaddpointstoteam" +#define ThisNative "ham_addpointstoteam" +#define ThisENative "ham_eaddpointstoteam" #define ThisRegisterID HAM_AddPointsToTeam #define ThisParamCount 2 #define ThisVoidCall 1 @@ -358,5 +358,5 @@ void ThisVTable::Execute(void *pthis,int points, int allownegative) }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative) { - VTMan.AddPointsToTeamEntries[id]->Execute(pthis,points,allownegative); + VTMan.ThisEntries[id]->Execute(pthis,points,allownegative); } diff --git a/dlls/hamsandwich/tableentries/Blocked.cpp b/dlls/hamsandwich/tableentries/Blocked.cpp index 2978650c..8ae7cd4b 100644 --- a/dlls/hamsandwich/tableentries/Blocked.cpp +++ b/dlls/hamsandwich/tableentries/Blocked.cpp @@ -15,8 +15,8 @@ #define ThisEntries BlockedEntries #define ThisKey "blocked" -#define ThisNative "hs_blocked" -#define ThisENative "hs_eblocked" +#define ThisNative "ham_blocked" +#define ThisENative "ham_eblocked" #define ThisRegisterID HAM_Blocked #define ThisParamCount 1 #define ThisVoidCall 1 @@ -30,8 +30,8 @@ unsigned int ThisVTable::index=0; unsigned int ThisVTable::indexset=0; static AMX_NATIVE_INFO callnatives[] = { - { "hs_blocked", ThisVTable::NativeCall }, - { "hs_eblocked", ThisVTable::ENativeCall }, + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, { NULL, NULL } }; @@ -57,7 +57,7 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned RegisterConfigCallback(ThisVTable::ConfigDone); - RegisterKeySuffix("blocked",ThisVTable::KeyValue); + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); RegisterThisRegisterName(ThisRegisterID,ThisKey); }; @@ -71,7 +71,7 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned */ void ThisVTable::KeyValue(const char *key, const char *data) { - if (strcmp(key,"blocked")==0) + if (strcmp(key,ThisKey)==0) { ThisVTable::index=HAM_StrToNum(data); ThisVTable::indexset=1; @@ -248,8 +248,8 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void outtrampoline, origfunc, reinterpret_cast(ThisVTable::EntryPoint), - 1, // param count - 1, // voidcall + ThisParamCount, // param count + ThisVoidCall, // voidcall 1); // thiscall }; @@ -362,5 +362,5 @@ void ThisVTable::Execute(void *pthis, void *other) }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,void *other) { - VTMan.BlockedEntries[id]->Execute(pthis,other); + VTMan.ThisEntries[id]->Execute(pthis,other); } diff --git a/dlls/hamsandwich/tableentries/BloodColor.cpp b/dlls/hamsandwich/tableentries/BloodColor.cpp new file mode 100644 index 00000000..c2ee0bd1 --- /dev/null +++ b/dlls/hamsandwich/tableentries/BloodColor.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableBloodColor +#define ThisEntries BloodColorEntries + +#define ThisKey "bloodcolor" +#define ThisNative "ham_bloodcolor" +#define ThisENative "ham_ebloodcolor" +#define ThisRegisterID HAM_BloodColor +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/Classify.cpp b/dlls/hamsandwich/tableentries/Classify.cpp new file mode 100644 index 00000000..27585412 --- /dev/null +++ b/dlls/hamsandwich/tableentries/Classify.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableClassify +#define ThisEntries ClassifyEntries + +#define ThisKey "classify" +#define ThisNative "ham_classify" +#define ThisENative "ham_eclassify" +#define ThisRegisterID HAM_Classify +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/GetToggleState.cpp b/dlls/hamsandwich/tableentries/GetToggleState.cpp new file mode 100644 index 00000000..226f7a3b --- /dev/null +++ b/dlls/hamsandwich/tableentries/GetToggleState.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableGetToggleState +#define ThisEntries GetToggleStateEntries + +#define ThisKey "gettogglestate" +#define ThisNative "ham_gettogglestate" +#define ThisENative "ham_egettogglestate" +#define ThisRegisterID HAM_GetToggleState +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsAlive.cpp b/dlls/hamsandwich/tableentries/IsAlive.cpp new file mode 100644 index 00000000..3a2fc800 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsAlive.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsAlive +#define ThisEntries IsAliveEntries + +#define ThisKey "isalive" +#define ThisNative "ham_isalive" +#define ThisENative "ham_eisalive" +#define ThisRegisterID HAM_IsAlive +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsBSPModel.cpp b/dlls/hamsandwich/tableentries/IsBSPModel.cpp new file mode 100644 index 00000000..938d5d05 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsBSPModel.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsBSPModel +#define ThisEntries IsBSPModelEntries + +#define ThisKey "isbspmodel" +#define ThisNative "ham_isbspmodel" +#define ThisENative "ham_eisbspmodel" +#define ThisRegisterID HAM_IsBSPModel +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsInWorld.cpp b/dlls/hamsandwich/tableentries/IsInWorld.cpp new file mode 100644 index 00000000..4fc5a0ff --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsInWorld.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsInWorld +#define ThisEntries IsInWorldEntries + +#define ThisKey "isinworld" +#define ThisNative "ham_isinworld" +#define ThisENative "ham_eisinworld" +#define ThisRegisterID HAM_IsInWorld +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsMoving.cpp b/dlls/hamsandwich/tableentries/IsMoving.cpp new file mode 100644 index 00000000..83f7f6e4 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsMoving.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsMoving +#define ThisEntries IsMovingEntries + +#define ThisKey "ismoving" +#define ThisNative "ham_ismoving" +#define ThisENative "ham_eismoving" +#define ThisRegisterID HAM_IsMoving +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsNetClient.cpp b/dlls/hamsandwich/tableentries/IsNetClient.cpp new file mode 100644 index 00000000..4253fb33 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsNetClient.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsNetClient +#define ThisEntries IsNetClientEntries + +#define ThisKey "isnetclient" +#define ThisNative "ham_isnetclient" +#define ThisENative "ham_eisnetclient" +#define ThisRegisterID HAM_IsNetClient +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsPlayer.cpp b/dlls/hamsandwich/tableentries/IsPlayer.cpp new file mode 100644 index 00000000..2ccd0125 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsPlayer.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsPlayer +#define ThisEntries IsPlayerEntries + +#define ThisKey "isplayer" +#define ThisNative "ham_isplayer" +#define ThisENative "ham_eisplayer" +#define ThisRegisterID HAM_IsPlayer +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/IsSneaking.cpp b/dlls/hamsandwich/tableentries/IsSneaking.cpp new file mode 100644 index 00000000..bd97ef51 --- /dev/null +++ b/dlls/hamsandwich/tableentries/IsSneaking.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableIsSneaking +#define ThisEntries IsSneakingEntries + +#define ThisKey "issneaking" +#define ThisNative "ham_issneaking" +#define ThisENative "ham_eissneaking" +#define ThisRegisterID HAM_IsSneaking +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/Killed.cpp b/dlls/hamsandwich/tableentries/Killed.cpp index 628bc5b1..b51ec3c6 100644 --- a/dlls/hamsandwich/tableentries/Killed.cpp +++ b/dlls/hamsandwich/tableentries/Killed.cpp @@ -15,8 +15,8 @@ #define ThisEntries KilledEntries #define ThisKey "killed" -#define ThisNative "hs_killed" -#define ThisENative "hs_ekilled" +#define ThisNative "ham_killed" +#define ThisENative "ham_ekilled" #define ThisRegisterID HAM_Killed #define ThisParamCount 2 #define ThisVoidCall 1 @@ -363,6 +363,6 @@ void ThisVTable::Execute(void *pthis, void *attacker, int gib) }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,void *attacker,int gib) { - VTMan.KilledEntries[id]->Execute(pthis,attacker,gib); + VTMan.ThisEntries[id]->Execute(pthis,attacker,gib); } diff --git a/dlls/hamsandwich/tableentries/ObjectCaps.cpp b/dlls/hamsandwich/tableentries/ObjectCaps.cpp new file mode 100644 index 00000000..130194ae --- /dev/null +++ b/dlls/hamsandwich/tableentries/ObjectCaps.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableObjectCaps +#define ThisEntries ObjectCapsEntries + +#define ThisKey "objectcaps" +#define ThisNative "ham_objectcaps" +#define ThisENative "ham_eobjectcaps" +#define ThisRegisterID HAM_ObjectCaps +#define ThisParamCount 0 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + return reinterpret_cast(func)( + pthis /*this*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall4( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + &(INDEXENT_NEW(params[2])->v), /*inflictor*/ + &(INDEXENT_NEW(params[3])->v), /*attacker*/ + amx_ctof2(params[4]), /*damage*/ + (int)params[5] /*dmgtype*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ +int ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/RemovePlayerItem.cpp b/dlls/hamsandwich/tableentries/RemovePlayerItem.cpp new file mode 100644 index 00000000..0a75b34f --- /dev/null +++ b/dlls/hamsandwich/tableentries/RemovePlayerItem.cpp @@ -0,0 +1,371 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableRemovePlayerItem +#define ThisEntries RemovePlayerItemEntries + +#define ThisKey "removeplayeritem" +#define ThisNative "ham_removeplayeritem" +#define ThisENative "ham_eremoveplayeritem" +#define ThisRegisterID HAM_RemovePlayerItem +#define ThisParamCount 1 +#define ThisVoidCall 0 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + //MF_AddNatives(registernatives); + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + + char *function=MF_GetAmxString(amx,params[2],0,NULL); + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + return reinterpret_cast(func)( + pthis, /*this*/ + 0, /*fastcall buffer*/ + INDEXENT_NEW(params[2])->pvPrivateData /*item*/ + ); +#else + return reinterpret_cast(func)( + pthis, /*this*/ + INDEXENT_NEW(params[2])->pvPrivateData /*item*/ + ); +#endif +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + return VCall1( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + INDEXENT_NEW(params[3])->pvPrivateData /*item*/ + ); +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*item*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param inflictor Damage inflictor. + * @param attacker The attacker who caused the inflictor to damage the victim. + * @param damage How much damage was caused. + * @param type Damage type (usually in bitmask form). + * @return Unsure. Does not appear to be used. + */ +int ThisVTable::Execute(void *pthis, void *item) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + int iItem=PrivateToIndex(item); + + while (iresult) + { + result=thisresult; + } + }; + int ireturn=0; + + if (result(function)(pthis,0,item); +#elif defined __linux__ + ireturn=reinterpret_cast(function)(pthis,item); +#endif + } + + i=0; + + end=PostForwards.size(); + while (iExecute(pthis,item); +} diff --git a/dlls/hamsandwich/tableentries/Respawn.cpp b/dlls/hamsandwich/tableentries/Respawn.cpp index dc307e23..b106f3dc 100644 --- a/dlls/hamsandwich/tableentries/Respawn.cpp +++ b/dlls/hamsandwich/tableentries/Respawn.cpp @@ -14,8 +14,8 @@ #define ThisVTable VTableRespawn #define ThisEntries RespawnEntries #define ThisKey "respawn" -#define ThisNative "hs_respawn" -#define ThisENative "hs_erespawn" +#define ThisNative "ham_respawn" +#define ThisENative "ham_erespawn" #define ThisRegisterID HAM_Respawn #define ThisParamCount 0 #define ThisVoidCall 1 @@ -28,8 +28,8 @@ unsigned int ThisVTable::index=0; unsigned int ThisVTable::indexset=0; static AMX_NATIVE_INFO callnatives[] = { - { "hs_respawn", ThisVTable::NativeCall }, - { "hs_respawn", ThisVTable::ENativeCall }, + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, { NULL, NULL } }; @@ -352,5 +352,5 @@ void *ThisVTable::Execute(void *pthis) }; extern "C" void *ThisVTable::EntryPoint(int id,void *pthis) { - return VTMan.RespawnEntries[id]->Execute(pthis); + return VTMan.ThisEntries[id]->Execute(pthis); } diff --git a/dlls/hamsandwich/tableentries/Restart.cpp b/dlls/hamsandwich/tableentries/Restart.cpp index 82fcd8da..f7900210 100644 --- a/dlls/hamsandwich/tableentries/Restart.cpp +++ b/dlls/hamsandwich/tableentries/Restart.cpp @@ -14,8 +14,8 @@ #define ThisVTable VTableRestart #define ThisEntries RestartEntries #define ThisKey "restart" -#define ThisNative "hs_restart" -#define ThisENative "hs_erestart" +#define ThisNative "ham_restart" +#define ThisENative "ham_erestart" #define ThisRegisterID HAM_Restart #define ThisParamCount 0 #define ThisVoidCall 1 @@ -352,5 +352,5 @@ void ThisVTable::Execute(void *pthis) }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis) { - VTMan.RestartEntries[id]->Execute(pthis); + VTMan.ThisEntries[id]->Execute(pthis); } diff --git a/dlls/hamsandwich/tableentries/TakeDamage.cpp b/dlls/hamsandwich/tableentries/TakeDamage.cpp index 2eaa989e..792db305 100644 --- a/dlls/hamsandwich/tableentries/TakeDamage.cpp +++ b/dlls/hamsandwich/tableentries/TakeDamage.cpp @@ -15,8 +15,8 @@ #define ThisEntries TakeDamageEntries #define ThisKey "takedamage" -#define ThisNative "hs_takedamage" -#define ThisENative "hs_etakedamage" +#define ThisNative "ham_takedamage" +#define ThisENative "ham_etakedamage" #define ThisRegisterID HAM_TakeDamage #define ThisParamCount 4 #define ThisVoidCall 0 @@ -377,5 +377,5 @@ int ThisVTable::Execute(void *pthis, void *inflictor, void *attacker, float dama }; HAM_CDECL int ThisVTable::EntryPoint(int id,void *pthis,void *inflictor,void *attacker,float damage,int type) { - return VTMan.TakeDamageEntries[id]->Execute(pthis,inflictor,attacker,damage,type); + return VTMan.ThisEntries[id]->Execute(pthis,inflictor,attacker,damage,type); } diff --git a/dlls/hamsandwich/tableentries/TakeHealth.cpp b/dlls/hamsandwich/tableentries/TakeHealth.cpp index 72949af1..c59a4578 100644 --- a/dlls/hamsandwich/tableentries/TakeHealth.cpp +++ b/dlls/hamsandwich/tableentries/TakeHealth.cpp @@ -15,8 +15,8 @@ #define ThisEntries TakeHealthEntries #define ThisKey "takehealth" -#define ThisNative "hs_takehealth" -#define ThisENative "hs_etakehealth" +#define ThisNative "ham_takehealth" +#define ThisENative "ham_etakehealth" #define ThisRegisterID HAM_TakeHealth #define ThisParamCount 2 #define ThisVoidCall 0 diff --git a/dlls/hamsandwich/tableentries/Think.cpp b/dlls/hamsandwich/tableentries/Think.cpp new file mode 100644 index 00000000..4744e365 --- /dev/null +++ b/dlls/hamsandwich/tableentries/Think.cpp @@ -0,0 +1,356 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableThink +#define ThisEntries ThinkEntries +#define ThisKey "think" +#define ThisNative "ham_think" +#define ThisENative "ham_ethink" +#define ThisRegisterID HAM_Think +#define ThisParamCount 0 +#define ThisVoidCall 1 + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + // class was not found + // throw an error alerting console that this hook did not happen + char *function=MF_GetAmxString(amx,params[2],0,NULL); + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + reinterpret_cast(func)( + pthis, /*this*/ + 0 /*fastcall buffer*/ + ); +#else + reinterpret_cast(func)( + pthis /*this*/ + ); +#endif + return 0; +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + VoidVCall0( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset) /*size of class*/ + ); + return 1; +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + 0, // param count + 1, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @return Unsure. Does not appear to be used. + */ +void ThisVTable::Execute(void *pthis) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + + while (iresult) + { + result=thisresult; + } + }; + + if (result(function)(pthis,0); +#elif defined __linux__ + reinterpret_cast(function)(pthis); +#endif + } + + i=0; + end=PostForwards.size(); + + while (iExecute(pthis); +} diff --git a/dlls/hamsandwich/tableentries/Touch.cpp b/dlls/hamsandwich/tableentries/Touch.cpp new file mode 100644 index 00000000..d8f0907d --- /dev/null +++ b/dlls/hamsandwich/tableentries/Touch.cpp @@ -0,0 +1,366 @@ +#include "sdk/amxxmodule.h" + +#include "hamsandwich.h" + +#include "VTableManager.h" +#include "VTableEntries.h" + +#include "vfunc_gcc295.h" +#include "vfunc_msvc.h" + +#include "NEW_Util.h" + +// Change these on a per-hook basis! Auto-changes all the annoying fields in the following functions +#define ThisVTable VTableTouch +#define ThisEntries TouchEntries + +#define ThisKey "touch" +#define ThisNative "ham_touch" +#define ThisENative "ham_etouch" +#define ThisRegisterID HAM_Touch +#define ThisParamCount 1 +#define ThisVoidCall 1 + + +unsigned int *ThisVTable::pevoffset=NULL; +unsigned int *ThisVTable::pevset=NULL; +unsigned int *ThisVTable::baseoffset=NULL; +unsigned int *ThisVTable::baseset=0; +unsigned int ThisVTable::index=0; +unsigned int ThisVTable::indexset=0; + +static AMX_NATIVE_INFO callnatives[] = { + { ThisNative, ThisVTable::NativeCall }, + { ThisENative, ThisVTable::ENativeCall }, + { NULL, NULL } +}; + +/** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ +void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset) +{ + ThisVTable::pevoffset=poffset; + ThisVTable::pevset=pset; + + ThisVTable::baseoffset=baseoffs; + ThisVTable::baseset=baseset; + + ThisVTable::index=0; + ThisVTable::indexset=0; + + RegisterConfigCallback(ThisVTable::ConfigDone); + + RegisterKeySuffix(ThisKey,ThisVTable::KeyValue); + + RegisterThisRegisterName(ThisRegisterID,ThisKey); +}; + +/** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ +void ThisVTable::KeyValue(const char *key, const char *data) +{ + if (strcmp(key,ThisKey)==0) + { + ThisVTable::index=HAM_StrToNum(data); + ThisVTable::indexset=1; + } +}; + +/** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ +void ThisVTable::ConfigDone(void) +{ + if (ThisVTable::indexset && *(ThisVTable::baseset)) + { + MF_AddNatives(callnatives); + + if (*(ThisVTable::pevset)) + { + RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative); + } + } +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterNative(AMX *amx, cell *params) +{ + // Get the classname + char *classname=MF_GetAmxString(amx,params[1],1,NULL); + + // create an entity, assign it the gamedll's class, hook it and destroy it + edict_t *Entity=CREATE_ENTITY(); + + CALL_GAME_ENTITY(PLID,classname,&Entity->v); + + if (Entity->pvPrivateData) + { + // Simulate a call to hs_register_id_takedamage + cell tempparams[4]; + memcpy(tempparams,params,sizeof(cell)*4); + tempparams[1]=ENTINDEX_NEW(Entity); + ThisVTable::RegisterIDNative(amx,&tempparams[0]); + REMOVE_ENTITY(Entity); + return 1; + } + + REMOVE_ENTITY(Entity); + // class was not found + // throw an error alerting console that this hook did not happen + char *function=MF_GetAmxString(amx,params[2],0,NULL); + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for \"%s\", hook for \"%s\" not active.",classname,function); + + return 0; + +}; + +/** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) +{ + int funcid; + char *function=MF_GetAmxString(amx,params[2],0,NULL); + + if (MF_AmxFindPublic(amx,function,&funcid)!=AMX_ERR_NONE) + { + MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); + return 0; + } + edict_t *Entity=INDEXENT_NEW(params[1]); + + if (Entity->pvPrivateData) + { + ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid,params[0] / sizeof(cell) > 2 ? params[3] : 0); + return 1; + } + + // class was not found + // throw an error alerting console that this hook did not happen + MF_LogError(amx, AMX_ERR_NATIVE,"Failed to retrieve classtype for entity id %d, hook for \"%s\" not active.",params[1],function); + + return 0; + +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::NativeCall(AMX *amx, cell *params) +{ + // scan to see if this virtual function is a trampoline + void *pthis=INDEXENT_NEW(params[1])->pvPrivateData; + void *func=GetVTableEntry(pthis,ThisVTable::index,*ThisVTable::baseoffset); + + int i=0; + int end=VTMan.ThisEntries.size(); + + while (iIsTrampoline(func)) + { + // this function is a trampoline + // use the original function instead + func=VTMan.ThisEntries[i]->GetOriginalFunction(); + break; + } + ++i; + } + // TODO: Inline ASM this +#ifdef _WIN32 + reinterpret_cast(func)( + pthis, /*this*/ + 0, /*fastcall buffer*/ + INDEXENT_NEW(params[2])->pvPrivateData /*other*/ + ); +#else + reinterpret_cast(func)( + pthis, /*this*/ + INDEXENT_NEW(params[2])->pvPrivateData /*other*/ + ); +#endif + return 1; +}; + +/** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ +cell ThisVTable::ENativeCall(AMX *amx, cell *params) +{ + VoidVCall1( + INDEXENT_NEW(params[1])->pvPrivateData, /*this*/ + ThisVTable::index, /*vtable entry*/ + *(ThisVTable::baseoffset), /*size of class*/ + INDEXENT_NEW(params[2])->pvPrivateData /*other*/ + ); + + return 1; +}; + +/** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ +void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc) +{ + + VTableEntryBase::CreateGenericTrampoline(manager, + vtable, + ThisVTable::index, + id, + outtrampoline, + origfunc, + reinterpret_cast(ThisVTable::EntryPoint), + ThisParamCount, // param count + ThisVoidCall, // voidcall + 1); // thiscall + +}; + +/** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ +void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post) +{ + void *ptr=vtable[ThisVTable::index]; + + int i=0; + int end=manager->ThisEntries.size(); + int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*other*/,FP_DONE); + while (iThisEntries[i]->IsTrampoline(ptr)) + { + // this function is already hooked! + + if (post) + { + manager->ThisEntries[i]->AddPostForward(fwd); + } + else + { + manager->ThisEntries[i]->AddForward(fwd); + } + + return; + } + + ++i; + } + // this function is NOT hooked + void *tramp; + void *func; + ThisVTable::CreateHook(manager,vtable,manager->ThisEntries.size(),&tramp,&func); + ThisVTable *entry=new ThisVTable; + + entry->Setup(&vtable[ThisVTable::index],tramp,func); + + manager->ThisEntries.push_back(entry); + + if (post) + { + entry->AddPostForward(fwd); + } + else + { + entry->AddForward(fwd); + } + +} + +/** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param activator Entity causing the opening. + * @param caller Entity controlling the caller. + * @param type USE_TYPE (USE_{ON,OFF,SET} + * @param value Use value, only seen set when USE_SET is used. + * @noreturn + */ +void ThisVTable::Execute(void *pthis, void *other) +{ + int i=0; + + int end=Forwards.size(); + + int result=HAM_UNSET; + int thisresult=HAM_UNSET; + + int iThis=PrivateToIndex(pthis); + int iOther=PrivateToIndex(other); + + while (iresult) + { + result=thisresult; + } + }; + + if (result(function)(pthis,0,other); +#elif defined __linux__ + reinterpret_cast(function)(pthis,other); +#endif + } + + i=0; + end=PostForwards.size(); + while (iExecute(pthis,other); +} diff --git a/dlls/hamsandwich/tableentries/Use.cpp b/dlls/hamsandwich/tableentries/Use.cpp index 0cac675f..6bfaf8d7 100644 --- a/dlls/hamsandwich/tableentries/Use.cpp +++ b/dlls/hamsandwich/tableentries/Use.cpp @@ -15,8 +15,8 @@ #define ThisEntries UseEntries #define ThisKey "use" -#define ThisNative "hs_use" -#define ThisENative "hs_euse" +#define ThisNative "ham_use" +#define ThisENative "ham_euse" #define ThisRegisterID HAM_Use #define ThisParamCount 4 #define ThisVoidCall 1 @@ -119,7 +119,6 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params) cell tempparams[4]; memcpy(tempparams,params,sizeof(cell)*4); tempparams[1]=ENTINDEX_NEW(Entity); - printf("TEMPPARAMS[1]==%d\n",tempparams[1]); ThisVTable::RegisterIDNative(amx,&tempparams[0]); REMOVE_ENTITY(Entity); return 1; @@ -153,7 +152,6 @@ cell ThisVTable::RegisterIDNative(AMX *amx, cell *params) MF_LogError(amx,AMX_ERR_NATIVE,"Can not find function \"%s\"",function); return 0; } - printf("PARAMS[1]==%d\n",params[1]); edict_t *Entity=INDEXENT_NEW(params[1]); if (Entity->pvPrivateData) @@ -377,5 +375,5 @@ void ThisVTable::Execute(void *pthis, void *activator, void *caller, int type, f }; HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,void *activator,void *caller,int type,float value) { - VTMan.UseEntries[id]->Execute(pthis,activator,caller,type,value); + VTMan.ThisEntries[id]->Execute(pthis,activator,caller,type,value); } diff --git a/dlls/hamsandwich/tableentries/VTableEntries.h b/dlls/hamsandwich/tableentries/VTableEntries.h index 5d0803f8..cc2a17b5 100644 --- a/dlls/hamsandwich/tableentries/VTableEntries.h +++ b/dlls/hamsandwich/tableentries/VTableEntries.h @@ -176,6 +176,233 @@ public: }; + +// int ObjectCaps(void) TODO +class VTableObjectCaps : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int Classify(void) TODO +class VTableClassify : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + class VTableTraceAttack : public VTableEntryBase { public: @@ -291,6 +518,7 @@ public: */ static HAM_CDECL void EntryPoint(int id,void *pthis,void *pevattacker,float flDamage,float *direction,void *tr,int bits); }; +// int TakeDamage(entvars_t *inflictor, entvars_t *attacker, float damage, int type); class VTableTakeDamage : public VTableEntryBase { public: @@ -406,6 +634,121 @@ public: */ static HAM_CDECL int EntryPoint(int id,void *pthis,void *inflictor,void *attacker,float damage,int type); }; +// int BloodColor(void) TODO +class VTableBloodColor : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + + +// void Killed(entvars_t *attacker, int gib) class VTableKilled : public VTableEntryBase { public: @@ -519,6 +862,1946 @@ public: */ static HAM_CDECL void EntryPoint(int id,void *pthis,void *attacker, int gib); }; +// void Restart(void) CS ONLY +class VTableRestart : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + void Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL void EntryPoint(int id,void *pthis); +}; +// int GetToggleState(void) TODO +class VTableGetToggleState : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + + +// void AddPoints(int points, int allownegative) +class VTableAddPoints : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + void Execute(void *pthis, int points, int allowneg); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL void EntryPoint(int id,void *pthis,int points,int allownegative); +}; +// void AddPointsToTeam(int points, int allownegative) +class VTableAddPointsToTeam : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + void Execute(void *pthis, int points, int allowneg); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL void EntryPoint(int id,void *pthis,int points,int allownegative); +}; + +// int AddPlayerItem(CBasePlayerItem *item); +class VTableAddPlayerItem : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param item The private data of the item being added. + * @return Unsure. Does not appear to be used. + */ + int Execute(void *pthis, void *item); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + * @param item The private data of the item being added. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis,void *item); +}; +// int RemovePlayerItem(CBasePlayerItem *item); +class VTableRemovePlayerItem : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param item The private data of the item being added. + * @return Unsure. Does not appear to be used. + */ + int Execute(void *pthis, void *item); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + * @param item The private data of the item being added. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis,void *item); +}; + + + + + + + + + + +// int Is(void) TODO +class VTableIsMoving : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + + +// int Is(void) TODO +class VTableDamageDecal : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + + + +// int Is(void) TODO +class VTableIsSneaking : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int Is(void) TODO +class VTableIsAlive : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int Is(void) TODO +class VTableIsBSPModel : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int IsInWorld(void) TODO +class VTableIsInWorld : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int IsPlayer(void) TODO +class VTableIsPlayer : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// int IsNetClient(void) TODO +class VTableIsNetClient : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + */ + int Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL int EntryPoint(int id,void *pthis); +}; + + +// const char *TeamID(void) TODO +class VTableTeamID : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + const char *Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL const char *EntryPoint(int id,void *pthis); +}; + +// void Think(void) TODO +class VTableThink : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + void Execute(void *pthis); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL void EntryPoint(int id,void *pthis); +}; +// void Touch(void *pOther) TODO +class VTableTouch : public VTableEntryBase +{ +public: + static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ + static unsigned int *pevset; /**< Whether or not pev entry has been set */ + static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ + static unsigned int *baseset; /**< Whether or base offset value has been set. */ + static unsigned int index; /**< This entry's virtual table index. */ + static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ + + /** + * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. + * + * @param poffset Pointer to an integer that stores the pev offset for this mod. + * @param pset Pointer to an integer that tells whether pev offset was set or not. + * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) + * @param baseset Pointer to an integer that tells whether class base offset has been set. + * @noreturn + */ + static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); + + /** + * Called when one of this table entry's keyvalues is caught in a config file. + * + * @param key The keyvalue suffix ("__" is removed) + * @param data The data this keyvalue is set to. + * @noreturn + */ + static void KeyValue(const char *key, const char *data); + + /** + * Called immediately after the config file is done being parsed. Register our natives here. + * + * @noreturn + */ + static void ConfigDone(void); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterNative(AMX *amx, cell *params); + + /** + * A plugin is registering this entry's virtual hook. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell RegisterIDNative(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell NativeCall(AMX *amx, cell *params); + + /** + * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. + * + * @param amx The AMX structure for the plugin. + * @param params The parameters passed from the plugin. + * @return 1 on success, 0 on failure. It only fails if the callback function is not found. + */ + static cell ENativeCall(AMX *amx, cell *params); + + /** + * Hook this entry's function! This creates our trampoline and modifies the virtual table. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param outtrampoline The trampoline that was created. + * @param origfunc The original function that was hooked. + * @noreturn + */ + static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); + + /** + * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. + * + * @param manager The VTableManager this is a child of. + * @param vtable The virtual table we're molesting. + * @param plugin The plugin that's requesting this. + * @param funcid The function id of the callback. + * @noreturn + */ + static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); + + /** + * Execute the command. This is called directly from our global hook function. + * + * @param pthis The "this" pointer, cast to a void. The victim. + * @param other Entity that's blocking. + * @noreturn + */ + void Execute(void *pthis, void *other); + + /** + * The hook that is directly called by the trampoline. + * + * @param id The index of the hook to call. + * @param pthis The "this" pointer. + */ + static HAM_CDECL void EntryPoint(int id,void *pthis,void *other); +}; +// void Use(CBaseEntity *activator, CBaseEntity *caller, USE_TYPE type, float value) class VTableUse : public VTableEntryBase { public: @@ -635,6 +2918,7 @@ public: static HAM_CDECL void EntryPoint(int id,void *pthis, void *activator, void *caller, int type, float value); }; +// void Blocked(CBaseEntity *pOther) class VTableBlocked : public VTableEntryBase { public: @@ -747,6 +3031,8 @@ public: */ static HAM_CDECL void EntryPoint(int id,void *pthis,void *other); }; + +// CBaseEntity *Respawn(void) class VTableRespawn : public VTableEntryBase { public: @@ -857,9 +3143,11 @@ public: * @param id The index of the hook to call. * @param pthis The "this" pointer. */ - static void *EntryPoint(int id,void *pthis); + static HAM_CDECL void *EntryPoint(int id,void *pthis); }; -class VTableRestart : public VTableEntryBase + +// void UpdateOwner(void) TODO +class VTableUpdateOwner : public VTableEntryBase { public: static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ @@ -971,230 +3259,8 @@ public: */ static HAM_CDECL void EntryPoint(int id,void *pthis); }; -class VTableAddPoints : public VTableEntryBase -{ -public: - static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ - static unsigned int *pevset; /**< Whether or not pev entry has been set */ - static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ - static unsigned int *baseset; /**< Whether or base offset value has been set. */ - static unsigned int index; /**< This entry's virtual table index. */ - static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ - /** - * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. - * - * @param poffset Pointer to an integer that stores the pev offset for this mod. - * @param pset Pointer to an integer that tells whether pev offset was set or not. - * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) - * @param baseset Pointer to an integer that tells whether class base offset has been set. - * @noreturn - */ - static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); - /** - * Called when one of this table entry's keyvalues is caught in a config file. - * - * @param key The keyvalue suffix ("__" is removed) - * @param data The data this keyvalue is set to. - * @noreturn - */ - static void KeyValue(const char *key, const char *data); - - /** - * Called immediately after the config file is done being parsed. Register our natives here. - * - * @noreturn - */ - static void ConfigDone(void); - - /** - * A plugin is registering this entry's virtual hook. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell RegisterNative(AMX *amx, cell *params); - - /** - * A plugin is registering this entry's virtual hook. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell RegisterIDNative(AMX *amx, cell *params); - - /** - * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell NativeCall(AMX *amx, cell *params); - - /** - * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell ENativeCall(AMX *amx, cell *params); - - /** - * Hook this entry's function! This creates our trampoline and modifies the virtual table. - * - * @param manager The VTableManager this is a child of. - * @param vtable The virtual table we're molesting. - * @param outtrampoline The trampoline that was created. - * @param origfunc The original function that was hooked. - * @noreturn - */ - static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); - - /** - * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. - * - * @param manager The VTableManager this is a child of. - * @param vtable The virtual table we're molesting. - * @param plugin The plugin that's requesting this. - * @param funcid The function id of the callback. - * @noreturn - */ - static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); - - /** - * Execute the command. This is called directly from our global hook function. - * - * @param pthis The "this" pointer, cast to a void. The victim. - * @param other Entity that's blocking. - * @noreturn - */ - void Execute(void *pthis, int points, int allowneg); - - /** - * The hook that is directly called by the trampoline. - * - * @param id The index of the hook to call. - * @param pthis The "this" pointer. - */ - static HAM_CDECL void EntryPoint(int id,void *pthis,int points,int allownegative); -}; -class VTableAddPointsToTeam : public VTableEntryBase -{ -public: - static unsigned int *pevoffset; /**< Offset of pev value (globally stored) */ - static unsigned int *pevset; /**< Whether or not pev entry has been set */ - static unsigned int *baseoffset; /**< Offset of the base class (only needed for GCC 2.95). */ - static unsigned int *baseset; /**< Whether or base offset value has been set. */ - static unsigned int index; /**< This entry's virtual table index. */ - static unsigned int indexset; /**< Whether or not this entry's virtual table index has been set. */ - - /** - * Initialize this table hook. This also registers our required keyvalue suffixes to the file parser. - * - * @param poffset Pointer to an integer that stores the pev offset for this mod. - * @param pset Pointer to an integer that tells whether pev offset was set or not. - * @param baseoffs Pointer to an integer that stores the class base offset for this mod. (GCC 2.95 only required) - * @param baseset Pointer to an integer that tells whether class base offset has been set. - * @noreturn - */ - static void Initialize(unsigned int *poffset, unsigned int *pset, unsigned int *baseoffs, unsigned int *baseset); - - /** - * Called when one of this table entry's keyvalues is caught in a config file. - * - * @param key The keyvalue suffix ("__" is removed) - * @param data The data this keyvalue is set to. - * @noreturn - */ - static void KeyValue(const char *key, const char *data); - - /** - * Called immediately after the config file is done being parsed. Register our natives here. - * - * @noreturn - */ - static void ConfigDone(void); - - /** - * A plugin is registering this entry's virtual hook. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell RegisterNative(AMX *amx, cell *params); - - /** - * A plugin is registering this entry's virtual hook. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell RegisterIDNative(AMX *amx, cell *params); - - /** - * A plugin is requesting a direct call of this entry's virtual function. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell NativeCall(AMX *amx, cell *params); - - /** - * A plugin is requesting a direct call of this entry's virtual function, and will be exposed to all hooks. This is a normal native callback. - * - * @param amx The AMX structure for the plugin. - * @param params The parameters passed from the plugin. - * @return 1 on success, 0 on failure. It only fails if the callback function is not found. - */ - static cell ENativeCall(AMX *amx, cell *params); - - /** - * Hook this entry's function! This creates our trampoline and modifies the virtual table. - * - * @param manager The VTableManager this is a child of. - * @param vtable The virtual table we're molesting. - * @param outtrampoline The trampoline that was created. - * @param origfunc The original function that was hooked. - * @noreturn - */ - static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc); - - /** - * Checks if the virtual function is already being hooked or not. If it's not, it begins hooking it. Either way it registers a forward and adds it to our vector. - * - * @param manager The VTableManager this is a child of. - * @param vtable The virtual table we're molesting. - * @param plugin The plugin that's requesting this. - * @param funcid The function id of the callback. - * @noreturn - */ - static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post); - - /** - * Execute the command. This is called directly from our global hook function. - * - * @param pthis The "this" pointer, cast to a void. The victim. - * @param other Entity that's blocking. - * @noreturn - */ - void Execute(void *pthis, int points, int allowneg); - - /** - * The hook that is directly called by the trampoline. - * - * @param id The index of the hook to call. - * @param pthis The "this" pointer. - */ - static HAM_CDECL void EntryPoint(int id,void *pthis,int points,int allownegative); -}; //TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); /*class VTableTraceAttack : public VTableEntryBase diff --git a/dlls/hamsandwich/tableentries/VTableManager.cpp b/dlls/hamsandwich/tableentries/VTableManager.cpp index 0dab6a66..56b31320 100644 --- a/dlls/hamsandwich/tableentries/VTableManager.cpp +++ b/dlls/hamsandwich/tableentries/VTableManager.cpp @@ -41,11 +41,11 @@ cell VTableManager::Register(AMX *amx, cell *params) { // this register is not found, fail the plugin int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE); + char error[256]; - char error[]="Requested to hs_registerid a function ID that is not registered in configs/hamdata.ini, cannot continue."; - int errorcell=MF_PrepareCharArray(&error[0],strlen(error)+1); + snprintf(&error[0],sizeof(error)-1,"Requested to ham_registerid a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id); - MF_ExecuteForward(fwd,errorcell); + MF_ExecuteForward(fwd,&error[0]); MF_UnregisterSPForward(fwd); return 0; @@ -71,10 +71,11 @@ cell VTableManager::RegisterID(AMX *amx, cell *params) // this register is not found, fail the plugin int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE); - char error[]="Requested to hs_register a function ID that is not registered in configs/hamdata.ini, cannot continue."; - int errorcell=MF_PrepareCharArray(&error[0],strlen(error)+1); + char error[256]; - MF_ExecuteForward(fwd,errorcell); + snprintf(&error[0],sizeof(error)-1,"Requested to ham_register a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id); + + MF_ExecuteForward(fwd,&error[0]); MF_UnregisterSPForward(fwd); return 0; diff --git a/dlls/hamsandwich/tableentries/VTableManager.h b/dlls/hamsandwich/tableentries/VTableManager.h index fe108763..be8a812f 100644 --- a/dlls/hamsandwich/tableentries/VTableManager.h +++ b/dlls/hamsandwich/tableentries/VTableManager.h @@ -87,6 +87,22 @@ public: VTINIT(Restart); VTINIT(AddPoints); VTINIT(AddPointsToTeam); + VTINIT(AddPlayerItem); + VTINIT(RemovePlayerItem); + VTINIT(BloodColor); + VTINIT(Classify); + VTINIT(GetToggleState); + VTINIT(IsAlive); + VTINIT(IsBSPModel); + VTINIT(IsInWorld); + VTINIT(IsMoving); + VTINIT(IsNetClient); + VTINIT(IsPlayer); + VTINIT(IsSneaking); + VTINIT(ObjectCaps); + VTINIT(Think); + VTINIT(Touch); + #undef VTINIT static NATIVEFUNC RegisterNatives[HAM_END_DONT_USE_ME]; static NATIVEFUNC RegisterIDNatives[HAM_END_DONT_USE_ME];