Hamsandwish hooks the virtual functions(vfuncs) of a class, to explain clearly, I'll give an example.
Here is the Class Hierachy:
Code:
CBaseEntity
CBaseDelay
CBaseToggle
CBaseItem
CBaseMonster
CBaseCycler
CBasePlayer
CBaseGroup
You can see that CBaseEntity is the base class of all other entity classes.
Here is part of vfuncs from CBasePlayer class
Code:
0 CBasePlayer::Spawn(void)
1 CBasePlayer::Precache(void)
2 CBaseEntity::Restart(void)
3 CBaseMonster::KeyValue(KeyValueData_s *)
4 CBasePlayer::Save(CSave &)
5 CBasePlayer::Restore(CRestore &)
6 CBasePlayer::ObjectCaps(void)
7 CBaseEntity::Activate(void)
8 CBaseEntity::SetObjectCollisionBox(void)
9 CBasePlayer::Classify(void)
10 CBaseEntity::DeathNotice(entvars_s *)
11 CBasePlayer::TraceAttack(entvars_s *,float,Vector,TraceResult *,int)
12 CBasePlayer::TakeDamage(entvars_s *,entvars_s *,float,int)
You can see that some functions from CBasePlayer override the original function from CBaseEntity
Code:
RegisterHam(Ham_TakeDamage, "player", "my_hook_func", 0 or 1) //pre or post
To hook the function CBasePlayer::TakeDamage, ham first spawn an entity with given classname, because different classes have different TakeDamage function, so we should specify which class we want to hook.
Virtual table(vtbl) stores in each object of a class, it stores the virtual function's address(pointer). When an obj call its virtual function, it will look up the vtbl to find its real address in memory.
Code:
CBasePlayer *pPlayer;
pPlayer->Spawn();
Numver 0 - 12 above is the index of these vfuncs in vtbl. You can find these numbers in hamdata.ini from configs folder
Ham does the followings to hook CBasePlayer::TakeDamage function:
(1)spawn a "player" entity
(2)get its vtbl address
(3)get its vtbl index from hamdata(actually this have been done when ham init)
(4)get the vfunc address
(5)generate a trampoline function
(6)changed the original vfunc address in vtbl to the trampoline function address(hooking started)
about the trampoline function, it looks like this:
Code:
Tramp()
{
//prehook
return_value = my_hook_func(original parameters)
if(return_value == HAM_SUPERSEDE)
return
//call the original function
this->TakeDamage(modified parameters from our prehook function)
//posthook
my_hook_func()
}
I'm not good at explaining things because of my poor English, so I didn't explain the c++ part, such as class, hierachy, virtual function..., you can find these in any c++ book.
===================
if you want to use ARRAYSIZE, use the hlsdk version
__________________