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

TF2 Attributes in Metamod


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
rcbotCheeseh
Junior Member
Join Date: May 2013
Old 03-24-2015 , 21:21   TF2 Attributes in Metamod
Reply With Quote #1

I'm trying to implement TF2 Attributes in Metamod -- I know you'd probably think why not just do it in SourceMod, well my plugin is huge and I'm not really going to be translating it all into sourcemod any time soon. It's in Metamod now and I've struggled to get this to work on my own.

The main problems I have are:
1) As far as I know the signature function is being called correctly using __asm, however it will still occassionaly crash especially if I call it twice with the same attribute.

I've tried the following. strAttrib = "max health additive bonus" for example, flVal = 100 or 200. It will always be OK the first time. Then the second time it will crash.

2) Secondly I can't seem to call the ClearCache function because my method of getting the vtable might be incorrect?
3) There is no update to the player on the hud althought this might just be caused by the inability to access ClearCache ?

Code:
    if (TF2_SetAttrib(pEdict, strAttrib, flVal))
     CBotGlobals::botMessage(NULL, 0, "OK");
    else
     CBotGlobals::botMessage(NULL, 0, "FAIL");
this is translated from sourcemod into metamod and my own plugin
Code:
// TF2 Attributes - Flamin Sarge
bool TF2_SetAttrib(edict_t *pedict, const char *strAttrib, float flVal)
{
 //CBaseEntity *pEntity;
 if (!pedict || pedict->IsFree())
  return false;
 CAttributeList *pList = CClassInterface::getAttributeList(pedict);
 CEconItemSchema *pSchema = g_pGetEconItemSchema->callme();
 if (pSchema == NULL) 
  return false;
 CEconItemAttributeDefinition *pAttribDef = g_pGetAttributeDefinitionByName->callme(pSchema, strAttrib);
 if ( (unsigned int)pAttribDef < 0x10000)
 {
  return false;
 }
 bool bSuccess = g_pSetRuntimeAttributeValue->callme(pedict, pList, pAttribDef, flVal);
 return bSuccess;
}
this calls the signature function
Code:
bool CSetRuntimeAttributeValue::callme(edict_t *pEnt, CAttributeList *list, CEconItemAttributeDefinition *attrib,float value)
{
 int bret = 0;
 void *thefunc = m_func;
 int iEntityIndex = ENTINDEX(pEnt);
 if ( list && attrib && thefunc )
 {
#ifdef _WIN32
  __asm 
  {
   mov ecx, list;
   push attrib;
   push value;
   call thefunc;
   mov bret, eax;
  };
#else
  FUNC_SET_ATTRIB_VALUE func = (FUNC_SET_ATTRIB_VALUE)thefunc;
  bret = func(list,attrib,value);
#endif
 }
 return (bret==1) || ((bret & 0x1FFF) == ((iEntityIndex + 4) * 4));
}
I get the signature at startup when I create CSetRuntimeAttributeValue instance
set_attribute_value_win and set_attribute_value_linux are just values I use in a config file to find updated signatures

Code:
CSetRuntimeAttributeValue::CSetRuntimeAttributeValue ( CRCBotKeyValueList *list, void *pAddrBase )
{
#ifdef _WIN32
 findFunc(list,"set_attribute_value_win",pAddrBase,"\\x55\\x8B\\xEC\\x83\\xEC\\x14\\x33\\xD2\\x53\\x8B\\xD9\\x56\\x57\\x8B\\x73\\x10\\x85\\xF6");
#else
 findFunc(list,"set_attribute_value_linux",pAddrBase,"@_ZN14CAttributeList24SetRuntimeAttributeValueEPK28CEconItemAttributeDefinitionf");
#endif
}
 
void CSignatureFunction :: findFunc ( CRCBotKeyValueList *kv, const char*pKey, void *pAddrBase, const char *defaultsig )
{
	char *sig = NULL;

	if ( kv->getString(pKey,&sig) && sig )
		m_func = findSignature(pAddrBase,sig);
	else
		m_func = findSignature(pAddrBase,defaultsig);
}
I've tried Clear Cache but the function is always NULL
Code:
 
void (CAttributeManager::*OnAttributeValuesChanged)(void) = 0x0;
/*   
"CAttributeManager::OnAttributeValuesChanged" //use instead of ClearCache/NotifyManagerOfAttributeValueChanges
{
 "windows" "12"
 "linux"  "13"
 "mac"  "13"
}
*/
bool RCBotPluginMeta::TF2_ClearAttributeCache(edict_t *pEdict)
{
 CAttributeList *pList = CClassInterface::getAttributeList(pEdict);
 CAttributeManager *pManager = (CAttributeManager*)(((unsigned long)pList) + 24);
 if (!pManager)
  return false;
 unsigned int *mem = (unsigned int*)*(unsigned int*)pManager; // Get the vtable into mem
 if (!mem)
  return false;
 int offset = 12; // From windows offset for now
 *(unsigned int*)&OnAttributeValuesChanged = mem[offset];
 if (!OnAttributeValuesChanged)
  return false;
// NEVER REACHES HERE!!!
 (*pManager.*OnAttributeValuesChanged)();
 return true;
}
__________________

Last edited by rcbotCheeseh; 03-24-2015 at 21:26.
rcbotCheeseh 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 11:21.


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