Here is my solution:
PHP Code:
#define EXTRACT_VOID_FUNCTIONPTR(x) (*(void **)(&(x)))
void *UTIL_FunctionFromName( datamap_t *pMap, const char *pName )
{
while ( pMap )
{
for ( int i = 0; i < pMap->dataNumFields; i++ )
{
Assert( sizeof(pMap->dataDesc[i].inputFunc) == sizeof(void *) );
if ( pMap->dataDesc[i].flags & FTYPEDESC_FUNCTIONTABLE )
{
if ( FStrEq( pName, pMap->dataDesc[i].fieldName ) )
{
return EXTRACT_VOID_FUNCTIONPTR(pMap->dataDesc[i].inputFunc);
}
}
}
pMap = pMap->baseMap;
}
Msg( "Failed to find function %s\n", pName );
return NULL;
}
typedef void (CBaseEntity::*VALVE_BASEPTR)(void);
typedef void (CBaseEntity::*VALVE_ENTITYFUNCPTR)(CBaseEntity *pOther);
VALVE_BASEPTR CBaseGrenade::func_Detonate = nullptr;
VALVE_ENTITYFUNCPTR CBaseGrenade::func_ExplodeTouch = nullptr;
void CBaseGrenade::detonate()
{
if(func_Detonate != nullptr)
return;
void *ptr = UTIL_FunctionFromName( GetDataDescMap_Real(), "CBaseGrenadeDetonate");
if(!ptr)
return;
memcpy(&func_Detonate, &ptr, sizeof(void *));
(getBaseEntity()->*func_Detonate)(); //getBaseEntity() returns CBaseEntity*
}
For GetDataDescMap_Real use standard offset from core.games "GetDataDescMap"
It seams to be the only way to detonate grenades without delays and dealing with signatures.