This is how I hook gamerules (in TF2). I basically hook by virtual table index. One of functions I hook in TF2 from CTFGameRules class is FlPlayerFallDamage (returns a float or amount of fall damage taken).
58 CTFGameRules::FlPlayerFallDamage(CBasePlayer *)
So I first declare it like other hooks:
SH_DECL_MANUALHOOK1(GR_FlPlayerFallDamage, 58, 0, 0, float, CBasePlayer*);
Then I hook it in other function that is part of a class (CGamerulesHooks) to deal with hooking gamerules functions.
SH_ADD_MANUALHOOK_MEMFUNC(GR_FlPlayerFallDamage, g_pGameRules, this, &CGamerulesHooks::Hook_FlPlayerFallDamage, false);
SH_REMOVE_MANUALHOOK_MEMFUNC(GR_FlPlayerFallDamage, g_pGameRules, this, &CGamerulesHooks::Hook_FlPlayerFallDamage, false);
I unhook gamerules functions at LevelShutdown. Then on ServerActivate I re-obtain gamerules pointer and rehook the gamerules functions (not sure if that is needed but I've been doing this for a while to be on safe side). One thing I noticed is I have to delay the signature scan for it for about 0.10 seconds after ServerActivate, otherwise the pointer is NULL for some reason.
Hope that helps.