Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Attributable entities contain one of these, which handles game specific handling:
  4. // - Save / Restore
  5. // - Networking
  6. // - Attribute providers
  7. // - Application of attribute effects
  8. //
  9. //=============================================================================
  10. #ifndef ATTRIBUTE_MANAGER_H
  11. #define ATTRIBUTE_MANAGER_H
  12. #ifdef _WIN32
  13. #pragma once
  14. #endif
  15. #include "econ_item_view.h"
  16. #include "ihasattributes.h"
  17. #include "tf_gcmessages.h"
  18. // Provider types
  19. enum attributeprovidertypes_t
  20. {
  21. PROVIDER_GENERIC,
  22. PROVIDER_WEAPON,
  23. };
  24. float CollateAttributeValues( const CEconItemAttributeDefinition *pAttrDef1, const float flAttribValue1, const CEconItemAttributeDefinition *pAttrDef2, const float flAttribValue2 );
  25. // Retrieve the IHasAttributes pointer from a Base Entity. This function checks for NULL entities
  26. // and asserts the return value is == to dynamic_cast< IHasAttributes * >( pEntity ).
  27. inline IHasAttributes *GetAttribInterface( CBaseEntity *pEntity )
  28. {
  29. IHasAttributes *pAttribInterface = pEntity ? pEntity->GetHasAttributesInterfacePtr() : NULL;
  30. // If this assert hits it most likely means that m_pAttribInterface has not been set
  31. // in the leaf class constructor for this object. See CTFPlayer::CTFPlayer() for an
  32. // example.
  33. Assert( pAttribInterface == dynamic_cast< IHasAttributes *>( pEntity ) );
  34. return pAttribInterface;
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Macros for hooking the application of attributes
  38. #define CALL_ATTRIB_HOOK( vartype, retval, hookName, who, itemlist ) \
  39. retval = CAttributeManager::AttribHookValue<vartype>( retval, #hookName, static_cast<const CBaseEntity*>( who ), itemlist, true );
  40. #define CALL_ATTRIB_HOOK_INT( retval, hookName ) CALL_ATTRIB_HOOK( int, retval, hookName, this, NULL )
  41. #define CALL_ATTRIB_HOOK_FLOAT( retval, hookName ) CALL_ATTRIB_HOOK( float, retval, hookName, this, NULL )
  42. #define CALL_ATTRIB_HOOK_STRING( retval, hookName ) CALL_ATTRIB_HOOK( CAttribute_String, retval, hookName, this, NULL )
  43. #define CALL_ATTRIB_HOOK_INT_ON_OTHER( other, retval, hookName ) CALL_ATTRIB_HOOK( int, retval, hookName, other, NULL )
  44. #define CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( other, retval, hookName ) CALL_ATTRIB_HOOK( float, retval, hookName, other, NULL )
  45. #define CALL_ATTRIB_HOOK_STRING_ON_OTHER( other, retval, hookName ) CALL_ATTRIB_HOOK( CAttribute_String, retval, hookName, other, NULL )
  46. #define CALL_ATTRIB_HOOK_INT_ON_OTHER_WITH_ITEMS( other, retval, items_array, hookName ) CALL_ATTRIB_HOOK( int, retval, hookName, other, items_array )
  47. #define CALL_ATTRIB_HOOK_FLOAT_ON_OTHER_WITH_ITEMS( other, retval, items_array, hookName ) CALL_ATTRIB_HOOK( float, retval, hookName, other, items_array )
  48. #define CALL_ATTRIB_HOOK_STRING_ON_OTHER_WITH_ITEMS( other, retval, items_array, hookName ) CALL_ATTRIB_HOOK( CAttribute_String, retval, hookName, other, items_array )
  49. template< class T > T AttributeConvertFromFloat( float flValue );
  50. template<> float AttributeConvertFromFloat<float>( float flValue );
  51. template<> int AttributeConvertFromFloat<int>( float flValue );
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Base Attribute manager.
  54. // This class knows how to apply attribute effects that have been
  55. // provided to its owner by other entities, but doesn't contain attributes itself.
  56. //-----------------------------------------------------------------------------
  57. class CAttributeManager
  58. {
  59. DECLARE_CLASS_NOBASE( CAttributeManager );
  60. public:
  61. DECLARE_DATADESC();
  62. DECLARE_EMBEDDED_NETWORKVAR();
  63. CAttributeManager();
  64. virtual ~CAttributeManager() {}
  65. // Call this inside your entity's Spawn()
  66. virtual void InitializeAttributes( CBaseEntity *pEntity );
  67. CBaseEntity *GetOuter( void ) const { return m_hOuter.Get(); }
  68. //--------------------------------------------------------
  69. // Attribute providers.
  70. // Other entities that are providing attributes to this entity (i.e. weapons being carried by a player)
  71. void ProvideTo( CBaseEntity *pProvider );
  72. void StopProvidingTo( CBaseEntity *pProvider );
  73. protected:
  74. // Not to be called directly. Use ProvideTo() or StopProvidingTo() above.
  75. void AddProvider( CBaseEntity *pProvider );
  76. void RemoveProvider( CBaseEntity *pProvider );
  77. public:
  78. // Return true if this entity is providing attributes to the specified entity
  79. bool IsProvidingTo( CBaseEntity *pEntity ) const;
  80. // Return true if this entity is being provided attributes by the specified entity
  81. bool IsBeingProvidedToBy( CBaseEntity *pEntity ) const;
  82. // Provider types are used to prevent specified providers supplying to certain initiators
  83. void SetProviderType( attributeprovidertypes_t tType ) { m_ProviderType = tType; }
  84. attributeprovidertypes_t GetProviderType( void ) const { return m_ProviderType; }
  85. //--------------------------------------------------------
  86. // Attribute hook. Use the CALL_ATTRIB_HOOK macros above.
  87. template <class T> static T AttribHookValue( T TValue, const char *pszAttribHook, const CBaseEntity *pEntity, CUtlVector<CBaseEntity*> *pItemList = NULL, bool bIsGlobalConstString = false )
  88. {
  89. VPROF_BUDGET( "CAttributeManager::AttribHookValue", VPROF_BUDGETGROUP_ATTRIBUTES );
  90. // Do we have a hook?
  91. if ( pszAttribHook == NULL || pszAttribHook[0] == '\0' )
  92. return TValue;
  93. // Verify that we have an entity, at least as "this"
  94. if ( pEntity == NULL )
  95. return TValue;
  96. IHasAttributes *pAttribInterface = GetAttribInterface( (CBaseEntity*) pEntity );
  97. AssertMsg( pAttribInterface, "If you hit this, you've probably got a hook incorrectly setup, because the entity it's hooking on doesn't know about attributes." );
  98. if ( pAttribInterface == NULL )
  99. return TValue;
  100. // Hook base attribute.
  101. T Scratch;
  102. AttribHookValueInternal( Scratch, TValue, pszAttribHook, pEntity, pAttribInterface, pItemList, bIsGlobalConstString );
  103. return Scratch;
  104. }
  105. private:
  106. template <class T> static void TypedAttribHookValueInternal( T& out, T TValue, string_t iszAttribHook, const CBaseEntity *pEntity, IHasAttributes *pAttribInterface, CUtlVector<CBaseEntity*> *pItemList )
  107. {
  108. float flValue = pAttribInterface->GetAttributeManager()->ApplyAttributeFloatWrapper( static_cast<float>( TValue ), const_cast<CBaseEntity *>( pEntity ), iszAttribHook, pItemList );
  109. out = AttributeConvertFromFloat<T>( flValue );
  110. }
  111. static void TypedAttribHookValueInternal( CAttribute_String& out, const CAttribute_String& TValue, string_t iszAttribHook, const CBaseEntity *pEntity, IHasAttributes *pAttribInterface, CUtlVector<CBaseEntity*> *pItemList )
  112. {
  113. string_t iszIn = AllocPooledString( TValue.value().c_str() );
  114. string_t iszOut = pAttribInterface->GetAttributeManager()->ApplyAttributeStringWrapper( iszIn, const_cast<CBaseEntity *>( pEntity ), iszAttribHook, pItemList );
  115. const char* pszOut = STRING( iszOut );
  116. // STRING() returns different value for server and client
  117. // server will return "" for NULL_STRING
  118. // client will return NULL for NULL_STRING
  119. if ( pszOut )
  120. {
  121. out.set_value( pszOut );
  122. }
  123. else
  124. {
  125. out.set_value( "" );
  126. }
  127. }
  128. template <class T> static void AttribHookValueInternal( T& out, T TValue, const char *pszAttribHook, const CBaseEntity *pEntity, IHasAttributes *pAttribInterface, CUtlVector<CBaseEntity*> *pItemList, bool bIsGlobalConstString )
  129. {
  130. Assert( pszAttribHook );
  131. Assert( pszAttribHook[0] );
  132. Assert( pEntity );
  133. Assert( pAttribInterface );
  134. Assert( GetAttribInterface( (CBaseEntity*) pEntity ) == pAttribInterface );
  135. Assert( pAttribInterface->GetAttributeManager() );
  136. string_t iszAttribHook = bIsGlobalConstString ? AllocPooledString_StaticConstantStringPointer( pszAttribHook ) : AllocPooledString( pszAttribHook );
  137. return TypedAttribHookValueInternal( out, TValue, iszAttribHook, pEntity, pAttribInterface, pItemList );
  138. }
  139. int m_nCurrentTick;
  140. int m_nCalls;
  141. public:
  142. virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL );
  143. virtual string_t ApplyAttributeString( string_t iszValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL );
  144. //--------------------------------------------------------
  145. // Networking
  146. #ifdef CLIENT_DLL
  147. virtual void OnPreDataChanged( DataUpdateType_t updateType );
  148. virtual void OnDataChanged( DataUpdateType_t updateType );
  149. #endif
  150. //--------------------------------------------------------
  151. // memory handling
  152. void *operator new( size_t stAllocateBlock );
  153. void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
  154. protected:
  155. CUtlVector<EHANDLE> m_Providers; // entities that we receive attribute data *from*
  156. CUtlVector<EHANDLE> m_Receivers; // entities that we provide attribute data *to*
  157. CNetworkVarForDerived( int, m_iReapplyProvisionParity );
  158. CNetworkVarForDerived( EHANDLE, m_hOuter );
  159. bool m_bPreventLoopback;
  160. CNetworkVarForDerived( attributeprovidertypes_t, m_ProviderType );
  161. int m_iCacheVersion; // maps to gamerules counter for global cache flushing
  162. public:
  163. virtual void OnAttributeValuesChanged()
  164. {
  165. ClearCache();
  166. }
  167. private:
  168. void ClearCache();
  169. int GetGlobalCacheVersion() const;
  170. virtual float ApplyAttributeFloatWrapper( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList = NULL );
  171. virtual string_t ApplyAttributeStringWrapper( string_t iszValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList = NULL );
  172. // Cached attribute results
  173. // We cache off requests for data, and wipe the cache whenever our providers change.
  174. union cached_attribute_types
  175. {
  176. float fl;
  177. string_t isz;
  178. };
  179. struct cached_attribute_t
  180. {
  181. string_t iAttribHook;
  182. cached_attribute_types in;
  183. cached_attribute_types out;
  184. };
  185. CUtlVector<cached_attribute_t> m_CachedResults;
  186. #ifdef CLIENT_DLL
  187. public:
  188. // Data received from the server
  189. int m_iOldReapplyProvisionParity;
  190. #endif
  191. };
  192. //-----------------------------------------------------------------------------
  193. // Purpose: This is an attribute manager that also knows how to contain attributes.
  194. //-----------------------------------------------------------------------------
  195. class CAttributeContainer : public CAttributeManager
  196. {
  197. public:
  198. DECLARE_DATADESC();
  199. DECLARE_CLASS( CAttributeContainer, CAttributeManager );
  200. DECLARE_EMBEDDED_NETWORKVAR();
  201. virtual void InitializeAttributes( CBaseEntity *pEntity );
  202. //--------------------------------------------------------
  203. // Attribute hook. Use the CALL_ATTRIB_HOOK macros above.
  204. virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
  205. virtual string_t ApplyAttributeString( string_t iszValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
  206. CEconItemView *GetItem( void ) { return &m_Item; }
  207. const CEconItemView *GetItem( void ) const { return &m_Item; }
  208. void SetItem( const CEconItemView *pItem ) { m_Item.CopyFrom( *pItem ); }
  209. virtual void OnAttributeValuesChanged()
  210. {
  211. BaseClass::OnAttributeValuesChanged();
  212. m_Item.OnAttributeValuesChanged();
  213. }
  214. private:
  215. CNetworkVarEmbedded( CEconItemView, m_Item );
  216. };
  217. //-----------------------------------------------------------------------------
  218. // Purpose: An attribute manager that uses a player's shared attributes.
  219. //-----------------------------------------------------------------------------
  220. #ifndef DOTA_DLL
  221. class CAttributeContainerPlayer : public CAttributeManager
  222. {
  223. public:
  224. DECLARE_DATADESC();
  225. DECLARE_CLASS( CAttributeContainerPlayer, CAttributeManager );
  226. DECLARE_EMBEDDED_NETWORKVAR();
  227. virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
  228. virtual string_t ApplyAttributeString( string_t iszValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
  229. CBasePlayer* GetPlayer( void ) { return m_hPlayer; }
  230. void SetPlayer( CBasePlayer *pPlayer ) { m_hPlayer = pPlayer; }
  231. virtual void OnAttributeValuesChanged()
  232. {
  233. BaseClass::OnAttributeValuesChanged();
  234. m_hPlayer->NetworkStateChanged();
  235. }
  236. private:
  237. CNetworkHandle( CBasePlayer, m_hPlayer );
  238. };
  239. #endif
  240. #ifdef CLIENT_DLL
  241. EXTERN_RECV_TABLE( DT_AttributeManager );
  242. EXTERN_RECV_TABLE( DT_AttributeContainer );
  243. #else
  244. EXTERN_SEND_TABLE( DT_AttributeManager );
  245. EXTERN_SEND_TABLE( DT_AttributeContainer );
  246. #endif
  247. #endif // ATTRIBUTE_MANAGER_H