attempted merge at 1.77 back into trunk... Oh MY GOD
This commit is contained in:
280
dlls/hamsandwich/tableentries/Blocked.cpp
Normal file
280
dlls/hamsandwich/tableentries/Blocked.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
#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 VTableBlocked
|
||||
#define ThisEntries BlockedEntries
|
||||
#define ThisHook VHOOK_Blocked
|
||||
|
||||
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 registernatives[] = {
|
||||
{ "register_blocked", ThisVTable::RegisterNative },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static AMX_NATIVE_INFO callnatives[] = {
|
||||
{ "hs_blocked", ThisVTable::NativeCall },
|
||||
{ "hs_eblocked", 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("blocked",ThisVTable::KeyValue);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when one of this table entry's keyvalues is caught in a config file.
|
||||
*
|
||||
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
|
||||
* @param data The data this keyvalue is set to.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::KeyValue(const char *key, const char *data)
|
||||
{
|
||||
if (strcmp(key,"blocked")==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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
REMOVE_ENTITY(Entity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
REMOVE_ENTITY(Entity);
|
||||
// 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 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)
|
||||
{
|
||||
// TODO: This
|
||||
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)
|
||||
{
|
||||
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<void *>(ThisHook),
|
||||
1, // 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)
|
||||
{
|
||||
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 (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[i]->IsTrampoline(ptr))
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
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);
|
||||
|
||||
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 (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iOther);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int, void *)>(function)(pthis,0,other);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *,void *)>(function)(pthis,other);
|
||||
#endif
|
||||
|
||||
|
||||
};
|
322
dlls/hamsandwich/tableentries/TakeDamage.cpp
Normal file
322
dlls/hamsandwich/tableentries/TakeDamage.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
#include "sdk/amxxmodule.h"
|
||||
|
||||
#include "hamsandwich.h"
|
||||
|
||||
#include "hooks.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 VTableTakeDamage
|
||||
#define ThisEntries TakeDamageEntries
|
||||
#define ThisHook VHOOK_TakeDamage
|
||||
|
||||
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 registernatives[] = {
|
||||
{ "register_takedamage", ThisVTable::RegisterNative },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static AMX_NATIVE_INFO callnatives[] = {
|
||||
{ "hs_takedamage", ThisVTable::NativeCall },
|
||||
{ "hs_etakedamage", 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("takedamage",ThisVTable::KeyValue);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when one of this table entry's keyvalues is caught in a config file.
|
||||
*
|
||||
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
|
||||
* @param data The data this keyvalue is set to.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::KeyValue(const char *key, const char *data)
|
||||
{
|
||||
if (strcmp(key,"takedamage")==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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
REMOVE_ENTITY(Entity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
REMOVE_ENTITY(Entity);
|
||||
// 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 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 (i<end)
|
||||
{
|
||||
if (VTMan.ThisEntries[i]->IsTrampoline(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<int (__fastcall *)(void *,int,void *,void *,float,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
|
||||
&(INDEXENT_NEW(params[3])->v), /*attacker*/
|
||||
amx_ctof2(params[4]), /*damage*/
|
||||
(int)params[5] /*dmgtype*/
|
||||
);
|
||||
#else
|
||||
return reinterpret_cast<int (*)(void *,void *,void *,float,int)>(func)(
|
||||
pthis, /*this*/
|
||||
&(INDEXENT_NEW(params[2])->v), /*inflictor*/
|
||||
&(INDEXENT_NEW(params[3])->v), /*attacker*/
|
||||
amx_ctof2(params[4]), /*damage*/
|
||||
(int)params[5] /*dmgtype*/
|
||||
);
|
||||
#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<int>(
|
||||
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<void *>(ThisHook),
|
||||
4, // param count
|
||||
0, // 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)
|
||||
{
|
||||
void *ptr=vtable[ThisVTable::index];
|
||||
|
||||
int i=0;
|
||||
int end=manager->ThisEntries.size();
|
||||
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*inflictor*/,FP_CELL/*attacker*/,FP_CELL/*damage*/,FP_CELL/*type*/,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[i]->IsTrampoline(ptr))
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
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);
|
||||
|
||||
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 *inflictor, void *attacker, float damage, int type)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
int iInflictor=EntvarToIndex((entvars_t *)inflictor);
|
||||
int iAttacker=EntvarToIndex((entvars_t *)attacker);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iInflictor,iAttacker,amx_ftoc2(damage),type);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
// stop here
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
int ireturn=reinterpret_cast<int (__fastcall *)(void *,int,void *,void *,float,int)>(function)(pthis,0,inflictor,attacker,damage,type);
|
||||
#elif defined __linux__
|
||||
int ireturn=reinterpret_cast<int (*)(void *,void *,void *,float,int)>(function)(pthis,inflictor,attacker,damage,type);
|
||||
#endif
|
||||
|
||||
if (result!=HAM_OVERRIDE)
|
||||
return ireturn;
|
||||
|
||||
return 0;
|
||||
};
|
282
dlls/hamsandwich/tableentries/Use.cpp
Normal file
282
dlls/hamsandwich/tableentries/Use.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
#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 VTableUse
|
||||
#define ThisEntries UseEntries
|
||||
#define ThisHook VHOOK_Use
|
||||
|
||||
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 registernatives[] = {
|
||||
{ "register_use", ThisVTable::RegisterNative },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static AMX_NATIVE_INFO callnatives[] = {
|
||||
{ "hs_use", ThisVTable::NativeCall },
|
||||
{ "hs_euse", 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("use",ThisVTable::KeyValue);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when one of this table entry's keyvalues is caught in a config file.
|
||||
*
|
||||
* @param key The keyvalue suffix ("<mod>_<os>_" is removed)
|
||||
* @param data The data this keyvalue is set to.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::KeyValue(const char *key, const char *data)
|
||||
{
|
||||
if (strcmp(key,"use")==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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
REMOVE_ENTITY(Entity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
REMOVE_ENTITY(Entity);
|
||||
// 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 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)
|
||||
{
|
||||
// TODO: This
|
||||
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)
|
||||
{
|
||||
VoidVCall4(
|
||||
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
|
||||
ThisVTable::index, /*vtable entry*/
|
||||
*(ThisVTable::baseoffset), /*size of class*/
|
||||
INDEXENT_NEW(params[2])->pvPrivateData, /*activator*/
|
||||
INDEXENT_NEW(params[3])->pvPrivateData, /*caller*/
|
||||
params[4], /*type*/
|
||||
amx_ctof2(params[5])); /*value*/
|
||||
|
||||
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<void *>(ThisHook),
|
||||
4, // 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)
|
||||
{
|
||||
void *ptr=vtable[ThisVTable::index];
|
||||
|
||||
int i=0;
|
||||
int end=manager->ThisEntries.size();
|
||||
int fwd=MF_RegisterSPForward(plugin,funcid,FP_CELL/*this*/,FP_CELL/*inflictor*/,FP_CELL/*attacker*/,FP_CELL/*damage*/,FP_CELL/*type*/,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[i]->IsTrampoline(ptr))
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
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);
|
||||
|
||||
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 *activator, void *caller, int type, float value)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
int iActivator=PrivateToIndex(activator);
|
||||
int iCaller=PrivateToIndex(caller);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iActivator,iCaller,type,amx_ftoc2(value));
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,void *,void *,int,float)>(function)(pthis,0,activator,caller,type,value);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *,void *,void *,int,float)>(function)(pthis,activator,caller,type,value);
|
||||
#endif
|
||||
|
||||
};
|
462
dlls/hamsandwich/tableentries/VTableEntries.h
Normal file
462
dlls/hamsandwich/tableentries/VTableEntries.h
Normal file
@ -0,0 +1,462 @@
|
||||
/* Ham Sandwich
|
||||
*
|
||||
* by the AMX Mod X Dev Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VTABLEENTRIES_H
|
||||
#define VTABLEENTRIES_H
|
||||
|
||||
#include "CVector.h"
|
||||
|
||||
#include "hooks.h"
|
||||
|
||||
class VTableManager;
|
||||
|
||||
class VTableEntryBase
|
||||
{
|
||||
public:
|
||||
void *function; /**< The pointer to the original function that is being hooked. */
|
||||
void **location; /**< The location of the vtable entry that is being hooked. */
|
||||
void *trampoline; /**< Our trampoline (needs to be freed when it's not hooking any more!). */
|
||||
CVector<int> Forwards; /**< Vector of forwards to call for this hook.*/
|
||||
|
||||
/**
|
||||
* Saves virtual table location, trampoline and function pointers.
|
||||
*
|
||||
* @param vt Pointer to the index in the virtual table.
|
||||
* @param tramp Pointer to the trampoline.
|
||||
* @param func Pointer to the original function.
|
||||
* @noreturn
|
||||
*/
|
||||
void Setup(void **vt,void *tramp, void *func)
|
||||
{
|
||||
location=vt;
|
||||
trampoline=tramp;
|
||||
function=func;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Manually called by VTableManager at destruction. Treat this like a dtor.
|
||||
*
|
||||
* @see VTableManager::Cleanup()
|
||||
* @noreturn
|
||||
*/
|
||||
void Destroy()
|
||||
{
|
||||
// restore original location
|
||||
if (location)
|
||||
{
|
||||
#if defined _WIN32
|
||||
DWORD OldFlags;
|
||||
VirtualProtect(location,sizeof(int*),PAGE_READWRITE,&OldFlags);
|
||||
#elif defined __linux__
|
||||
mprotect(location,sizeof(int*),PROT_READ|PROT_WRITE);
|
||||
#endif
|
||||
|
||||
*location=function;
|
||||
}
|
||||
|
||||
// free the trampoline
|
||||
free(trampoline);
|
||||
|
||||
Forwards.clear();
|
||||
|
||||
};
|
||||
/**
|
||||
* Tells whether the given pointer is this entry's trampoline.
|
||||
*
|
||||
* @param ptr Pointer (cast to void*) of the function in question.
|
||||
* @return true: Yes, the pointer in question is this entry's trampoline.
|
||||
* fase: No, the pointer in question is not this entry's trampoline.
|
||||
*/
|
||||
bool IsTrampoline(void *ptr)
|
||||
{
|
||||
return (ptr==trampoline);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the pointer (cast to void*) of the original function which is being hooked.
|
||||
*
|
||||
* @return Original function pointer, cast to void*.
|
||||
*/
|
||||
void *GetOriginalFunction(void)
|
||||
{
|
||||
return function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the location of this entry's virtual table entry itself.
|
||||
*
|
||||
* @return Pointer to this entry's virtual table entry.
|
||||
*/
|
||||
void **GetLocation(void)
|
||||
{
|
||||
return location;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a pointer to this entry's trampoline.
|
||||
*
|
||||
* @return Trampoline pointer, cast to void*.
|
||||
*/
|
||||
void *GetTrampoline(void)
|
||||
{
|
||||
return trampoline;
|
||||
};
|
||||
/**
|
||||
* Adds a forward to this entry's forward vector.
|
||||
*
|
||||
* @param fwd Forward index to add.
|
||||
* @noreturn
|
||||
*/
|
||||
void AddForward(int fwd)
|
||||
{
|
||||
Forwards.push_back(fwd);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a generic trampoline.
|
||||
*
|
||||
* @param manager The VTableManager this entry belongs to.
|
||||
* @param vtable Pointer to the virtual table to molest.
|
||||
* @param vindex VTable index to replace.
|
||||
* @param id The unique id of this trampoline.
|
||||
* @param outtrampoline Gets set to the location of the trampoline.
|
||||
* @param origfunc Gets set to the original function which is being hooked.
|
||||
* @param calee Target function this trampoline will call.
|
||||
* @param paramcount How many parameters this trampoline pushes.
|
||||
* @param voidcall Set to 1, this function does not return. 0 otherwise.
|
||||
* @param thiscall Set to 1, treat this function like a thiscall.
|
||||
*/
|
||||
static void CreateGenericTrampoline(VTableManager *manager, void **vtable, int vtableindex, int id, void **outtrampoline, void **origfunc, void *calee, int paramcount, int voidcall=1, int thiscall=1);
|
||||
|
||||
};
|
||||
|
||||
class VTableTakeDamage : 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 ("<mod>_<os>_" 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 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);
|
||||
|
||||
/**
|
||||
* 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 Execute(void *pthis, void *inflictor, void *attacker, float damage, int type);
|
||||
};
|
||||
class VTableUse : 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 ("<mod>_<os>_" 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 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);
|
||||
|
||||
/**
|
||||
* 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 Execute(void *pthis, void *activator, void *caller, int type, float value);
|
||||
};
|
||||
class VTableBlocked : 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 ("<mod>_<os>_" 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 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);
|
||||
|
||||
/**
|
||||
* 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 that's blocking.
|
||||
* @noreturn
|
||||
*/
|
||||
void Execute(void *pthis, void *other);
|
||||
};
|
||||
//TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
||||
/*class VTableTraceAttack : public VTableEntryBase
|
||||
{
|
||||
public:
|
||||
static void CreateHook(VTableManager *manager, void **vtable, int id, void **outtrampoline, void **origfunc);
|
||||
static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid);
|
||||
void Execute(void *pthis, entvars_t *attacker, float damage, float *direction, TraceResult *tr, int damagetype);
|
||||
};
|
||||
*/
|
||||
#endif // VTABLEENTRIES_H
|
104
dlls/hamsandwich/tableentries/VTableManager.cpp
Normal file
104
dlls/hamsandwich/tableentries/VTableManager.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include "sdk/amxxmodule.h"
|
||||
|
||||
#include "VTableManager.h"
|
||||
#include "VTableEntries.h"
|
||||
|
||||
#include "NEW_Util.h"
|
||||
|
||||
void *VTableManager::InsertIntoVTable(void **vtable, int index, void *trampoline)
|
||||
{
|
||||
void *func;
|
||||
#if defined _WIN32
|
||||
DWORD OldFlags;
|
||||
VirtualProtect(&vtable[index],sizeof(int*),PAGE_READWRITE,&OldFlags);
|
||||
#elif defined __linux__
|
||||
mprotect(&vtable[index],sizeof(int*),PROT_READ|PROT_WRITE);
|
||||
#endif
|
||||
func=vtable[index];
|
||||
vtable[index]=trampoline;
|
||||
|
||||
return func;
|
||||
};
|
||||
|
||||
|
||||
#define CLEAR_ENTRIES(Container) \
|
||||
i=Container.size(); \
|
||||
while (i--) \
|
||||
{ \
|
||||
Container[i]->Destroy(); \
|
||||
delete Container[i]; \
|
||||
} \
|
||||
Container.clear()
|
||||
|
||||
|
||||
void VTableManager::Cleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
CLEAR_ENTRIES(UseEntries);
|
||||
CLEAR_ENTRIES(TakeDamageEntries);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void VTableEntryBase::CreateGenericTrampoline(VTableManager *manager, void **vtable, int vtid, int id, void **outtrampoline, void **origfunc, void *callee, int paramcount, int voidcall, int thiscall)
|
||||
{
|
||||
Trampolines::TrampolineMaker tramp;
|
||||
|
||||
if (voidcall)
|
||||
{
|
||||
if (thiscall)
|
||||
{
|
||||
tramp.ThisVoidPrologue();
|
||||
}
|
||||
else
|
||||
{
|
||||
tramp.VoidPrologue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thiscall)
|
||||
{
|
||||
tramp.ThisReturnPrologue();
|
||||
}
|
||||
else
|
||||
{
|
||||
tramp.ReturnPrologue();
|
||||
}
|
||||
}
|
||||
|
||||
while (paramcount)
|
||||
{
|
||||
tramp.PushParam(paramcount--);
|
||||
}
|
||||
if (thiscall)
|
||||
{
|
||||
tramp.PushThis();
|
||||
}
|
||||
tramp.PushNum(id);
|
||||
tramp.Call(callee);
|
||||
tramp.FreeTargetStack();
|
||||
if (voidcall)
|
||||
{
|
||||
#if defined _WIN32
|
||||
tramp.VoidEpilogueAndFree();
|
||||
#elif defined __linux__
|
||||
tramp.VoidEpilogue();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined _WIN32
|
||||
tramp.ReturnEpilogueAndFree();
|
||||
#elif defined __linux__
|
||||
tramp.ReturnEpilogue();
|
||||
#endif
|
||||
}
|
||||
|
||||
void *trampoline=tramp.Finish(NULL);
|
||||
|
||||
*outtrampoline=trampoline;
|
||||
|
||||
*origfunc=manager->InsertIntoVTable(vtable,vtid,trampoline);
|
||||
};
|
93
dlls/hamsandwich/tableentries/VTableManager.h
Normal file
93
dlls/hamsandwich/tableentries/VTableManager.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef VTABLEMANAGER_H
|
||||
#define VTABLEMANAGER_H
|
||||
|
||||
#include "Trampolines.h"
|
||||
|
||||
#include "CVector.h"
|
||||
#include "hooks.h"
|
||||
#include "VTableEntries.h"
|
||||
|
||||
/* !!WARNING: HERE BE DRAGONS
|
||||
|
||||
.~))>>
|
||||
.~)>>
|
||||
.~))))>>>
|
||||
.~))>> ___
|
||||
.~))>>)))>> .-~))>>
|
||||
.~)))))>> .-~))>>)>
|
||||
.~)))>>))))>> .-~)>>)>
|
||||
) .~))>>))))>> .-~)))))>>)>
|
||||
( )@@*) //)>)))))) .-~))))>>)>
|
||||
).@(@@ //))>>))) .-~))>>)))))>>)>
|
||||
(( @.@). //))))) .-~)>>)))))>>)>
|
||||
)) )@@*.@@ ) //)>))) //))))))>>))))>>)>
|
||||
(( ((@@@.@@ |/))))) //)))))>>)))>>)>
|
||||
)) @@*. )@@ ) (\_(\-\b |))>)) //)))>>)))))))>>)>
|
||||
(( @@@(.@(@ . _/`-` ~|b |>))) //)>>)))))))>>)>
|
||||
)* @@@ )@* (@) (@) /\b|))) //))))))>>))))>>
|
||||
(( @. )@( @ . _/ / / \b)) //))>>)))))>>>_._
|
||||
)@@ (@@*)@@. (6///6)- / ^ \b)//))))))>>)))>> ~~-.
|
||||
( @jgs@@. @@@.*@_ VvvvvV// ^ \b/)>>))))>> _. `bb
|
||||
((@@ @@@*.(@@ . - | o |' \ ( ^ \b)))>> .' b`,
|
||||
((@@).*@@ )@ ) \^^^/ (( ^ ~)_ \ / b `,
|
||||
(@@. (@@ ). `-' ((( ^ `\ \ \ \ \| b `.
|
||||
(*.@* / (((( \| | | \ . b `.
|
||||
/ / ((((( \ \ / _.-~\ Y, b ;
|
||||
/ / / (((((( \ \.-~ _.`" _.-~`, b ;
|
||||
/ / `(((((() ) (((((~ `, b ;
|
||||
_/ _/ `"""/ /' ; b ;
|
||||
_.-~_.-~ / /' _.'~bb _.'
|
||||
((((~~ / /' _.'~bb.--~
|
||||
(((( __.-~bb.-~
|
||||
.' b .~~
|
||||
:bb ,'
|
||||
~~~~
|
||||
*/
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
HAM_UNSET = 0,
|
||||
HAM_IGNORED,
|
||||
HAM_HANDLED,
|
||||
HAM_OVERRIDE,
|
||||
HAM_SUPERCEDE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
HAM_TYPE_UNKNOWN = 0,
|
||||
HAM_TYPE_CBASE,
|
||||
HAM_TYPE_ENTVAR,
|
||||
HAM_TYPE_EDICT,
|
||||
HAM_TYPE_INT,
|
||||
HAM_TYPE_FLOAT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
HAM_ERROR_BOUNDS = -2,
|
||||
HAM_ERROR_TYPE = -1,
|
||||
HAM_ERROR_NONE = 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class VTableManager
|
||||
{
|
||||
public:
|
||||
CVector<VTableUse *> UseEntries;
|
||||
CVector<VTableTakeDamage *> TakeDamageEntries;
|
||||
CVector<VTableBlocked *> BlockedEntries;
|
||||
|
||||
/* returns the original function */
|
||||
void *InsertIntoVTable(void **vtable, int index, void *trampoline);
|
||||
void Cleanup(void);
|
||||
};
|
||||
|
||||
extern VTableManager VTMan;
|
||||
|
||||
//#include "VTableEntries.h"
|
||||
|
||||
#endif // VTABLEMANAGER_H
|
Reference in New Issue
Block a user