mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-24 13:55:36 +03:00
Continued making adding new entries easier
{hs_}register_function->ham_register(HamHook:function,...) Added a few more hooks Fixed a few directory errors Updated config file
This commit is contained in:
parent
71065a65dd
commit
8939c3076a
@ -20,7 +20,7 @@ static char *FP_FormatLine(char *data)
|
||||
{
|
||||
char *End; /**< Pointer to the end of the string. */
|
||||
char *Start; /**< Pointer to the start of the string. */
|
||||
char *Temp=Start; /**< Temporary pointer for parsing. */
|
||||
char *Temp; /**< Temporary pointer for parsing. */
|
||||
|
||||
Start=data;
|
||||
|
||||
|
@ -25,7 +25,9 @@ BIN_SUFFIX = amxx_i386.so
|
||||
|
||||
OBJECTS = sdk/amxxmodule.cpp FileParser.cpp amxxapi.cpp hooks.cpp \
|
||||
tableentries/VTableManager.cpp tableentries/TakeDamage.cpp tableentries/Use.cpp \
|
||||
tableentries/Blocked.cpp
|
||||
tableentries/Blocked.cpp tableentries/Killed.cpp tableentries/Respawn.cpp \
|
||||
tableentries/Restart.cpp tableentries/AddPoints.cpp tableentries/AddPointsToTeam.cpp \
|
||||
|
||||
|
||||
|
||||
#natives.cpp vtable.cpp
|
||||
|
@ -37,6 +37,14 @@
|
||||
#endif
|
||||
|
||||
#if defined _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif // WIN32_LEAN_AND_MEAN
|
||||
#if _MSC_VER >= 1400
|
||||
#ifdef offsetof
|
||||
#undef offsetof
|
||||
#endif // offsetof
|
||||
#endif // _MSC_VER >= 1400
|
||||
#include <windows.h>
|
||||
#elif defined __linux__
|
||||
#include <sys/mman.h>
|
||||
|
@ -101,6 +101,12 @@ void HAM_CallInitialization(void)
|
||||
|
||||
VTINIT(TakeDamage);
|
||||
VTINIT(Use);
|
||||
VTINIT(Killed);
|
||||
VTINIT(Blocked);
|
||||
VTINIT(Respawn);
|
||||
VTINIT(Restart);
|
||||
VTINIT(AddPoints);
|
||||
VTINIT(AddPointsToTeam);
|
||||
|
||||
#undef VTINIT
|
||||
}
|
||||
@ -217,6 +223,8 @@ void OnAmxxAttach()
|
||||
HAM_classbaseset=1;
|
||||
#endif
|
||||
|
||||
RegisterRegisterNatives();
|
||||
|
||||
FP_SetupOffsets(ModKey,HAM_GetKey);
|
||||
|
||||
HAM_CallConfigDone();
|
||||
|
@ -26,10 +26,21 @@
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: 1.6 Steam (legitimate)
|
||||
cstrike_windows_takedamage 12
|
||||
cstrike_windows_killed 14 ;estimated
|
||||
cstrike_windows_addpoints 23 ;estimated
|
||||
cstrike_windows_addpointstoteam 24 ;estimated
|
||||
cstrike_windows_use 46
|
||||
cstrike_windows_blocked 47 ;estimated
|
||||
cstrike_windows_respawn 48 ;estimated
|
||||
cstrike_windows_pev 4
|
||||
cstrike_linux_restart 4 ;estimated
|
||||
cstrike_linux_takedamage 14
|
||||
cstrike_windows_addpoints 25 ;estimated
|
||||
cstrike_windows_addpointstoteam 26 ;estimated
|
||||
cstrike_linux_killed 16 ;estimated
|
||||
cstrike_linux_use 48
|
||||
cstrike_linux_blocked 49 ;estimated
|
||||
cstrike_linux_respawn 50 ;estimated
|
||||
cstrike_linux_pev 0
|
||||
cstrike_linux_classbase 0x94
|
||||
|
||||
@ -46,20 +57,20 @@ czero_linux_classbase 0x94
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: 3.1
|
||||
ns_windows_takedamage 10
|
||||
ns_windows_use 48
|
||||
ns_windows_use 49
|
||||
ns_windows_pev 4
|
||||
ns_linux_takedamage 11
|
||||
ns_linux_use 49
|
||||
ns_linux_use 50
|
||||
ns_linux_pev 4
|
||||
ns_linux_classbase 0x0
|
||||
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: 3.2 beta 2
|
||||
nsp_windows_takedamage 10
|
||||
nsp_windows_use 48
|
||||
nsp_windows_use 49
|
||||
nsp_windows_pev 4
|
||||
nsp_linux_takedamage 11
|
||||
nsp_linux_use 49
|
||||
nsp_linux_use 50
|
||||
nsp_linux_pev 4
|
||||
nsp_linux_classbase 0x0
|
||||
|
||||
@ -75,23 +86,23 @@ dod_linux_classbase 0x154
|
||||
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: 2.1
|
||||
ts_windows_takedamage 14
|
||||
ts_windows_use 48
|
||||
ts_windows_takedamage 12
|
||||
ts_windows_use 44
|
||||
ts_windows_pev 4
|
||||
ts_linux_takedamage 16
|
||||
ts_linux_use 50
|
||||
ts_linux_takedamage 14
|
||||
ts_linux_use 46
|
||||
ts_linux_pev 0
|
||||
ts_linux_classbase 0x60
|
||||
ts_linux_classbase 0x470
|
||||
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: ?? (Most up to date) Steam (legitimate)
|
||||
tfc_windows_takedamage 12
|
||||
tfc_windows_use 44
|
||||
; Version tested: 1.5 Steam (legitimate)
|
||||
tfc_windows_takedamage 14
|
||||
tfc_windows_use 48
|
||||
tfc_windows_pev 4
|
||||
tfc_linux_takedamage 14
|
||||
tfc_linux_use 46
|
||||
tfc_linux_takedamage 16
|
||||
tfc_linux_use 50
|
||||
tfc_linux_pev 0
|
||||
tfc_linux_classbase 0x470
|
||||
tfc_linux_classbase 0x60
|
||||
|
||||
; Data dated: 2007-02-23
|
||||
; Version tested: 3.0
|
||||
@ -102,7 +113,7 @@ svencoop_windows_pev 4
|
||||
|
||||
; Data dated: 2007-02-26
|
||||
; Version tested: 2.18.07
|
||||
; Earth's Special Forces (I can't find the non beta version, but it should still work!
|
||||
; Earth's Special Forces (I can't find the non beta version, but it should still work!)
|
||||
; ESF does not have a Linux binary!
|
||||
esf_openbeta_windows_takedamage 12
|
||||
esf_openbeta_windows_use 46
|
@ -36,6 +36,20 @@
|
||||
extern unsigned int HAM_pev;
|
||||
extern unsigned int HAM_classbase;
|
||||
|
||||
enum HAMHooks
|
||||
{
|
||||
HAM_TakeDamage,
|
||||
HAM_Use,
|
||||
HAM_AddPoints,
|
||||
HAM_AddPointsToTeam,
|
||||
HAM_Blocked,
|
||||
HAM_Killed,
|
||||
HAM_Respawn,
|
||||
HAM_Restart,
|
||||
HAM_TakeHealth,
|
||||
|
||||
HAM_END_DONT_USE_ME
|
||||
};
|
||||
|
||||
inline edict_t *PrivateToEdict(const void *pdata)
|
||||
{
|
||||
|
@ -12,6 +12,10 @@
|
||||
#pragma library hamsandwich
|
||||
#endif
|
||||
|
||||
#if !defined _amxmodx_included
|
||||
#include <amxmodx>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ham Sandwich general usage
|
||||
* -
|
||||
@ -112,6 +116,15 @@ native hs_etakedamage(id,inflictor,attacker,Float:damage,type);
|
||||
native hs_use(id,activator,caller,use_type,Float:use_value);
|
||||
native hs_euse(id,activator,caller,use_type,Float:use_value);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
enum
|
||||
@ -133,7 +146,7 @@ enum
|
||||
* 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[]);
|
||||
native register_takedamage(const classname[], const function[], post=0);
|
||||
|
||||
/**
|
||||
* Forwards all use routines that would occur to the given
|
||||
@ -145,4 +158,31 @@ native register_takedamage(const classname[], const function[]);
|
||||
* 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[]);
|
||||
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
|
||||
{
|
||||
HAM_TakeDamage,
|
||||
HAM_Use,
|
||||
HAM_AddPoints,
|
||||
HAM_AddPointsToTeam,
|
||||
HAM_Blocked,
|
||||
HAM_Killed,
|
||||
HAM_Respawn,
|
||||
HAM_Restart,
|
||||
HAM_TakeHealth,
|
||||
|
||||
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);
|
||||
}
|
@ -133,7 +133,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="z:\metamod\metamod;z:\hlsdk\common;z:\hlsdk\engine;z:\hlsdk\dlls;z:\hlsdk\pm_shared;.."
|
||||
AdditionalIncludeDirectories="z:\metamod\metamod;z:\hlsdk\common;z:\hlsdk\engine;z:\hlsdk\dlls;z:\hlsdk\pm_shared;"$(ProjectDir)\..\tableentries";"$(ProjectDir)\..""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ns_amxx_EXPORTS"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
@ -214,6 +214,50 @@
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Entries"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\tableentries\AddPoints.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\AddPointsToTeam.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\Blocked.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\Killed.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\Respawn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\Restart.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\TakeDamage.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\TakeHealth.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\Use.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\tableentries\VTableEntries.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\amxxapi.cpp"
|
||||
>
|
||||
@ -234,10 +278,6 @@
|
||||
RelativePath="..\Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\natives.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\NEW_Util.h"
|
||||
>
|
||||
@ -255,11 +295,11 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vtable.cpp"
|
||||
RelativePath="..\tableentries\VTableManager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\VTableManager.h"
|
||||
RelativePath="..\tableentries\VTableManager.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
|
363
dlls/hamsandwich/tableentries/AddPoints.cpp
Normal file
363
dlls/hamsandwich/tableentries/AddPoints.cpp
Normal file
@ -0,0 +1,363 @@
|
||||
#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 VTableAddPoints
|
||||
#define ThisEntries AddPointsEntries
|
||||
#define ThisKey "addpoints"
|
||||
#define ThisNative "hs_addpoints"
|
||||
#define ThisENative "hs_eaddpoints"
|
||||
#define ThisRegisterID HAM_AddPoints
|
||||
#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 ("<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,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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 (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
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
#else
|
||||
reinterpret_cast<void (*)(void *,int,int)>(func)(
|
||||
pthis, /*this*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
#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)
|
||||
{
|
||||
VoidVCall2(
|
||||
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
|
||||
ThisVTable::index, /*vtable entry*/
|
||||
*(ThisVTable::baseoffset), /*size of class*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
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 *>(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,FP_CELL,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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 points, int allownegative)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,points,allownegative);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(function)(pthis,0,points,allownegative);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *,int,int)>(function)(pthis,points,allownegative);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,points,allownegative);
|
||||
}
|
||||
|
||||
};
|
||||
HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative)
|
||||
{
|
||||
VTMan.AddPointsEntries[id]->Execute(pthis,points,allownegative);
|
||||
}
|
362
dlls/hamsandwich/tableentries/AddPointsToTeam.cpp
Normal file
362
dlls/hamsandwich/tableentries/AddPointsToTeam.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
#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 VTableAddPointsToTeam
|
||||
#define ThisEntries AddPointsToTeamEntries
|
||||
#define ThisKey "addpointstoteam"
|
||||
#define ThisNative "hs_addpointstoteam"
|
||||
#define ThisENative "hs_eaddpointstoteam"
|
||||
#define ThisRegisterID HAM_AddPointsToTeam
|
||||
#define ThisParamCount 2
|
||||
#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 ("<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,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 (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
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
#else
|
||||
reinterpret_cast<void (*)(void *,int,int)>(func)(
|
||||
pthis, /*this*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
#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)
|
||||
{
|
||||
VoidVCall2(
|
||||
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
|
||||
ThisVTable::index, /*vtable entry*/
|
||||
*(ThisVTable::baseoffset), /*size of class*/
|
||||
params[2],
|
||||
params[3]
|
||||
);
|
||||
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 *>(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,FP_CELL,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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 points, int allownegative)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,points,allownegative);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,int,int)>(function)(pthis,0,points,allownegative);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *,int,int)>(function)(pthis,points,allownegative);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,points,allownegative);
|
||||
}
|
||||
|
||||
};
|
||||
HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,int points,int allownegative)
|
||||
{
|
||||
VTMan.AddPointsToTeamEntries[id]->Execute(pthis,points,allownegative);
|
||||
}
|
@ -13,7 +13,14 @@
|
||||
// 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
|
||||
|
||||
#define ThisKey "blocked"
|
||||
#define ThisNative "hs_blocked"
|
||||
#define ThisENative "hs_eblocked"
|
||||
#define ThisRegisterID HAM_Blocked
|
||||
#define ThisParamCount 1
|
||||
#define ThisVoidCall 1
|
||||
|
||||
|
||||
unsigned int *ThisVTable::pevoffset=NULL;
|
||||
unsigned int *ThisVTable::pevset=NULL;
|
||||
@ -22,11 +29,6 @@ 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 },
|
||||
@ -56,6 +58,8 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned
|
||||
RegisterConfigCallback(ThisVTable::ConfigDone);
|
||||
|
||||
RegisterKeySuffix("blocked",ThisVTable::KeyValue);
|
||||
|
||||
RegisterThisRegisterName(ThisRegisterID,ThisKey);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -87,7 +91,7 @@ void ThisVTable::ConfigDone(void)
|
||||
|
||||
if (*(ThisVTable::pevset))
|
||||
{
|
||||
MF_AddNatives(registernatives);
|
||||
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -101,14 +105,6 @@ void ThisVTable::ConfigDone(void)
|
||||
*/
|
||||
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);
|
||||
|
||||
@ -119,7 +115,11 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
|
||||
if (Entity->pvPrivateData)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
// 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;
|
||||
}
|
||||
@ -127,12 +127,46 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
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.
|
||||
*
|
||||
@ -142,8 +176,38 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
*/
|
||||
cell ThisVTable::NativeCall(AMX *amx, cell *params)
|
||||
{
|
||||
// TODO: This
|
||||
return 0;
|
||||
// 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
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,void *)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
|
||||
);
|
||||
#else
|
||||
reinterpret_cast<void (*)(void *,void *)>(func)(
|
||||
pthis, /*this*/
|
||||
INDEXENT_NEW(params[2])->pvPrivateData /*other*/
|
||||
);
|
||||
#endif
|
||||
return 1;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -183,7 +247,7 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
id,
|
||||
outtrampoline,
|
||||
origfunc,
|
||||
reinterpret_cast<void *>(ThisHook),
|
||||
reinterpret_cast<void *>(ThisVTable::EntryPoint),
|
||||
1, // param count
|
||||
1, // voidcall
|
||||
1); // thiscall
|
||||
@ -199,7 +263,7 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid)
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
|
||||
{
|
||||
void *ptr=vtable[ThisVTable::index];
|
||||
|
||||
@ -212,7 +276,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
manager->ThisEntries[i]->AddPostForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -229,7 +300,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
|
||||
manager->ThisEntries.push_back(entry);
|
||||
|
||||
entry->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
entry->AddPostForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->AddForward(fwd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -265,16 +343,24 @@ void ThisVTable::Execute(void *pthis, void *other)
|
||||
}
|
||||
};
|
||||
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
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
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,iOther);
|
||||
}
|
||||
|
||||
};
|
||||
HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,void *other)
|
||||
{
|
||||
VTMan.BlockedEntries[id]->Execute(pthis,other);
|
||||
}
|
||||
|
368
dlls/hamsandwich/tableentries/Killed.cpp
Normal file
368
dlls/hamsandwich/tableentries/Killed.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
#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 VTableKilled
|
||||
#define ThisEntries KilledEntries
|
||||
|
||||
#define ThisKey "killed"
|
||||
#define ThisNative "hs_killed"
|
||||
#define ThisENative "hs_ekilled"
|
||||
#define ThisRegisterID HAM_Killed
|
||||
#define ThisParamCount 2
|
||||
#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 ("<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,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 (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 *,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
|
||||
(int)params[3] /*gib*/
|
||||
);
|
||||
#else
|
||||
return reinterpret_cast<int (*)(void *,void *,int)>(func)(
|
||||
pthis, /*this*/
|
||||
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
|
||||
(int)params[3] /*gib*/
|
||||
);
|
||||
#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)
|
||||
{
|
||||
VoidVCall2(
|
||||
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
|
||||
ThisVTable::index, /*vtable entry*/
|
||||
*(ThisVTable::baseoffset), /*size of class*/
|
||||
&(INDEXENT_NEW(params[2])->v), /*pevattacker*/
|
||||
(int)params[3] /*gib*/
|
||||
);
|
||||
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 *>(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/*attacker*/,FP_CELL/*gib*/,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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.
|
||||
*/
|
||||
void ThisVTable::Execute(void *pthis, void *attacker, int gib)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
int iAttacker=EntvarToIndex((entvars_t *)attacker);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,iAttacker,gib);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,void *,int)>(function)(pthis,0,attacker,gib);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *,void *,int)>(function)(pthis,attacker,gib);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,iAttacker,gib);
|
||||
}
|
||||
|
||||
};
|
||||
HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis,void *attacker,int gib)
|
||||
{
|
||||
VTMan.KilledEntries[id]->Execute(pthis,attacker,gib);
|
||||
}
|
||||
|
356
dlls/hamsandwich/tableentries/Respawn.cpp
Normal file
356
dlls/hamsandwich/tableentries/Respawn.cpp
Normal file
@ -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 VTableRespawn
|
||||
#define ThisEntries RespawnEntries
|
||||
#define ThisKey "respawn"
|
||||
#define ThisNative "hs_respawn"
|
||||
#define ThisENative "hs_erespawn"
|
||||
#define ThisRegisterID HAM_Respawn
|
||||
#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[] = {
|
||||
{ "hs_respawn", ThisVTable::NativeCall },
|
||||
{ "hs_respawn", 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 ("<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,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 (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 PrivateToIndex(reinterpret_cast<void *(__fastcall *)(void *,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0 /*fastcall buffer*/
|
||||
));
|
||||
#else
|
||||
return PrivateToIndex(reinterpret_cast<void *(*)(void *)>(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 PrivateToIndex(VCall0<void *>(
|
||||
INDEXENT_NEW(params[1])->pvPrivateData, /*this*/
|
||||
ThisVTable::index, /*vtable entry*/
|
||||
*(ThisVTable::baseoffset) /*size of class*/
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 *>(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 (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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 Pointer to the this object it seems? Pointless
|
||||
*/
|
||||
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 (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
void *ret=NULL;
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
ret=reinterpret_cast<void *(__fastcall *)(void *,int)>(function)(pthis,0);
|
||||
#elif defined __linux__
|
||||
ret=reinterpret_cast<void *(*)(void *)>(function)(pthis);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
};
|
||||
extern "C" void *ThisVTable::EntryPoint(int id,void *pthis)
|
||||
{
|
||||
return VTMan.RespawnEntries[id]->Execute(pthis);
|
||||
}
|
356
dlls/hamsandwich/tableentries/Restart.cpp
Normal file
356
dlls/hamsandwich/tableentries/Restart.cpp
Normal file
@ -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 VTableRestart
|
||||
#define ThisEntries RestartEntries
|
||||
#define ThisKey "restart"
|
||||
#define ThisNative "hs_restart"
|
||||
#define ThisENative "hs_erestart"
|
||||
#define ThisRegisterID HAM_Restart
|
||||
#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 ("<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,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 (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
|
||||
reinterpret_cast<void (__fastcall *)(void *,int)>(func)(
|
||||
pthis, /*this*/
|
||||
0 /*fastcall buffer*/
|
||||
);
|
||||
#else
|
||||
reinterpret_cast<void (*)(void *)>(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<void *>(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 (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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 (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
reinterpret_cast<void (__fastcall *)(void *,int)>(function)(pthis,0);
|
||||
#elif defined __linux__
|
||||
reinterpret_cast<void (*)(void *)>(function)(pthis);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
end=PostForwards.size();
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis);
|
||||
}
|
||||
|
||||
};
|
||||
HAM_CDECL void ThisVTable::EntryPoint(int id,void *pthis)
|
||||
{
|
||||
VTMan.RestartEntries[id]->Execute(pthis);
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include "hamsandwich.h"
|
||||
|
||||
#include "hooks.h"
|
||||
#include "VTableManager.h"
|
||||
#include "VTableEntries.h"
|
||||
|
||||
@ -14,7 +13,13 @@
|
||||
// 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
|
||||
|
||||
#define ThisKey "takedamage"
|
||||
#define ThisNative "hs_takedamage"
|
||||
#define ThisENative "hs_etakedamage"
|
||||
#define ThisRegisterID HAM_TakeDamage
|
||||
#define ThisParamCount 4
|
||||
#define ThisVoidCall 0
|
||||
|
||||
unsigned int *ThisVTable::pevoffset=NULL;
|
||||
unsigned int *ThisVTable::pevset=NULL;
|
||||
@ -23,14 +28,9 @@ 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 },
|
||||
{ ThisNative, ThisVTable::NativeCall },
|
||||
{ ThisENative, ThisVTable::ENativeCall },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@ -56,7 +56,9 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned
|
||||
|
||||
RegisterConfigCallback(ThisVTable::ConfigDone);
|
||||
|
||||
RegisterKeySuffix("takedamage",ThisVTable::KeyValue);
|
||||
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
|
||||
|
||||
RegisterThisRegisterName(ThisRegisterID,ThisKey);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -68,7 +70,7 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned
|
||||
*/
|
||||
void ThisVTable::KeyValue(const char *key, const char *data)
|
||||
{
|
||||
if (strcmp(key,"takedamage")==0)
|
||||
if (strcmp(key,ThisKey)==0)
|
||||
{
|
||||
ThisVTable::index=HAM_StrToNum(data);
|
||||
ThisVTable::indexset=1;
|
||||
@ -88,7 +90,8 @@ void ThisVTable::ConfigDone(void)
|
||||
|
||||
if (*(ThisVTable::pevset))
|
||||
{
|
||||
MF_AddNatives(registernatives);
|
||||
//MF_AddNatives(registernatives);
|
||||
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -102,14 +105,6 @@ void ThisVTable::ConfigDone(void)
|
||||
*/
|
||||
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);
|
||||
|
||||
@ -120,12 +115,18 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
|
||||
if (Entity->pvPrivateData)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
// 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);
|
||||
@ -134,6 +135,39 @@ cell ThisVTable::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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -220,9 +254,9 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
id,
|
||||
outtrampoline,
|
||||
origfunc,
|
||||
reinterpret_cast<void *>(ThisHook),
|
||||
4, // param count
|
||||
0, // voidcall
|
||||
reinterpret_cast<void *>(ThisVTable::EntryPoint),
|
||||
ThisParamCount, // param count
|
||||
ThisVoidCall, // voidcall
|
||||
1); // thiscall
|
||||
|
||||
};
|
||||
@ -236,7 +270,7 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid)
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
|
||||
{
|
||||
void *ptr=vtable[ThisVTable::index];
|
||||
|
||||
@ -249,7 +283,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
manager->ThisEntries[i]->AddPostForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -266,7 +307,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
|
||||
manager->ThisEntries.push_back(entry);
|
||||
|
||||
entry->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
entry->AddPostForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->AddForward(fwd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -302,21 +350,32 @@ int ThisVTable::Execute(void *pthis, void *inflictor, void *attacker, float dama
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
int ireturn=0;
|
||||
|
||||
// stop here
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
return 0;
|
||||
#if defined _WIN32
|
||||
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,void *,void *,float,int)>(function)(pthis,0,inflictor,attacker,damage,type);
|
||||
#elif defined __linux__
|
||||
ireturn=reinterpret_cast<int (*)(void *,void *,void *,float,int)>(function)(pthis,inflictor,attacker,damage,type);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
|
||||
end=PostForwards.size();
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,iInflictor,iAttacker,amx_ftoc2(damage),type);
|
||||
}
|
||||
|
||||
#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;
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
374
dlls/hamsandwich/tableentries/TakeHealth.cpp
Normal file
374
dlls/hamsandwich/tableentries/TakeHealth.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
#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 VTableTakeHealth
|
||||
#define ThisEntries TakeHealthEntries
|
||||
|
||||
#define ThisKey "takehealth"
|
||||
#define ThisNative "hs_takehealth"
|
||||
#define ThisENative "hs_etakehealth"
|
||||
#define ThisRegisterID HAM_TakeHealth
|
||||
#define ThisParamCount 2
|
||||
#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 ("<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,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_TakeHealth
|
||||
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 (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 *>(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/*amount*/,FP_CELL/*type*/,FP_DONE);
|
||||
while (i<end)
|
||||
{
|
||||
if (manager->ThisEntries[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, float amount, int type)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
int end=Forwards.size();
|
||||
|
||||
int result=HAM_UNSET;
|
||||
int thisresult=HAM_UNSET;
|
||||
|
||||
int iThis=PrivateToIndex(pthis);
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
thisresult=MF_ExecuteForward(Forwards[i++],iThis,amx_ftoc2(amount),type);
|
||||
|
||||
if (thisresult>result)
|
||||
{
|
||||
result=thisresult;
|
||||
}
|
||||
};
|
||||
int ireturn=0;
|
||||
|
||||
if (result<HAM_SUPERCEDE)
|
||||
{
|
||||
#if defined _WIN32
|
||||
ireturn=reinterpret_cast<int (__fastcall *)(void *,int,float,int)>(function)(pthis,0,amount,type);
|
||||
#elif defined __linux__
|
||||
ireturn=reinterpret_cast<int (*)(void *,float,int)>(function)(pthis,amount,type);
|
||||
#endif
|
||||
}
|
||||
|
||||
i=0;
|
||||
|
||||
end=PostForwards.size();
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,amx_ftoc2(amount),type);
|
||||
}
|
||||
|
||||
|
||||
if (result!=HAM_OVERRIDE)
|
||||
return ireturn;
|
||||
|
||||
return 0;
|
||||
};
|
@ -13,7 +13,14 @@
|
||||
// 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
|
||||
|
||||
#define ThisKey "use"
|
||||
#define ThisNative "hs_use"
|
||||
#define ThisENative "hs_euse"
|
||||
#define ThisRegisterID HAM_Use
|
||||
#define ThisParamCount 4
|
||||
#define ThisVoidCall 1
|
||||
|
||||
|
||||
unsigned int *ThisVTable::pevoffset=NULL;
|
||||
unsigned int *ThisVTable::pevset=NULL;
|
||||
@ -22,14 +29,9 @@ 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 },
|
||||
{ ThisNative, ThisVTable::NativeCall },
|
||||
{ ThisENative, ThisVTable::ENativeCall },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@ -55,7 +57,9 @@ void ThisVTable::Initialize(unsigned int *poffset, unsigned int *pset, unsigned
|
||||
|
||||
RegisterConfigCallback(ThisVTable::ConfigDone);
|
||||
|
||||
RegisterKeySuffix("use",ThisVTable::KeyValue);
|
||||
RegisterKeySuffix(ThisKey,ThisVTable::KeyValue);
|
||||
|
||||
RegisterThisRegisterName(ThisRegisterID,ThisKey);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -67,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,"use")==0)
|
||||
if (strcmp(key,ThisKey)==0)
|
||||
{
|
||||
ThisVTable::index=HAM_StrToNum(data);
|
||||
ThisVTable::indexset=1;
|
||||
@ -87,7 +91,7 @@ void ThisVTable::ConfigDone(void)
|
||||
|
||||
if (*(ThisVTable::pevset))
|
||||
{
|
||||
MF_AddNatives(registernatives);
|
||||
RegisterThisRegister(ThisRegisterID,ThisVTable::RegisterNative,ThisVTable::RegisterIDNative);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -101,14 +105,6 @@ void ThisVTable::ConfigDone(void)
|
||||
*/
|
||||
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);
|
||||
|
||||
@ -119,12 +115,19 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
|
||||
if (Entity->pvPrivateData)
|
||||
{
|
||||
ThisVTable::Hook(&VTMan,EdictToVTable(Entity),amx,funcid);
|
||||
// Simulate a call to hs_register_id_takedamage
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -133,6 +136,40 @@ cell ThisVTable::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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
printf("PARAMS[1]==%d\n",params[1]);
|
||||
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.
|
||||
*
|
||||
@ -142,7 +179,43 @@ cell ThisVTable::RegisterNative(AMX *amx, cell *params)
|
||||
*/
|
||||
cell ThisVTable::NativeCall(AMX *amx, cell *params)
|
||||
{
|
||||
// TODO: This
|
||||
// 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
|
||||
reinterpret_cast<void (__fastcall *)(void *,int,void *, void *, int, float)>(func)(
|
||||
pthis, /*this*/
|
||||
0, /*fastcall buffer*/
|
||||
INDEXENT_NEW(params[2])->pvPrivateData,
|
||||
INDEXENT_NEW(params[3])->pvPrivateData,
|
||||
params[4],
|
||||
amx_ctof2(params[5])
|
||||
);
|
||||
#else
|
||||
reinterpret_cast<void (*)(void *,void *, void *, int, float)>(func)(
|
||||
pthis, /*this*/
|
||||
INDEXENT_NEW(params[2])->pvPrivateData,
|
||||
INDEXENT_NEW(params[3])->pvPrivateData,
|
||||
params[4],
|
||||
amx_ctof2(params[5])
|
||||
);
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -185,9 +258,9 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
id,
|
||||
outtrampoline,
|
||||
origfunc,
|
||||
reinterpret_cast<void *>(ThisHook),
|
||||
4, // param count
|
||||
1, // voidcall
|
||||
reinterpret_cast<void *>(ThisVTable::EntryPoint),
|
||||
ThisParamCount, // param count
|
||||
ThisVoidCall, // voidcall
|
||||
1); // thiscall
|
||||
|
||||
};
|
||||
@ -201,7 +274,7 @@ void ThisVTable::CreateHook(VTableManager *manager, void **vtable, int id, void
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid)
|
||||
void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid, int post)
|
||||
{
|
||||
void *ptr=vtable[ThisVTable::index];
|
||||
|
||||
@ -214,7 +287,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
{
|
||||
// this function is already hooked!
|
||||
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
manager->ThisEntries[i]->AddPostForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
manager->ThisEntries[i]->AddForward(fwd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -231,7 +311,14 @@ void ThisVTable::Hook(VTableManager *manager, void **vtable, AMX *plugin, int fu
|
||||
|
||||
manager->ThisEntries.push_back(entry);
|
||||
|
||||
entry->AddForward(fwd);
|
||||
if (post)
|
||||
{
|
||||
entry->AddForward(fwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->AddPostForward(fwd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -268,15 +355,27 @@ void ThisVTable::Execute(void *pthis, void *activator, void *caller, int type, f
|
||||
}
|
||||
};
|
||||
|
||||
if (result>=HAM_SUPERCEDE)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#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
|
||||
i=0;
|
||||
|
||||
end=PostForwards.size();
|
||||
|
||||
while (i<end)
|
||||
{
|
||||
MF_ExecuteForward(PostForwards[i++],iThis,iActivator,iCaller,type,amx_ftoc2(value));
|
||||
};
|
||||
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
@ -32,9 +32,13 @@
|
||||
#ifndef VTABLEENTRIES_H
|
||||
#define VTABLEENTRIES_H
|
||||
|
||||
#include "CVector.h"
|
||||
#ifdef _WIN32
|
||||
#define HAM_CDECL __cdecl
|
||||
#else
|
||||
#define HAM_CDECL __attribute__((cdecl))
|
||||
#endif
|
||||
|
||||
#include "hooks.h"
|
||||
#include "CVector.h"
|
||||
|
||||
class VTableManager;
|
||||
|
||||
@ -45,6 +49,7 @@ public:
|
||||
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.*/
|
||||
CVector<int> PostForwards; /**< Vector of forwards to call for this post hook.*/
|
||||
|
||||
/**
|
||||
* Saves virtual table location, trampoline and function pointers.
|
||||
@ -87,6 +92,7 @@ public:
|
||||
free(trampoline);
|
||||
|
||||
Forwards.clear();
|
||||
PostForwards.clear();
|
||||
|
||||
};
|
||||
/**
|
||||
@ -141,6 +147,17 @@ public:
|
||||
Forwards.push_back(fwd);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a forward to this entry's post forward vector.
|
||||
*
|
||||
* @param fwd Forward index to add.
|
||||
* @noreturn
|
||||
*/
|
||||
void AddPostForward(int fwd)
|
||||
{
|
||||
PostForwards.push_back(fwd);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a generic trampoline.
|
||||
*
|
||||
@ -159,6 +176,121 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class VTableTraceAttack : 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 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 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 *pevattacker, float flDamage, float *direction, void *tr, int bitsDamageType);
|
||||
|
||||
/**
|
||||
* 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 *pevattacker,float flDamage,float *direction,void *tr,int bits);
|
||||
};
|
||||
class VTableTakeDamage : public VTableEntryBase
|
||||
{
|
||||
public:
|
||||
@ -205,6 +337,15 @@ public:
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -243,7 +384,7 @@ public:
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid);
|
||||
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.
|
||||
@ -256,6 +397,127 @@ public:
|
||||
* @return Unsure. Does not appear to be used.
|
||||
*/
|
||||
int Execute(void *pthis, void *inflictor, void *attacker, float damage, int type);
|
||||
|
||||
/**
|
||||
* 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 *inflictor,void *attacker,float damage,int type);
|
||||
};
|
||||
class VTableKilled : 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 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 attacker The attacker who caused the inflictor to damage the victim.
|
||||
* @param gib Whether to gib or not.
|
||||
* @noreturn
|
||||
*/
|
||||
void Execute(void *pthis, void *attacker, int gib);
|
||||
|
||||
/**
|
||||
* 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 *attacker, int gib);
|
||||
};
|
||||
class VTableUse : public VTableEntryBase
|
||||
{
|
||||
@ -312,6 +574,15 @@ public:
|
||||
*/
|
||||
static cell NativeCall(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, and will be exposed to all hooks. This is a normal native callback.
|
||||
*
|
||||
@ -341,7 +612,7 @@ public:
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid);
|
||||
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.
|
||||
@ -354,6 +625,15 @@ public:
|
||||
* @noreturn
|
||||
*/
|
||||
void Execute(void *pthis, void *activator, void *caller, int type, float value);
|
||||
|
||||
/**
|
||||
* 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 *activator, void *caller, int type, float value);
|
||||
|
||||
};
|
||||
class VTableBlocked : public VTableEntryBase
|
||||
{
|
||||
@ -401,6 +681,15 @@ public:
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -439,17 +728,474 @@ public:
|
||||
* @param funcid The function id of the callback.
|
||||
* @noreturn
|
||||
*/
|
||||
static void Hook(VTableManager *manager, void **vtable, AMX *plugin, int funcid);
|
||||
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 activator Entity that's blocking.
|
||||
* @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);
|
||||
};
|
||||
class VTableRespawn : 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 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 void *EntryPoint(int id,void *pthis);
|
||||
};
|
||||
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 ("<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 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);
|
||||
};
|
||||
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 ("<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 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 ("<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 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
|
||||
{
|
||||
|
@ -1,10 +1,98 @@
|
||||
#include "sdk/amxxmodule.h"
|
||||
|
||||
#include "hamsandwich.h"
|
||||
|
||||
#include "VTableManager.h"
|
||||
#include "VTableEntries.h"
|
||||
|
||||
#include "NEW_Util.h"
|
||||
|
||||
VTableManager VTMan;
|
||||
|
||||
NATIVEFUNC VTableManager::RegisterNatives[HAM_END_DONT_USE_ME];
|
||||
NATIVEFUNC VTableManager::RegisterIDNatives[HAM_END_DONT_USE_ME];
|
||||
const char *VTableManager::RegisterNames[HAM_END_DONT_USE_ME];
|
||||
|
||||
void RegisterThisRegister(int index,NATIVEFUNC byname, NATIVEFUNC byid)
|
||||
{
|
||||
VTableManager::RegisterNatives[index]=byname;
|
||||
VTableManager::RegisterIDNatives[index]=byid;
|
||||
}
|
||||
void RegisterThisRegisterName(int index, const char *name)
|
||||
{
|
||||
VTableManager::RegisterNames[index]=name;
|
||||
}
|
||||
|
||||
static AMX_NATIVE_INFO registernatives[] = {
|
||||
{ "ham_register", VTableManager::Register },
|
||||
{ "ham_registerid", VTableManager::RegisterID },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
void RegisterRegisterNatives(void)
|
||||
{
|
||||
MF_AddNatives(registernatives);
|
||||
}
|
||||
cell VTableManager::Register(AMX *amx, cell *params)
|
||||
{
|
||||
int id=params[1];
|
||||
|
||||
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterIDNatives[id]==NULL)
|
||||
{
|
||||
// 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_registerid a function ID that is not registered in configs/hamdata.ini, cannot continue.";
|
||||
int errorcell=MF_PrepareCharArray(&error[0],strlen(error)+1);
|
||||
|
||||
MF_ExecuteForward(fwd,errorcell);
|
||||
|
||||
MF_UnregisterSPForward(fwd);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
cell tempparams[4];
|
||||
|
||||
// remove one parameter from this param count
|
||||
tempparams[0]=(params[0]-(sizeof(cell)));
|
||||
tempparams[1]=params[2];
|
||||
tempparams[2]=params[3];
|
||||
tempparams[3]=params[4];
|
||||
|
||||
return RegisterNatives[id](amx,&tempparams[0]);
|
||||
}
|
||||
cell VTableManager::RegisterID(AMX *amx, cell *params)
|
||||
{
|
||||
int id=params[1];
|
||||
|
||||
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterNatives[id]==NULL)
|
||||
{
|
||||
// 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);
|
||||
|
||||
MF_ExecuteForward(fwd,errorcell);
|
||||
|
||||
MF_UnregisterSPForward(fwd);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
cell tempparams[4];
|
||||
|
||||
// remove one parameter from this param count
|
||||
tempparams[0]=(params[0]-(sizeof(cell)));
|
||||
tempparams[1]=params[2];
|
||||
tempparams[2]=params[3];
|
||||
tempparams[3]=params[4];
|
||||
|
||||
return RegisterIDNatives[id](amx,&tempparams[0]);
|
||||
}
|
||||
|
||||
|
||||
void *VTableManager::InsertIntoVTable(void **vtable, int index, void *trampoline)
|
||||
{
|
||||
void *func;
|
||||
|
@ -3,8 +3,9 @@
|
||||
|
||||
#include "Trampolines.h"
|
||||
|
||||
#include "hamsandwich.h"
|
||||
|
||||
#include "CVector.h"
|
||||
#include "hooks.h"
|
||||
#include "VTableEntries.h"
|
||||
|
||||
/* !!WARNING: HERE BE DRAGONS
|
||||
@ -72,22 +73,38 @@ enum
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef cell (*NATIVEFUNC)(AMX *, cell *);
|
||||
|
||||
class VTableManager
|
||||
{
|
||||
public:
|
||||
CVector<VTableUse *> UseEntries;
|
||||
CVector<VTableTakeDamage *> TakeDamageEntries;
|
||||
CVector<VTableBlocked *> BlockedEntries;
|
||||
#define VTINIT(Type) CVector<VTable##Type *> Type##Entries
|
||||
VTINIT(Use);
|
||||
VTINIT(TakeDamage);
|
||||
VTINIT(Blocked);
|
||||
VTINIT(Killed);
|
||||
VTINIT(Respawn);
|
||||
VTINIT(Restart);
|
||||
VTINIT(AddPoints);
|
||||
VTINIT(AddPointsToTeam);
|
||||
#undef VTINIT
|
||||
static NATIVEFUNC RegisterNatives[HAM_END_DONT_USE_ME];
|
||||
static NATIVEFUNC RegisterIDNatives[HAM_END_DONT_USE_ME];
|
||||
static const char *RegisterNames[HAM_END_DONT_USE_ME];
|
||||
|
||||
static cell Register(AMX *amx, cell *params);
|
||||
static cell RegisterID(AMX *amx, cell *params);
|
||||
|
||||
/* returns the original function */
|
||||
void *InsertIntoVTable(void **vtable, int index, void *trampoline);
|
||||
void Cleanup(void);
|
||||
};
|
||||
|
||||
void RegisterThisRegister(int index,NATIVEFUNC byname, NATIVEFUNC byid);
|
||||
void RegisterThisRegisterName(int index, const char *name);
|
||||
void RegisterRegisterNatives(void);
|
||||
|
||||
extern VTableManager VTMan;
|
||||
|
||||
//#include "VTableEntries.h"
|
||||
|
||||
#endif // VTABLEMANAGER_H
|
||||
|
@ -80,6 +80,46 @@ inline RetType VCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, P
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
return function(pThis,pa,pb,pc,pd);
|
||||
};
|
||||
template <class PTypeA, class PTypeB, class PTypeC>
|
||||
inline void VoidVCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef void (*fptr)(void*,PTypeA,PTypeB,PTypeC);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
function(pThis,pa,pb,pc);
|
||||
};
|
||||
template <class RetType, class PTypeA, class PTypeB, class PTypeC>
|
||||
inline RetType VCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef RetType (*fptr)(void*,PTypeA,PTypeB,PTypeC);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
return function(pThis,pa,pb,pc);
|
||||
};
|
||||
template <class PTypeA, class PTypeB>
|
||||
inline void VoidVCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef void (*fptr)(void*,PTypeA,PTypeB);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
function(pThis,pa,pb);
|
||||
};
|
||||
template <class RetType, class PTypeA, class PTypeB>
|
||||
inline RetType VCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef RetType (*fptr)(void*,PTypeA,PTypeB);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
return function(pThis,pa,pb);
|
||||
};
|
||||
template <class PTypeA>
|
||||
inline void VoidVCall1(void *pThis, int ventry, int size, PTypeA pa)
|
||||
{
|
||||
@ -100,6 +140,26 @@ inline RetType VCall1(void *pThis, int ventry, int size, PTypeA pa)
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
return function(pThis,pa);
|
||||
};
|
||||
inline void VoidVCall0(void *pThis, int ventry, int size)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef void (*fptr)(void*);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
function(pThis);
|
||||
};
|
||||
template <class RetType>
|
||||
inline RetType VCall0(void *pThis, int ventry, int size)
|
||||
{
|
||||
char *pcThis=*(char **)&pThis;
|
||||
pcThis+=size;
|
||||
int **vtbl=*(int ***)pcThis;
|
||||
typedef RetType (*fptr)(void*);
|
||||
fptr function=reinterpret_cast<fptr>(vtbl[ventry]);
|
||||
return function(pThis);
|
||||
};
|
||||
|
||||
|
||||
#endif //VFUNC_GCC295_H
|
||||
#endif // __linux__
|
||||
|
@ -93,6 +93,78 @@ inline RetType VCall4(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, P
|
||||
|
||||
return _ret;
|
||||
};
|
||||
template <class PTypeA, class PTypeB, class PTypeC>
|
||||
inline void VoidVCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
void *func=vtbl[ventry];
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
push pc;
|
||||
push pb;
|
||||
push pa;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
};
|
||||
template <class RetType, class PTypeA, class PTypeB, class PTypeC>
|
||||
inline RetType VCall3(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb, PTypeC pc)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
void *func=vtbl[ventry];
|
||||
RetType _ret;
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
push pc;
|
||||
push pb;
|
||||
push pa;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
mov _ret, eax;
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
return _ret;
|
||||
};
|
||||
template <class PTypeA, class PTypeB>
|
||||
inline void VoidVCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
void *func=vtbl[ventry];
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
push pb;
|
||||
push pa;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
};
|
||||
template <class RetType, class PTypeA, class PTypeB>
|
||||
inline RetType VCall2(void *pThis, int ventry, int size, PTypeA pa, PTypeB pb)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
void *func=vtbl[ventry];
|
||||
RetType _ret;
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
push pb;
|
||||
push pa;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
mov _ret, eax;
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
return _ret;
|
||||
};
|
||||
template <class PTypeA>
|
||||
inline void VoidVCall1(void *pThis, int ventry, int size, PTypeA pa)
|
||||
{
|
||||
@ -132,6 +204,42 @@ inline RetType VCall1(void *pThis, int ventry, int size, PTypeA pa)
|
||||
return _ret;
|
||||
};
|
||||
|
||||
inline void VoidVCall0(void *pThis, int ventry, int size)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
|
||||
void *func=vtbl[ventry];
|
||||
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
};
|
||||
template <class RetType>
|
||||
inline RetType VCall0(void *pThis, int ventry, int size)
|
||||
{
|
||||
void **vtbl=*(void ***)pThis;
|
||||
|
||||
void *func=vtbl[ventry];
|
||||
|
||||
RetType _ret;
|
||||
_asm {
|
||||
push ecx;
|
||||
push eax;
|
||||
mov ecx, pThis;
|
||||
call [func];
|
||||
mov _ret, eax;
|
||||
pop eax;
|
||||
pop ecx;
|
||||
};
|
||||
|
||||
return _ret;
|
||||
};
|
||||
|
||||
|
||||
#endif //VFUNC_MSVC_H
|
||||
#endif // _WIN32
|
||||
|
Loading…
Reference in New Issue
Block a user