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

[TF2/ANY?] Disable items static attributes without removing them


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Benoist3012
Veteran Member
Join Date: Mar 2014
Location: CWave::ForceFinish()
Old 01-31-2022 , 07:40   [TF2/ANY?] Disable items static attributes without removing them
Reply With Quote #1

Introduction

Have you ever wanted to strip attributes on a weapon, without screwing over the client's min view models, or any other cosmetic effects (like weapon skins) ?
Then this snippet is for you! With the addition of DHooks into sourcemod I can now share my method.

The code

PHP Code:
DynamicHook g_hDHookItemIterateAttribute;
int g_iCEconItem_m_Item;
int g_iCEconItemView_m_bOnlyIterateItemViewAttributes;

static 
void SDK_Init()
{
    
Handle hConfig = new GameData("yourgamedata");

    
int iOffset GameConfGetOffset(hConfig"CEconItemView::IterateAttributes");
    
g_hDHookItemIterateAttribute = new DynamicHook(iOffsetHookType_RawReturnType_VoidThisPointer_Address);
    if (
g_hDHookItemIterateAttribute == null)
    {
        
SetFailState("Failed to create hook CEconItemView::IterateAttributes offset from SF2 gamedata!");
    }
    
g_hDHookItemIterateAttribute.AddParam(HookParamType_ObjectPtr);

    
g_iCEconItem_m_Item FindSendPropInfo("CEconEntity""m_Item");
    
FindSendPropInfo("CEconEntity""m_bOnlyIterateItemViewAttributes"__g_iCEconItemView_m_bOnlyIterateItemViewAttributes);
    
    
delete hConfig;
}

public 
void OnEntityCreate(int iEntity, const char[] sClassname)
// OR (As long you have a method to detect the weapon/hat/medal/etc... entity)
public void TF2Items_OnGiveNamedItem_Post(int iClientchar[] sClassnameint iItemDefIndexint iLevelint iQualityint iEntity)
{
    if (
your special weapon detection method here)
    {
        
Address pCEconItemView GetEntityAddress(iEntity) + view_as<Address>(g_iCEconItem_m_Item);
        
g_hDHookItemIterateAttribute.HookRaw(Hook_PrepCEconItemViewCEconItemView_IterateAttributes);
        
g_hDHookItemIterateAttribute.HookRaw(Hook_PostpCEconItemViewCEconItemView_IterateAttributes_Post);
    }
}

static 
MRESReturn CEconItemView_IterateAttributes(Address pThisDHookParam hParams)
{
    
StoreToAddress(pThis view_as<Address>(g_iCEconItemView_m_bOnlyIterateItemViewAttributes), trueNumberType_Int8false);
    return 
MRES_Ignored;
}

static 
MRESReturn CEconItemView_IterateAttributes_Post(Address pThisDHookParam hParams)
{
    
StoreToAddress(pThis view_as<Address>(g_iCEconItemView_m_bOnlyIterateItemViewAttributes), falseNumberType_Int8false);
    return 
MRES_Ignored;

In depth explanation

Everytime the server or client needs to parse an item's attributes (both dynamic and static), it goes through the item's CEconItemView (m_Item) and then calls CEconItemView::IterateAttributes.

CEconItemView::IterateAttributes works like so : After parsing the dynamic attributes, it looks for the member property CEconItemView::m_bOnlyIterateItemViewAttribut es.
If it's true, the server won't parse the static attributes, if it is false it will.
CEconItemView::m_bOnlyIterateItemViewAttribut es is also networked, therefore if you force set it to true on the server the client will also not parse static attributes. Which we don't want, as we need static attributes like "min view model offset" to still work on the client side.
This is where DHook comes in...

PHP Code:
g_iCEconItem_m_Item FindSendPropInfo("CEconEntity""m_Item"); 
m_Item absolute offset retrieved so we may create a CEconItemView ptr with it, which is needed by DHook to detour the function CEconItemView::IterateAttributes.
PHP Code:
FindSendPropInfo("CEconEntity""m_bOnlyIterateItemViewAttributes"__g_iCEconItemView_m_bOnlyIterateItemViewAttributes); 
m_bOnlyIterateItemViewAttributes LOCAL offset is retrieved (relative to CEconItemView) so we can update the property value under DHook's callbacks.

The rest should now be very straight forward now.
- When CEconItemView_IterateAttributes fires, we change CEconItemView::m_bOnlyIterateItemViewAttribut es to true so the static attributes aren't parsed on the server.
- When CEconItemView_IterateAttributes_Post fires, we change CEconItemView::m_bOnlyIterateItemViewAttribut es back to false so the static attributes are still parsed on the client (remember, it's a networked property).

And voilą! You now have successfully created an item whose static attributes will be ignored by the server but not the client.

Where to find gamedata ?

Use IDA, or Asherkin's very useful tool vtable.
Look for CEconItemView::IterateAttributes and you're set.

Edit: This snippet is also technically valid on other source games that have items, but you will have to dig a bit to ensure the logic of attributes iteration I described above is valid there as well.
Raw hooks are also not cleaned upon entity deletion, so don't forget to store the return value of DynamicHook.HookRaw and remove the hooks when entity is deleted.
__________________

Last edited by Benoist3012; 03-17-2024 at 19:41. Reason: Small footnote for "any" games
Benoist3012 is offline
404UserNotFound
BANNED
Join Date: Dec 2011
Old 02-03-2022 , 09:26   Re: [TF2/ANY?] Disable items static attributes without removing them
Reply With Quote #2

Very interesting stuff Benoist.
404UserNotFound is offline
CookieCat
New Member
Join Date: Mar 2024
Old 03-18-2024 , 18:16   Re: [TF2/ANY?] Disable items static attributes without removing them
Reply With Quote #3

Just a warning to anyone using this, it does break the following weapons by default:
- Flamethrowers (Flames completely break)
- Base Jumper (Can't deploy parachute)
- Soldier Banners (Can't gain rage)
- Crit-A-Cola (Acts like Bonk)
- Heavy Lunchbox items (all of them behave like the normal Sandvich and don't recharge)
- Thermal Thruster (Does not work at all)
- Gas Passer (Doesn't charge)

I haven't tested any other weapons but there are probably others that break as well. To fix these weapons you just have to set their attributes manually. It's probably a good idea to just set the attributes using TF2Attrib_GetStaticAttribs to fix these issues.

Last edited by CookieCat; 03-18-2024 at 20:55.
CookieCat is offline
Benoist3012
Veteran Member
Join Date: Mar 2014
Location: CWave::ForceFinish()
Old 04-05-2024 , 20:24   Re: [TF2/ANY?] Disable items static attributes without removing them
Reply With Quote #4

Quote:
Originally Posted by CookieCat View Post
Just a warning to anyone using this, it does break the following weapons by default:
- Flamethrowers (Flames completely break)
- Base Jumper (Can't deploy parachute)
- Soldier Banners (Can't gain rage)
- Crit-A-Cola (Acts like Bonk)
- Heavy Lunchbox items (all of them behave like the normal Sandvich and don't recharge)
- Thermal Thruster (Does not work at all)
- Gas Passer (Doesn't charge)
Thank you for confirming the snippet works as intended...

That's the point of stripping static attributes server side only. It disables inherent functionalities of the items, without touching at the attributes the client-side cares about.
__________________
Benoist3012 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 18:01.


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