Raised This Month: $32 Target: $400
 8% 

g_pGameRules question


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Keeper
Senior Member
Join Date: Nov 2006
Old 06-24-2009 , 22:41   g_pGameRules question
Reply With Quote #1

Ok, I've found the game rules via scanning (HL2MP). What am I supposed to do next? I need to hook some functions, and have tried and gotten an error reading that address. Maybe I've scanned for the wrong address, but I want to make sure that I'm thinking right so I can know when I get the right one.

Let's say I want to hook CGameRules:: DeathNotice

Assuming I scan for the g_pGameRules correctly, I use the following to hook that function:
Code:
SH_ADD_HOOK_MEMFUNC ( CGameRules, DeathNotice, g_pMyGameRules, &gPlugin, &CPlugin::MyDeathNotice, PRE );
Is my thinking right?

And no, I'm not using SDK tools...
Keeper is offline
Nite
Junior Member
Join Date: Dec 2007
Old 06-25-2009 , 03:39   Re: g_pGameRules question
Reply With Quote #2

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).

Code:
58    CTFGameRules::FlPlayerFallDamage(CBasePlayer *)
So I first declare it like other hooks:

Code:
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.

Code:
//to hook
void CGamerulesHooks::SetupHooks()
{
   SH_ADD_MANUALHOOK_MEMFUNC(GR_FlPlayerFallDamage, g_pGameRules, this, &CGamerulesHooks::Hook_FlPlayerFallDamage, false);
}
 
//to unhook
void CGamerulesHooks::RemoveHooks()
{
   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.
Nite is offline
Keeper
Senior Member
Join Date: Nov 2006
Old 06-25-2009 , 13:16   Re: g_pGameRules question
Reply With Quote #3

Ok, that makes complete sense to me now. Dumping the vtable for the game rules. And I've gone through the binaries over and over again, and I'm 99.9% certain I have the correct address for the gamerules. When I try to access them in any way I get
Quote:
Unhandled exception at 0x0e11c4f1 (keeper_plugins.dll) in srcds.exe: 0xC0000005: Access violation reading location 0x6e29940d.
So I must still be doing something wrong. Did you define your g_pGameRules as CTFGameRules *?
Keeper is offline
Nite
Junior Member
Join Date: Dec 2007
Old 06-25-2009 , 15:01   Re: g_pGameRules question
Reply With Quote #4

Quote:
Originally Posted by Keeper View Post
So I must still be doing something wrong. Did you define your g_pGameRules as CTFGameRules *?
Nope. I just declare it how it is in SDK just at top of my main plugin cpp file and extern it in header file. Like so:

Code:
CGameRules *g_pGameRules = NULL;
This is what I do for signature scan, I used SourceMod's SDKTools extension (vglobals.cpp file) as an example (Linux part is not tested since my plugin is Windows only build):

Code:
CGameRules *CSignatures::GetGameRules()
{
    static CGameRules *rules = NULL;
#ifdef WIN32
    if (!m_pCreateGameRulesObject)
    {
        LogSigError("CreateGameRulesObject");
        return NULL;
    }
    char *addr = (char*)m_pCreateGameRulesObject;
    rules = **reinterpret_cast<CGameRules***>(addr + 2);
#else
    void *pHandle, *pAddr, *pBase;
    Dl_info info;
    pBase = (void*)g_SMAPI->GetServerFactory(false);
    if (dladdr(pBase, &info) !=0)
    {
        pHandle = dlopen(info.dli_fname, RTLD_NOW);
        if (pHandle)
        {
            pAddr = dlsym(pHandle, "g_pGameRules");
            dlclose(pHandle);
            rules = *(CGameRules**)pAddr;
        }
    }
#endif
    return rules;
}
Nite is offline
Keeper
Senior Member
Join Date: Nov 2006
Old 06-25-2009 , 23:27   Re: g_pGameRules question
Reply With Quote #5

Ok, I already hook another variable, so I know the code works. It definitely doesn't crash on Linux. I guess my 99.9% was just that ... not a sure thing. I'll look for the sig again tomorrow and see if I can't make some progress in the windows world.

EDIT: While my linux side doesn't crash, none of the hooks are being called either. I'm going back to square one to try and figure this out.

Last edited by Keeper; 06-26-2009 at 09:00.
Keeper is offline
voogru
Inspector Javert
Join Date: Oct 2004
Old 06-27-2009 , 03:38   Re: g_pGameRules question
Reply With Quote #6

You don't need a signature to obtain the gamerules fyi.


Find the "tf_gamerules" entity, when it spawns:

Code:
ServerClass *pServerClass = SH_MCALL(BaseEntity(), GetServerClass)();
	void		*pTFGameRules = NULL;

	if(pServerClass)
	{
		int i, iCount;
		iCount = pServerClass->m_pTable->GetNumProps();
		for(i = 0;i < iCount ;i++) 
		{
			if(FStrEq(pServerClass->m_pTable->GetProp(i)->GetName(), "tf_gamerules_data")) 
			{
				pTFGameRules = (*pServerClass->m_pTable->GetProp(i)->GetDataTableProxyFn())(NULL, NULL, NULL, NULL, 0);
				break;
			}
		}		
	}
Wham, bam, gamerules pointer.
voogru is offline
Keeper
Senior Member
Join Date: Nov 2006
Old 06-27-2009 , 09:05   Re: g_pGameRules question
Reply With Quote #7

ooooooooh, saixy. I'll give that a shot. Thanks!
Keeper is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 23:41.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode