diff options
Diffstat (limited to 'game/shared/econ/econ_item_schema.h')
| -rw-r--r-- | game/shared/econ/econ_item_schema.h | 3374 |
1 files changed, 3374 insertions, 0 deletions
diff --git a/game/shared/econ/econ_item_schema.h b/game/shared/econ/econ_item_schema.h new file mode 100644 index 0000000..283526a --- /dev/null +++ b/game/shared/econ/econ_item_schema.h @@ -0,0 +1,3374 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: EconItemSchema: Defines a schema for econ items +// +//============================================================================= + +#ifndef ECONITEMSCHEMA_H +#define ECONITEMSCHEMA_H +#ifdef _WIN32 +#pragma once +#endif + +// Valve code doesn't play nicely with standard headers on some platforms sometimes. +#ifdef min + #undef min +#endif + +#ifdef max + #undef max +#endif + +#include <string> + +#include "KeyValues.h" +#include "tier1/utldict.h" +#include "tier1/utlhashmaplarge.h" +#include "econ_item_constants.h" + +#include "item_selection_criteria.h" +#include "bitvec.h" +#include "language.h" +#include "smartptr.h" +#include "rtime.h" +#include "checksum_sha1.h" + +#if defined(CLIENT_DLL) || defined(GAME_DLL) +#include "engine/ivmodelinfo.h" +#include "engine/ivmodelrender.h" +#include "ilocalize.h" +#endif +#include "gamestringpool.h" + +class CEconItemSchema; +class CEconItem; +class CEconSharedObjectCache; +class CSOItemRecipe; + +union attribute_data_union_t +{ + float asFloat; + uint32 asUint32; + byte *asBlobPointer; +}; + +struct static_attrib_t +{ + static_attrib_t() + { + iDefIndex = 0; + m_value.asBlobPointer = NULL; +#ifdef GC_DLL + bForceGCToGenerate = false; + m_pKVCustomData = NULL; +#endif // GC_DLL + } + + ~static_attrib_t() + { +#ifdef GC_DLL + if ( m_pKVCustomData ) + m_pKVCustomData->deleteThis(); + m_pKVCustomData = NULL; +#endif + } + + static_attrib_t( const static_attrib_t& rhs ) + { + iDefIndex = rhs.iDefIndex; + m_value = rhs.m_value; +#ifdef GC_DLL + m_pKVCustomData = rhs.m_pKVCustomData ? rhs.m_pKVCustomData->MakeCopy() : NULL; + bForceGCToGenerate = rhs.bForceGCToGenerate; +#endif + } + + attrib_definition_index_t iDefIndex; + attribute_data_union_t m_value; +#ifdef GC_DLL + bool bForceGCToGenerate; + KeyValues *m_pKVCustomData; +#endif // GC_DLL + + // Parses a single subsection from a multi-line attribute block that looks like: + // + // "attributes" + // { + // "cannot trade" + // { + // "attribute_class" "cannot_trade" + // "value" "1" + // } + // "kill eater" + // { + // "attribute_class" "kill_eater" + // "force_gc_to_generate" "1" + // "use_custom_logic" "gifts_given_out" + // } + // } + // + // The "force_gc_to_generate" and "use_custom_logic" fields will only be parsed on the GC. Will return + // true/false based on whether the whole attribute and value parsed successfully. + bool BInitFromKV_MultiLine( const char *pszContext, KeyValues *pKVAttribute, CUtlVector<CUtlString> *pVecErrors ); + + // Parses a single subsection from a single-line attribute block that looks like: + // + // CharacterAttributes + // { + // "increase buff duration" 9.0 + // "damage bonus" 2.0 + // } + // + // It's impossible to specify GC-generated attributes in this format. Will return true/false based on + // whether the whole attribute and value parsed successfully. + bool BInitFromKV_SingleLine( const char *pszContext, KeyValues *pKVAttribute, CUtlVector<CUtlString> *pVecErrors, bool bEnableTerribleBackwardsCompatibilitySchemaParsingCode = true ); + + // Data access helpers. + const class CEconItemAttributeDefinition *GetAttributeDefinition() const; + const class ISchemaAttributeType *GetAttributeType() const; +}; + +typedef uint16 equipped_class_t; +typedef uint16 equipped_slot_t; +typedef uint8 equipped_preset_t; + +#define INVALID_EQUIPPED_SLOT ((equipped_slot_t)-1) +#define INVALID_STYLE_INDEX ((style_index_t)-1) +#define INVALID_PRESET_INDEX ((equipped_preset_t)-1) + +enum EEquipType_t +{ + EQUIP_TYPE_CLASS = 0, + EQUIP_TYPE_ACCOUNT, + + EQUIP_TYPE_INVALID, +}; + +// Streamable weapons cause stutters when people enter PVS. Turn it off for now. +// #define WITH_STREAMABLE_WEAPONS + +//----------------------------------------------------------------------------- +// IEconItemPropertyGenerator +//----------------------------------------------------------------------------- +class IEconItemPropertyGenerator +{ +public: + virtual ~IEconItemPropertyGenerator() { } + + MUST_CHECK_RETURN virtual bool BGenerateProperties( CEconItem *pItem ) const = 0; +}; + +//----------------------------------------------------------------------------- +// Item Series +//----------------------------------------------------------------------------- +class CEconItemSeriesDefinition +{ +public: + CEconItemSeriesDefinition( void ); + CEconItemSeriesDefinition( const CEconItemSeriesDefinition &that ); + CEconItemSeriesDefinition &operator=( const CEconItemSeriesDefinition& rhs ); + + ~CEconItemSeriesDefinition( void ) { } + + bool BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); + + int32 GetDBValue( void ) const { return m_nValue; } + const char *GetName( void ) const { return !m_strName.IsEmpty() ? m_strName.String() : "unknown"; } + const char *GetLocKey( void ) const { return !m_strLockKey.IsEmpty() ? m_strLockKey.String() : "unknown"; } + const char *GetUiFile( void ) const { return !m_strUiFile.IsEmpty() ? m_strUiFile.String() : "unknown"; } + +private: + + // The value that the game/DB will know this series by + int32 m_nValue; + + CUtlString m_strName; // Key Name + CUtlString m_strLockKey; // Localization key + CUtlString m_strUiFile; // Ui File (.res file) +}; +//----------------------------------------------------------------------------- +// CEconItemRarityDefinition +//----------------------------------------------------------------------------- +class CEconItemRarityDefinition +{ +public: + CEconItemRarityDefinition( void ); + + ~CEconItemRarityDefinition( void ) { } + + bool BInitFromKV( KeyValues *pKVItem, KeyValues *pKVRarityWeights, CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors = NULL ); + + int32 GetDBValue( void ) const { return m_nValue; } + const char *GetName( void ) const { return !m_strName.IsEmpty() ? m_strName.String() : "unknown"; } + const char *GetLocKey( void ) const { return m_strLocKey.String(); } + const char *GetWepLocKey( void ) const { return m_strWepLocKey.String(); } + const char *GetDropSound( void ) const { return m_strDropSound.String(); } + attrib_colors_t GetAttribColor( void ) const { return m_iAttribColor; } + const char *GetNextRarity( void ) const { return m_strNextRarity.String(); } + int32 GetLootlistWeight( void ) const { return m_nLootlistWeight; } + +private: + + // The value that the game/DB will know this rarity by + int32 m_nValue; + + attrib_colors_t m_iAttribColor; + + // The English name of the rarity + CUtlString m_strName; + + // The localization key for this rarity. + CUtlString m_strLocKey; + // The localization key for this rarity, for weapons. + CUtlString m_strWepLocKey; + + // The loot list name associated with this rarity. + CUtlString m_strDropSound; + + CUtlString m_strNextRarity; + + int32 m_nLootlistWeight; + +}; + +//----------------------------------------------------------------------------- +// CEconItemQualityDefinition +// Template Definition of a randomly created item +//----------------------------------------------------------------------------- +class CEconItemQualityDefinition +{ +public: + CEconItemQualityDefinition( void ); + CEconItemQualityDefinition( const CEconItemQualityDefinition &that ); + CEconItemQualityDefinition &operator=( const CEconItemQualityDefinition& rhs ); + + ~CEconItemQualityDefinition( void ) { } + + bool BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); + + + int32 GetDBValue( void ) const { return m_nValue; } + const char *GetName( void ) const { return !m_strName.IsEmpty() ? m_strName.Get() : "unknown"; } + bool CanSupportSet( void ) const { return m_bCanSupportSet; } + const char *GetHexColor( void ) const { return !m_strHexColor.IsEmpty() ? m_strHexColor.Get() : "B2B2B2"; } + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ) + { + VALIDATE_SCOPE(); + ValidateObj( m_strName ); + } +#endif // DBGFLAG_VALIDATE + +private: + + // The value that the game/DB will know this quality by + int32 m_nValue; + + // The English name of the quality + CUtlConstString m_strName; + + // if this is true the support tool is allowed to set this quality level on any item + bool m_bCanSupportSet; + + // A hex string representing the color this quality should display as. Used primarily for display on the Web. + CUtlConstString m_strHexColor; +}; + +//----------------------------------------------------------------------------- +// CEconColorDefinition +//----------------------------------------------------------------------------- +class CEconColorDefinition +{ +public: + bool BInitFromKV( KeyValues *pKVColor, CUtlVector<CUtlString> *pVecErrors = NULL ); + + const char *GetName( void ) const { return m_strName.Get(); } + const char *GetColorName( void ) const { return m_strColorName.Get(); } // meant for passing into VGUI styles, etc. + const char *GetHexColor( void ) const { return m_strHexColor.Get(); } + +private: + // The English name of this color. Only used for lookup. + CUtlConstString m_strName; + + // The VGUI name of the color in our schema. This will be used to set values + // for VGUI controls. + CUtlConstString m_strColorName; + + // The hex string value of this color. This will be used for Web display. + CUtlConstString m_strHexColor; +}; + +//----------------------------------------------------------------------------- +// CEconItemSetDefinition +// Definition of an item set +//----------------------------------------------------------------------------- +class CEconItemSetDefinition +{ +public: + CEconItemSetDefinition( void ); + CEconItemSetDefinition( const CEconItemSetDefinition &that ); + CEconItemSetDefinition &operator=( const CEconItemSetDefinition& rhs ); + + ~CEconItemSetDefinition( void ) {} + + bool BInitFromKV( KeyValues *pKVItemSet, CUtlVector<CUtlString> *pVecErrors = NULL ); + + void IterateAttributes( class IEconItemAttributeIterator *pIterator ) const; + +public: + + const char *m_pszName; + const char *m_pszLocalizedName; + CUtlVector<item_definition_index_t> m_iItemDefs; + int m_iBundleItemDef; // Item def of the store bundle for this set, if any + bool m_bIsHiddenSet; // If true, this set and any bonuses will only be visible if the whole set is equipped. + + struct itemset_attrib_t + { + attrib_definition_index_t m_iAttribDefIndex; + float m_flValue; + }; + CUtlVector<itemset_attrib_t> m_iAttributes; +}; + +//----------------------------------------------------------------------------- +class CEconItemCollectionDefinition +{ +public: + CEconItemCollectionDefinition( void ); + ~CEconItemCollectionDefinition( void ) {} + + bool BInitFromKV( KeyValues *pKVItemCollection, CUtlVector<CUtlString> *pVecErrors = NULL ); + + uint8 GetMinRarity() const { return m_iRarityMin; } + uint8 GetMaxRarity() const { return m_iRarityMax; } + +public: + + const char *m_pszName; + const char *m_pszLocalizedName; + const char *m_pszLocalizedDesc; + CUtlVector<item_definition_index_t> m_iItemDefs; + +private: + bool m_bIsReferenceCollection; + + uint8 m_iRarityMin; + uint8 m_iRarityMax; +}; + +//----------------------------------------------------------------------------- +class CEconItemPaintKitDefinition +{ +public: + CEconItemPaintKitDefinition( void ); + ~CEconItemPaintKitDefinition( void ); + + bool BInitFromKV( KeyValues *pKVItemPaintKit, CUtlVector<CUtlString> *pVecErrors = NULL ); + + //KeyValues *GetKVP() { return m_pKVItem; } + + const char *GetName() const { return m_pszName; } + const char *GetLocalizeName() const { return m_pszLocalizedName; } + + KeyValues *GetPaintKitWearKV( int nWear ); + +private: + const char *m_pszName; + const char *m_pszLocalizedName; + + CUtlVector< KeyValues * > m_vecPaintKitWearKVP; +}; + +//----------------------------------------------------------------------------- +class CEconOperationDefinition +{ +public: + CEconOperationDefinition( void ); + ~CEconOperationDefinition( void ); + + bool BInitFromKV( KeyValues *pKVOperation, CUtlVector<CUtlString> *pVecErrors = NULL ); + + const char *GetName() const { return m_pszName; } + operation_definition_index_t GetOperationID() const { return m_unOperationID; } + item_definition_index_t GetRequiredItemDefIndex() const { return m_unRequiredItemDefIndex; } + item_definition_index_t GetGatewayItemDefIndex() const { return m_unGatewayItemDefIndex; } + + KeyValues *GetKVP() { return m_pKVItem; } + + // use the date that we stop giving things to players as expiry date + bool IsExpired() const { return CRTime::RTime32TimeCur() > GetStopGivingToPlayerDate(); } + bool IsActive() const { return CRTime::RTime32TimeCur() >= GetStartDate() && !IsExpired(); } + + const char *GetQuestLogOverrideResFile() const { return m_pszQuestLogResFile; } + const char *GetQuestListOverrideResFile() const { return m_pszQuestListResFile; } + + RTime32 GetStartDate() const { return m_OperationStartDate; } + RTime32 GetStopGivingToPlayerDate() const { return m_StopGivingToPlayerDate; } + RTime32 GetStopAddingToQueueDate() const { return m_StopAddingToQueueDate; } + + const char *GetOperationLootlist() const { return m_pszOperationLootList; } + bool IsCampaign() const { return m_bIsCampaign; } + uint32 GetMaxDropCount() const { return m_unMaxDropCount; } + +#ifdef GC_DLL + enum EContractRewardLootlist_t + { + REWARD_CASE, + REWARD_WEAPON, + + NUM_REWARDS + }; + const char *GetContractRewardLootlist( EContractRewardLootlist_t eType ) const { return m_pszContractRewardLootlist[ eType ]; } + + RTime32 GetMinQueueFreq() const; + RTime32 GetMaxQueueFreq() const; + RTime32 GetMinDropFreq() const; + RTime32 GetMaxDropFreq() const; + + uint8 GetNumSeededContracts() const { return m_unSeed; } + uint16 GetNumMaxHeldDrops() const { return m_unMaxHeldDrops; } + + int GetNumMaxQueueCount() const { return m_nMaxQueueCount; } + + uint8 GetMaxDropPerThink() const { return m_unMaxDropPerThink; } + +#endif // GC_DLL + +private: + const char *m_pszName; + operation_definition_index_t m_unOperationID; + + // things operation periodically drops + const char *m_pszOperationLootList; + bool m_bIsCampaign; + uint32 m_unMaxDropCount; + + const char *m_pszQuestLogResFile; + const char *m_pszQuestListResFile; + + item_definition_index_t m_unRequiredItemDefIndex; + item_definition_index_t m_unGatewayItemDefIndex; // Defindex of the item users need to acquire in order to get the required item. Could be the required item itself. + + RTime32 m_OperationStartDate; // when the operation starts and gives out rewards + RTime32 m_StopGivingToPlayerDate; // when the operation stops giving quests to player + RTime32 m_StopAddingToQueueDate; // when the operation stops adding more quests to the bucket + +#ifdef GC_DLL + const char *m_pszContractRewardLootlist[ NUM_REWARDS ]; + + // in seconds + RTime32 m_rtQueueFreqMin; + RTime32 m_rtQueueFreqMax; + RTime32 m_rtDropFreqMin; + RTime32 m_rtDropFreqMax; + + uint8 m_unSeed; + uint16 m_unMaxHeldDrops; + int m_nMaxQueueCount; + + uint8 m_unMaxDropPerThink; + +#endif // GC_DLL + + KeyValues *m_pKVItem; +}; + +//----------------------------------------------------------------------------- +// CEconLootListDefinition +// Definition of a loot list +//----------------------------------------------------------------------------- +class IEconLootList +{ +public: + virtual ~IEconLootList() { } + + MUST_CHECK_RETURN virtual bool BPublicListContents() const = 0; + MUST_CHECK_RETURN virtual const char *GetLootListHeaderLocalizationKey() const = 0; + MUST_CHECK_RETURN virtual const char *GetLootListFooterLocalizationKey() const = 0; + MUST_CHECK_RETURN virtual const char *GetLootListCollectionReference() const = 0; + + class IEconLootListIterator + { + public: + virtual ~IEconLootListIterator() { } + virtual void OnIterate( item_definition_index_t unItemDefIndex ) = 0; + }; + + virtual void EnumerateUserFacingPotentialDrops( IEconLootListIterator *pIt ) const = 0; + +#ifdef GC_DLL + MUST_CHECK_RETURN virtual bool BGenerateSingleRollRandomItems( const CEconGameAccount *pGameAccount, bool bFreeAccount, CUtlVector<CEconItem *> *out_pvecItems, const CUtlVector< item_definition_index_t > *pVecAvoidItemDefs = NULL ) const = 0; +#endif // GC_DLL +}; + +#ifdef GC_DLL +struct lootlist_attrib_t +{ + static_attrib_t m_staticAttrib; + float m_flWeight; + + bool BInitFromKV( const char *pszContext, KeyValues *pKVKey, CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors ); +}; + +struct random_attrib_t +{ + float m_flChanceOfRandomAttribute; + float m_flTotalAttributeWeight; + bool m_bPickAllAttributes; + CUtlVector<lootlist_attrib_t> m_RandomAttributes; + + bool RollRandomAttributes( CUtlVector< static_attrib_t >& vecAttributes, const CEconGameAccount *pGameAccount ) const; +}; +#endif // GC_DLL + +class CEconLootListDefinition : public IEconLootList +{ +public: + struct drop_period_t + { + bool IsValidForTime( const RTime32& time ) const; + + RTime32 m_DropStartDate; + RTime32 m_DropEndDate; + }; + + struct drop_item_t + { + int m_iItemOrLootlistDef; // negative values indicate nested loot lists + float m_flWeight; + drop_period_t m_dropPeriod; + }; + + struct loot_list_additional_drop_t + { + float m_fChance; + bool m_bPremiumOnly; + const char *m_pszLootListDefName; + int m_iRequiredHolidayIndex; + drop_period_t m_dropPeriod; + }; + + virtual ~CEconLootListDefinition(); + + bool BInitFromKV( KeyValues *pKVLootList, CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors ); + + const char *GetName() const { return m_pszName; } + virtual const char *GetLootListHeaderLocalizationKey() const OVERRIDE { return m_pszLootListHeader; } + virtual const char *GetLootListFooterLocalizationKey() const OVERRIDE { return m_pszLootListFooter; } + virtual const char *GetLootListCollectionReference() const OVERRIDE { return m_pszCollectionReference; } + + const CUtlVector<drop_item_t>& GetLootListContents() const { return m_DropList; } +#ifdef GC_DLL + const CUtlVector<loot_list_additional_drop_t>& GetAdditionalDrops() const { return m_AdditionalDrops; } +#endif + virtual void EnumerateUserFacingPotentialDrops( IEconLootListIterator *pIt ) const OVERRIDE; + + virtual bool BPublicListContents() const OVERRIDE + { + return m_bPublicListContents; + } + +#ifdef GC_DLL + +public: + struct rolled_item_defs_t + { + const CEconItemDefinition *m_pItemDef; + CCopyableUtlVector< const CEconLootListDefinition * > m_vecAffectingLootLists; + }; + + bool AddRandomAtrributes( KeyValues *pRandomAttributesKV, CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors = NULL ); + bool AddRandomAttributesFromTemplates( KeyValues *pRandomAttributesKV, CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors = NULL ); + + + // Generates a single roll for this loot list as well as each "additional drop" loot list specified. This will return + // true if all items were created successfully or false if anything went wrong in any of the relevant lootlists. All + // items created will be returned via out_pvecItems. + MUST_CHECK_RETURN virtual bool BGenerateSingleRollRandomItems( const CEconGameAccount *pGameAccount, bool bFreeAccount, CUtlVector<CEconItem *> *out_pvecItems, const CUtlVector< item_definition_index_t > *pVecAvoidItemDefs = NULL ) const OVERRIDE; + + void RollRandomAttributes( CUtlVector< static_attrib_t >& vecAttributes, const CEconGameAccount *pGameAccount ) const; + bool RollRandomItemsAndAdditionalItems( IUniformRandomStream *pRandomStream, bool bFreeAccount, CUtlVector<rolled_item_defs_t> *out_pVecRolledItems, const CUtlVector< item_definition_index_t > *pVecAvoidItemDefs = NULL ) const; + + uint8 GetRarity() const { return m_unRarity; } + void GetRarityLootLists( CUtlVector< const CEconLootListDefinition* > *out_pVecRarityLootList ) const; + void GetItemDefs( CUtlVector< item_definition_index_t > *out_pVecItemDefs ) const; + +private: + bool RollRandomItemDef( IUniformRandomStream *pRandomStream, bool bFreeAccount, CUtlVector<rolled_item_defs_t> *out_pVecRolledItems, const CUtlVector< item_definition_index_t > *pVecAvoidItemDefs = NULL ) const; + bool BIsInternalNoDupesLootList() const { return m_iNoDupesIterations >= 0; } + + MUST_CHECK_RETURN bool BInitPropertyGeneratorsFromKV( KeyValues *pKV, CUtlVector<CUtlString> *pVecErrors ); +#endif + +private: + const char *m_pszName; + const char *m_pszLootListHeader; + const char *m_pszLootListFooter; + const char *m_pszCollectionReference; + CUtlVector<drop_item_t> m_DropList; + + bool m_bPublicListContents; // do not show loot list contents to users (ie., when listing crate contents on Steam) + +#ifdef GC_DLL + + MUST_CHECK_RETURN bool BAttachLootListAttributes( const CEconGameAccount *pGameAccount, CEconItem *pItem ) const; + + int m_iNoDupesIterations; // if less than zero, "no dupes" functionality disabled; if greater than or equal to zero, the number of iterations we want to run through passing no-dupe sets + + CUtlVector<random_attrib_t*> m_RandomAttribs; + CUtlVector<loot_list_additional_drop_t> m_AdditionalDrops; + CUtlVector<const IEconItemPropertyGenerator *> m_PropertyGenerators; + + uint8 m_unRarity; +#endif // GC_DLL +}; + +//----------------------------------------------------------------------------- +// CEconCraftingRecipeDefinition +// Template Definition of an item recipe +//----------------------------------------------------------------------------- +class CEconCraftingRecipeDefinition +{ +public: + CEconCraftingRecipeDefinition( void ); + virtual ~CEconCraftingRecipeDefinition( void ) { } + + bool BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); + +#ifdef GC_DLL + bool BIsCraftableByUnverifiedClients() const { return m_bIsCraftableByUnverifiedClient; } +#endif // GC_DLL + + virtual void CopyPolymorphic( const CEconCraftingRecipeDefinition *pSourceDef ) { *this = *pSourceDef; } + + void SetDefinitionIndex( uint32 iIndex ) { m_nDefIndex = iIndex; } + int32 GetDefinitionIndex( void ) const { return m_nDefIndex; } + const char *GetName( void ) const { return !m_strName.IsEmpty() ? m_strName.String() : "unknown"; } + const char *GetName_A( void ) const { return !m_strN_A.IsEmpty() ? m_strN_A.String() : "unknown"; } + const char *GetDescInputs( void ) const { return !m_strDescInputs.IsEmpty() ? m_strDescInputs.String() : "unknown"; } + const char *GetDescOutputs( void ) const { return !m_strDescOutputs.IsEmpty() ? m_strDescOutputs.String() : "unknown"; } + + const char *GetDescI_A( void ) const { return !m_strDI_A.IsEmpty() ? m_strDI_A.String() : "unknown"; } + const char *GetDescI_B( void ) const { return !m_strDI_B.IsEmpty() ? m_strDI_B.String() : "unknown"; } + const char *GetDescI_C( void ) const { return !m_strDI_C.IsEmpty() ? m_strDI_C.String() : "unknown"; } + const char *GetDescO_A( void ) const { return !m_strDO_A.IsEmpty() ? m_strDO_A.String() : "unknown"; } + const char *GetDescO_B( void ) const { return !m_strDO_B.IsEmpty() ? m_strDO_B.String() : "unknown"; } + const char *GetDescO_C( void ) const { return !m_strDO_C.IsEmpty() ? m_strDO_C.String() : "unknown"; } + + bool IsDisabled( void ) const { return m_bDisabled; } + bool RequiresAllSameClass( void ) { return m_bRequiresAllSameClass; } + bool RequiresAllSameSlot( void ) { return m_bRequiresAllSameSlot; } + bool IsPremiumAccountOnly( void ) const { return m_bPremiumAccountOnly; } + recipecategories_t GetCategory( void ) const { return m_iCategory; } + int GetTotalInputItemsRequired( void ) const; + int GetTotalOutputItems( void ) const { return m_OutputItemsCriteria.Count(); } + + // Returns true if the vector contains a set of items that matches the inputs for this recipe + virtual bool ItemListMatchesInputs( CUtlVector<CEconItem*> *vecCraftingItems, KeyValues *out_pCraftParams = NULL, bool bIgnoreSlop = false, CUtlVector<uint64> *vecChosenItems = NULL ) const; + + const CUtlVector<CItemSelectionCriteria> *GetInputItems( void ) const { return &m_InputItemsCriteria; } + const CUtlVector<uint32> &GetInputItemDupeCounts( void ) const { return m_InputItemDupeCounts; } + const CUtlVector<CItemSelectionCriteria> &GetOutputItems( void ) const { return m_OutputItemsCriteria; } + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ) + { + VALIDATE_SCOPE(); + ValidateObj( m_InputItemsCriteria ); + ValidateObj( m_InputItemDupeCounts ); + ValidateObj( m_OutputItemsCriteria ); + } +#endif // DBGFLAG_VALIDATE + + // Serializes the criteria to and from messages + bool BSerializeToMsg( CSOItemRecipe & msg ) const; + bool BDeserializeFromMsg( const CSOItemRecipe & msg ); + +protected: + // The number used to refer to this definition in the DB + int32 m_nDefIndex; + + // Localization key strings + CUtlString m_strName; + CUtlString m_strN_A; + CUtlString m_strDescInputs; + CUtlString m_strDescOutputs; + CUtlString m_strDI_A; + CUtlString m_strDI_B; + CUtlString m_strDI_C; + CUtlString m_strDO_A; + CUtlString m_strDO_B; + CUtlString m_strDO_C; + + bool m_bDisabled; +#ifdef GC_DLL + bool m_bIsCraftableByUnverifiedClient; +#endif // GC_DLL + bool m_bRequiresAllSameClass; + bool m_bRequiresAllSameSlot; + int m_iCacheClassUsageForOutputFromItem; + int m_iCacheSlotUsageForOutputFromItem; + int m_iCacheSetForOutputFromItem; + bool m_bPremiumAccountOnly; + recipecategories_t m_iCategory; + + // The list of items that a required to make this recipe + CUtlVector<CItemSelectionCriteria> m_InputItemsCriteria; + CUtlVector<uint32> m_InputItemDupeCounts; + + // The list of items that are generated by this recipe + CUtlVector<CItemSelectionCriteria> m_OutputItemsCriteria; +}; + +//----------------------------------------------------------------------------- +// Purpose: Attribute definition details +//----------------------------------------------------------------------------- +enum +{ + ATTDESCFORM_VALUE_IS_PERCENTAGE, // Printed as: ((m_flValue*100)-100.0) + ATTDESCFORM_VALUE_IS_INVERTED_PERCENTAGE, // Printed as: ((m_flValue*100)-100.0) if it's > 1.0, or ((1.0-m_flModifier)*100) if it's < 1.0 + ATTDESCFORM_VALUE_IS_ADDITIVE, // Printed as: m_flValue + ATTDESCFORM_VALUE_IS_ADDITIVE_PERCENTAGE, // Printed as: (m_flValue*100) + ATTDESCFORM_VALUE_IS_OR, // Printed as: m_flValue, but results are ORd together instead of added + ATTDESCFORM_VALUE_IS_DATE, // Printed as a date + ATTDESCFORM_VALUE_IS_ACCOUNT_ID, // Printed as steam user name + ATTDESCFORM_VALUE_IS_PARTICLE_INDEX, // Printed as a particle description + ATTDESCFORM_VALUE_IS_KILLSTREAKEFFECT_INDEX,// Printed as killstreak effect description + ATTDESCFORM_VALUE_IS_KILLSTREAK_IDLEEFFECT_INDEX, // Printed as idle effect description + ATTDESCFORM_VALUE_IS_ITEM_DEF, // Printed as item name + ATTDESCFORM_VALUE_IS_FROM_LOOKUP_TABLE, // Printed as a string from a lookup table, specified by the attribute definition name +}; + +// Coloring for attribute lines +enum attrib_effect_types_t +{ + ATTRIB_EFFECT_UNUSUAL = 0, + ATTRIB_EFFECT_STRANGE, + ATTRIB_EFFECT_NEUTRAL, + ATTRIB_EFFECT_POSITIVE, + ATTRIB_EFFECT_NEGATIVE, + + NUM_EFFECT_TYPES, +}; + +enum EAssetClassAttrExportRule_t +{ + k_EAssetClassAttrExportRule_Default = 0, + k_EAssetClassAttrExportRule_Bucketed = ( 1 << 0 ), // attribute exports bucketed value to Steam Community + k_EAssetClassAttrExportRule_Skip = ( 1 << 1 ), // attribute value is not exported to Steam Community + k_EAssetClassAttrExportRule_GCOnly = ( 1 << 2 ), // attribute only lives on GC and not exported to any external request +}; + +//----------------------------------------------------------------------------- +// CEconItemAttributeDefinition +// Template definition of a randomly created attribute +//----------------------------------------------------------------------------- +class CEconItemAttributeDefinition +{ +public: + CEconItemAttributeDefinition( void ); + CEconItemAttributeDefinition( const CEconItemAttributeDefinition &that ); + CEconItemAttributeDefinition &operator=( const CEconItemAttributeDefinition& rhs ); + + ~CEconItemAttributeDefinition( void ); + + bool BInitFromKV( KeyValues *pKVAttribute, CUtlVector<CUtlString> *pVecErrors = NULL ); + + attrib_definition_index_t GetDefinitionIndex( void ) const { return m_nDefIndex; } + // Attribute name referenced in the db. + const char *GetDefinitionName( void ) const { return m_pszDefinitionName; } + + KeyValues *GetRawDefinition( void ) const { return m_pKVAttribute; } + + // Data accessing + bool IsHidden( void ) const { return m_bHidden; } + bool BForceWebSchemaOutput( void ) const { return m_bWebSchemaOutputForced; } + bool BIsSetBonusAttribute( void ) const { return m_bIsSetBonus; } + bool CanAffectMarketName( void ) const { return m_bCanAffectMarketName; } + bool CanAffectRecipeComponentName( void ) const { return m_bCanAffectRecipeComponentName; } + bool IsStoredAsInteger( void ) const { return m_bStoredAsInteger; } + bool IsStoredAsFloat( void ) const { return !m_bStoredAsInteger; } + int GetUserGenerationType( void ) const { return m_iUserGenerationType; } + bool IsInstanceData() const { return m_bInstanceData; } + EAssetClassAttrExportRule_t GetAssetClassAttrExportRule() const { return m_eAssetClassAttrExportRule; } + uint32 GetAssetClassBucket() const { return m_unAssetClassBucket; } + int GetDescriptionFormat( void ) const { return m_iDescriptionFormat; } + const char *GetDescriptionString( void ) const { return m_pszDescriptionString; } + const char *GetArmoryDescString( void ) const { return m_pszArmoryDesc; } + const char *GetAttributeClass( void ) const { return m_pszAttributeClass; } + econ_tag_handle_t GetItemDefinitionTag( void ) const { return m_ItemDefinitionTag; } + attrib_effect_types_t GetEffectType( void ) const { return m_iEffectType; } + + const class ISchemaAttributeType *GetAttributeType( void ) const { return m_pAttrType; } + +#ifndef GC_DLL + void ClearStringCache( void ) const { m_iszAttributeClass = NULL_STRING; } + string_t GetCachedClass( void ) const + { + if ( m_iszAttributeClass == NULL_STRING && m_pszAttributeClass ) + { + m_iszAttributeClass = AllocPooledString( m_pszAttributeClass ); + } + return m_iszAttributeClass; + } +#endif + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ) + { + VALIDATE_SCOPE(); + ValidatePtr( m_pKVAttribute ); + } +#endif // DBGFLAG_VALIDATE + +private: + // The raw keyvalues for this attribute definition. + KeyValues *m_pKVAttribute; + + // Required valued from m_pKVAttribute: + + // The number used to refer to this definition in the DB + attrib_definition_index_t m_nDefIndex; + + // A pointer to the schema-global type data for this attribute. This maps attribute types to functionality + // for loading/storing, both to memory and the DB. + const class ISchemaAttributeType *m_pAttrType; + + // --------------------------------------------- + // Display related data + // --------------------------------------------- + // If true, this attribute isn't shown in the item description + bool m_bHidden; + + // If true, this attribute's description is always output in web api calls regardless of the hidden flag. + bool m_bWebSchemaOutputForced; + + // Whether or not the value is stored as an integer in the DB. + bool m_bStoredAsInteger; + + // If this is true the attribute is counted as "instance" data for purposes of asset class in the Steam Economy. Non-instance + // properties are considered things that can differentiate items at a fundamental level (ie., definition index, quality); instance + // properties are more things like additional customizations -- score for strange items, paint color, etc. + bool m_bInstanceData; + EAssetClassAttrExportRule_t m_eAssetClassAttrExportRule; // if this is true the attribute will not be exported for asset class + uint32 m_unAssetClassBucket; // if this is set then attribute value is bucketed when exported for asset class + + // Set item bonus attributes use a different attribute parser and make assumptions about memory layout. We + // don't really use these for any new content currently and it isn't worth touching all the old code. + // + // At runtime, this flag is used to determine whether or not to rebuild dynamic attributes attached to + // players on respawn. + bool m_bIsSetBonus; + + // Whether or not this attribute is supposed to only come from user actions. These attributes are used for + // player item upgrades, etc. and cannot be set on items directly in the schema. + int m_iUserGenerationType; + + // Overall positive/negative effect. Used to color the attribute. + attrib_effect_types_t m_iEffectType; + + // Contains the description format & string for this attribute + int m_iDescriptionFormat; + const char *m_pszDescriptionString; + + // Contains information on how to describe items with this attribute in the Armory + const char *m_pszArmoryDesc; + + // Used to allow unique items to specify attributes by name. + const char *m_pszDefinitionName; + + // The class name of this attribute. Used in creation, and to hook the attribute into the actual code that uses it. + const char *m_pszAttributeClass; + + // Allowed to affect the market bucketization name. We dont want things like the strange level to affect the name, + // but we do want things like crate series number and strangifier targets to get their own buckets. + bool m_bCanAffectMarketName; + + // Allowed to list itself in the name of an item in the recipe component description. + bool m_bCanAffectRecipeComponentName; + + // Do item definitions with this attribute specified automatically get an additional tag applied? + econ_tag_handle_t m_ItemDefinitionTag; + +#ifndef GC_DLL + mutable string_t m_iszAttributeClass; // Same as the above, but used for fast lookup when applying attributes. +#endif +}; + + +//----------------------------------------------------------------------------- +// Visual data storage in item definitions +//----------------------------------------------------------------------------- +#define TEAM_VISUAL_SECTIONS 5 +#define MAX_VISUALS_CUSTOM_SOUNDS 10 + +struct attachedparticlesystem_t +{ + attachedparticlesystem_t() : + pszSystemName( NULL ) + , bFollowRootBone( NULL ) + , iCustomType( 0 ) + , nSystemID( 0 ) + , fRefireTime( 0 ) // only works for taunt effects, currently + , bDrawInViewModel( false ) + , bUseSuffixName( false ) + , bHasViewModelSpecificEffect ( false ) + { + V_memset( pszControlPoints, 0, sizeof( pszControlPoints ) ); + } + + const char *pszSystemName; + bool bFollowRootBone; + int iCustomType; + int nSystemID; + float fRefireTime; // only works for taunt effects, currently + bool bDrawInViewModel; + bool bUseSuffixName; + bool bHasViewModelSpecificEffect; + + const char *pszControlPoints[7]; +}; + + +#if defined(CLIENT_DLL) || defined(GAME_DLL) +enum +{ + kAttachedModelDisplayFlag_WorldModel = 0x01, + kAttachedModelDisplayFlag_ViewModel = 0x02, + + kAttachedModelDisplayFlag_MaskAll = kAttachedModelDisplayFlag_WorldModel | kAttachedModelDisplayFlag_ViewModel, +}; + +struct attachedmodel_t +{ + const char *m_pszModelName; + int m_iModelDisplayFlags; +}; + +enum wearableanimplayback_t +{ + WAP_ON_SPAWN, // Play this animation immediately on spawning the wearable + WAP_START_BUILDING, // Game code will start this anim whenever a player wearing this item deploys their builder weapon. + WAP_STOP_BUILDING, // Game code will start this anim whenever a player wearing this item holsters their builder weapon. + WAP_START_TAUNTING, // Game code will start this anim whenever a player wearing this item taunts + WAP_STOP_TAUNTING, // Game code will start this anim whenever a player wearing this item stops taunting + + NUM_WAP_TYPES, +}; + +struct animation_on_wearable_t +{ + int iActivity; + const char *pszActivity; + const char *pszReplacement; + int iReplacement; // Replacement activity to play. Might be set to one of kActivityLookup_Unknown/kActivityLookup_Missing. + const char *pszSequence; + const char *pszRequiredItem; + const char *pszScene; +}; + +struct activity_on_wearable_t +{ + wearableanimplayback_t iPlayback; + int iActivity; + const char *pszActivity; +}; + +struct codecontrolledbodygroupdata_t +{ + const char *pFuncName; + void *pFunc; +}; + +// This is a workaround because Source practice is to disable operator=() for CUtlMap. +struct perteamvisuals_maps_t +{ + perteamvisuals_maps_t() + { + m_ModifiedBodyGroupNames.SetLessFunc( StringLessThan ); + m_CodeControlledBodyGroupNames.SetLessFunc( StringLessThan ); + } + + void operator=( const perteamvisuals_maps_t& other ) + { + DeepCopyMap( other.m_ModifiedBodyGroupNames, &m_ModifiedBodyGroupNames ); + DeepCopyMap( other.m_CodeControlledBodyGroupNames, &m_CodeControlledBodyGroupNames ); + } + + CUtlMap<const char*, int> m_ModifiedBodyGroupNames; // Better method: hide multiple body groups by name. + CUtlMap<const char*, codecontrolledbodygroupdata_t> m_CodeControlledBodyGroupNames; +}; + +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + +class CEconStyleInfo +{ +public: + CEconStyleInfo() + { + for ( int i = 0; i < TEAM_VISUAL_SECTIONS; i++ ) + { + m_iSkins[i] = 0; + m_iViewmodelSkins[i] = -1; + } + + m_pszName = NULL; + m_pszBasePlayerModel = NULL; + m_bIsSelectable = true; + m_pszInventoryImage = NULL; + + m_pszBodygroupName = NULL; + m_iBodygroupSubmodelIndex = -1; + + m_sIconURLSmall = ""; + m_sIconURLLarge = ""; + } + + virtual ~CEconStyleInfo() + { + // + } + + virtual void BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors ); + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + virtual void GeneratePrecacheModelStringsForStyle( CUtlVector<const char *> *out_pVecModelStrings ) const; +#endif + + int GetSkin( int iTeam, bool bViewmodel ) const + { + Assert( iTeam >= 0 ); + Assert( iTeam < TEAM_VISUAL_SECTIONS ); + + if ( bViewmodel && m_iViewmodelSkins[ iTeam ] != -1 ) + { + return m_iViewmodelSkins[ iTeam ]; + } + + return m_iSkins[iTeam]; + } + + const char *GetName() const { return m_pszName; } + const char *GetBasePlayerDisplayModel() const { return m_pszBasePlayerModel; } + const CUtlVector<const char *>& GetAdditionalHideBodygroups() const { return m_vecAdditionalHideBodygroups; } + bool IsSelectable() const { return m_bIsSelectable; } + const char *GetInventoryImage() const { return m_pszInventoryImage; } + + const char *GetBodygroupName() const { return m_pszBodygroupName; } + int GetBodygroupSubmodelIndex() const { return m_iBodygroupSubmodelIndex; } + + const char *GetIconURLSmall() const { return m_sIconURLSmall; } + const char *GetIconURLLarge() const { return m_sIconURLLarge; } + void SetIconURLSmall( const char *szURL ) { m_sIconURLSmall = szURL; } + void SetIconURLLarge( const char *szURL ) { m_sIconURLLarge = szURL; } + +protected: + int m_iSkins[TEAM_VISUAL_SECTIONS]; + int m_iViewmodelSkins[TEAM_VISUAL_SECTIONS]; + const char *m_pszName; + const char *m_pszBasePlayerModel; + bool m_bIsSelectable; + const char *m_pszInventoryImage; + + const char *m_pszBodygroupName; + int m_iBodygroupSubmodelIndex; + + CUtlVector<const char *> m_vecAdditionalHideBodygroups; + +private: + + CUtlString m_sIconURLSmall; + CUtlString m_sIconURLLarge; +}; + +struct perteamvisuals_t +{ + perteamvisuals_t() + { +#if defined(CLIENT_DLL) || defined(GAME_DLL) + iHideParentBodyGroup = -1; + + iSkin = -1; + bUsePerClassBodygroups = false; + pszMaterialOverride = NULL; + pszMuzzleFlash = NULL; + pszTracerEffect = NULL; + pszParticleEffect = NULL; + for ( int i = 0; i < MAX_VISUALS_CUSTOM_SOUNDS; i++ ) + { + pszCustomSounds[i] = NULL; + } + + for ( int i = 0; i < NUM_SHOOT_SOUND_TYPES; i++ ) + { + pszWeaponSoundReplacements[i] = NULL; + } + + m_iViewModelBodyGroupOverride = -1; + m_iViewModelBodyGroupStateOverride = -1; + m_iWorldModelBodyGroupOverride = -1; + m_iWorldModelBodyGroupStateOverride = -1; + +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + } + + ~perteamvisuals_t() + { + m_Styles.PurgeAndDeleteElements(); + } + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + int iHideParentBodyGroup; + + // Properties necessary for the game client/server but not for the GC. + perteamvisuals_maps_t m_Maps; + int iSkin; + bool bUsePerClassBodygroups; + CUtlVector<attachedmodel_t> m_AttachedModels; + CUtlVector<attachedmodel_t> m_AttachedModelsFestive; // Attr controlled Festive Attachments + CUtlVector<attachedparticlesystem_t> m_AttachedParticles; + CUtlVector<animation_on_wearable_t> m_Animations; + CUtlVector<activity_on_wearable_t> m_Activities; + const char *pszCustomSounds[MAX_VISUALS_CUSTOM_SOUNDS]; + const char *pszMaterialOverride; + const char *pszMuzzleFlash; + const char *pszTracerEffect; + const char *pszParticleEffect; + const char *pszWeaponSoundReplacements[NUM_SHOOT_SOUND_TYPES]; + int m_iViewModelBodyGroupOverride; + int m_iViewModelBodyGroupStateOverride; + int m_iWorldModelBodyGroupOverride; + int m_iWorldModelBodyGroupStateOverride; +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + + // The GC does care about styles. + CUtlVector<CEconStyleInfo *> m_Styles; +}; + +enum item_capabilities_t +{ + ITEM_CAP_NONE = 0, + ITEM_CAP_PAINTABLE = 1 << 0, + ITEM_CAP_NAMEABLE = 1 << 1, + ITEM_CAP_DECODABLE = 1 << 2, + ITEM_CAP_CAN_BE_CRAFTED_IF_PURCHASED = 1 << 3, // was ITEM_CAP_CAN_MOD_SOCKET + ITEM_CAP_CAN_CUSTOMIZE_TEXTURE = 1 << 4, + ITEM_CAP_USABLE = 1 << 5, + ITEM_CAP_USABLE_GC = 1 << 6, + ITEM_CAP_CAN_GIFT_WRAP = 1 << 7, + ITEM_CAP_USABLE_OUT_OF_GAME = 1 << 8, + ITEM_CAP_CAN_COLLECT = 1 << 9, + ITEM_CAP_CAN_CRAFT_COUNT = 1 << 10, + ITEM_CAP_CAN_CRAFT_MARK = 1 << 11, + ITEM_CAP_PAINTABLE_TEAM_COLORS = 1 << 12, + ITEM_CAP_CAN_BE_RESTORED = 1 << 13, // can users remove properties (paint, nametag, etc.) from this item via the in-game UI? + ITEM_CAP_CAN_USE_STRANGE_PARTS = 1 << 14, + ITEM_CAP_CAN_CARD_UPGRADE = 1 << 15, + ITEM_CAP_CAN_STRANGIFY = 1 << 16, + ITEM_CAP_CAN_KILLSTREAKIFY = 1 << 17, + ITEM_CAP_CAN_CONSUME = 1 << 18, + ITEM_CAP_CAN_SPELLBOOK_PAGE = 1 << 19, // IT'S A VERB OKAY + ITEM_CAP_HAS_SLOTS = 1 << 20, + ITEM_CAP_DUCK_UPGRADABLE = 1 << 21, + ITEM_CAP_CAN_UNUSUALIFY = 1 << 22, + NUM_ITEM_CAPS = 23, +}; + +enum { ITEM_CAP_DEFAULT = ITEM_CAP_CAN_CRAFT_MARK | ITEM_CAP_CAN_BE_RESTORED | ITEM_CAP_CAN_USE_STRANGE_PARTS | ITEM_CAP_CAN_CARD_UPGRADE | ITEM_CAP_CAN_STRANGIFY | ITEM_CAP_CAN_KILLSTREAKIFY | ITEM_CAP_CAN_CONSUME | ITEM_CAP_CAN_GIFT_WRAP }; // what are the default capabilities on an item? +enum { ITEM_CAP_TOOL_DEFAULT = ITEM_CAP_NONE }; // what are the default capabilities of a tool? + +struct bundleinfo_t +{ + CUtlVector<CEconItemDefinition *> vecItemDefs; +}; + +#ifdef GC_DLL +enum EPaymentRuleType +{ + kPaymentRule_SteamWorkshopFileID = 0x01, + kPaymentRule_PartnerSteamID = 0x02, + kPaymentRule_Bundle = 0x04, +}; + +struct econ_item_payment_rule_t +{ + double m_RevenueShare; + EPaymentRuleType m_eRuleType; + CCopyableUtlVector<uint64> m_vecValues; +}; +#endif // GC_DLL + +#ifdef CLIENT_DLL +namespace vgui +{ + class Panel; +} +#endif // CLIENT_DLL + +class IEconTool +{ + friend class CEconSharedToolSupport; + +public: + IEconTool( const char *pszTypeName, const char *pszUseString, const char *pszUsageRestriction, item_capabilities_t unCapabilities ) + : m_pszTypeName( pszTypeName ) + , m_pszUseString( pszUseString ) + , m_pszUsageRestriction( pszUsageRestriction ) + , m_unCapabilities( unCapabilities ) + { + // + } + + virtual ~IEconTool() { } + + // Shared code. + const char *GetUsageRestriction() const { return m_pszUsageRestriction; } + item_capabilities_t GetCapabilities() const { return m_unCapabilities; } + + virtual bool CanApplyTo( const IEconItemInterface *pTool, const IEconItemInterface *pToolSubject ) const { Assert( pTool ); Assert( pToolSubject ); return true; } + virtual bool ShouldDisplayQuantity( const IEconItemInterface *pTool ) const; + virtual bool RequiresToolEscrowPeriod() const { return false; } + + // We don't support throwing exceptions from tool construction so this is intended to be checked afterwards + // whenever a new tool is created. (See CreateEconToolImpl().) + virtual bool BFinishInitialization() { return true; } + + // Used by the GC only for WebAPI responses and for some weird internal code. + const char *GetTypeName() const { return m_pszTypeName; } // would like to disable on the client so we aren't tempted to check against it, but used for building a unique tool list + const char *GetUseString() const { return m_pszUseString; } + +#ifdef CLIENT_DLL + virtual bool CanBeUsedNow( const IEconItemInterface *pItem ) const { return true; } + virtual bool ShouldShowContainedItemPanel( const IEconItemInterface *pItem ) const { Assert( !"IEconTool::ShouldShowContainedItemPanel(): we don't expect this to be called on anything besides gifts!" ); return false; } + virtual bool ShouldDisplayAsUseableOnItemsInArmory() const { return true; } + virtual const char *GetUseCommandLocalizationToken( const IEconItemInterface *pItem, int i = 0 ) const; + virtual int GetUseCommandCount( const IEconItemInterface *pItem ) const { return 1; } + virtual const char* GetUseCommand( const IEconItemInterface *pItem, int i = 0 ) const; + + + // Client "do something" interface. At least one of these functions must be implemented or your tool + // won't do anything on the client. Some tools (ie., collections) will implement both because they + // have one application behavior and one client-UI behavior. + + // When the client attempts to use a consumable item of any kind, this function will be called. This + // is called from the UI in response to things like using dueling pistols, using a noisemaker, etc. + // Usually this opens up some UI, sends off a GC message, etc. + // + // There is a "default" implementation of this function in ClientConsumableTool_Generic() that can + // be called if specific behavior isn't needed. + virtual void OnClientUseConsumable( class C_EconItemView *pItem, vgui::Panel *pParent ) const + { + Assert( !"IEconTool::OnClientUseConsumable(): unimplemented call!" ); + } + + // When the client attempts to apply a tool to a specific other item in their inventory, this function + // will be called. This is called from the UI is response to things like putting paint on an item, + // using a key to unlock a crate, etc. + virtual void OnClientApplyTool( class C_EconItemView *pTool, class C_EconItemView *pSubject, vgui::Panel *pParent ) const + { + Assert( !"IEconTool::OnClientApplyTool(): unimplemented call!" ); + } +#endif // CLIENT_DLL + +#ifdef GC_DLL + virtual class CGCEconConsumableBehavior *CreateGCConsumableBehavior() const; + virtual bool BGenerateDynamicAttributes( CEconItem* pItem, const CEconGameAccount *pGameAccount ) const { return true; } +#endif // GC_DLL + +private: + const char *m_pszTypeName; + const char *m_pszUseString; + const char *m_pszUsageRestriction; + item_capabilities_t m_unCapabilities; +}; + +//----------------------------------------------------------------------------- +// CQuestObjectiveDefinition +//----------------------------------------------------------------------------- +class CQuestObjectiveDefinition +{ +public: + + CQuestObjectiveDefinition( void ); + virtual ~CQuestObjectiveDefinition( void ); + + virtual bool BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); + + uint32 GetDefinitionIndex( void ) const { return m_nDefIndex; } + const char *GetDescriptionToken( void ) const { return m_pszDescriptionToken; } + bool IsOptional() const { return m_bOptional; } + bool IsAdvanced() const { return m_bAdvanced; } + uint32 GetPoints() const { return m_nPoints; } // TODO: change to a float + +private: + const char *m_pszDescriptionToken; + uint32 m_nDefIndex; + uint32 m_nPoints; + bool m_bOptional; + bool m_bAdvanced; +}; + +//----------------------------------------------------------------------------- +// CEconItemDefinition +// Template Definition of a randomly created item +//----------------------------------------------------------------------------- +class CEconItemDefinition +{ +public: + CEconItemDefinition( void ); + virtual ~CEconItemDefinition( void ); + + // BInitFromKV can be implemented on subclasses to parse additional values. + virtual bool BInitFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); +#if defined(CLIENT_DLL) || defined(GAME_DLL) + virtual bool BInitFromTestItemKVs( int iNewDefIndex, KeyValues *pKVItem, CUtlVector<CUtlString>* pVecErrors = NULL ); + virtual void GeneratePrecacheModelStrings( bool bDynamicLoad, CUtlVector<const char *> *out_pVecModelStrings ) const; + virtual void GeneratePrecacheSoundStrings( bool bDynamicLoad, CUtlVector<const char *> *out_pVecSoundStrings ) const; + virtual void CopyPolymorphic( const CEconItemDefinition *pSourceDef ) { *this = *pSourceDef; } +#endif + + bool BInitItemMappings( CUtlVector<CUtlString> *pVecErrors ); + + void BInitVisualBlockFromKV( KeyValues *pKVItem, CUtlVector<CUtlString> *pVecErrors = NULL ); + void BInitStylesBlockFromKV( KeyValues *pKVStyles, perteamvisuals_t *pVisData, CUtlVector<CUtlString> *pVecErrors ); + + item_definition_index_t GetDefinitionIndex( void ) const { return m_nDefIndex; } + bool BEnabled( void ) const { return m_bEnabled; } + bool BLoadOnDemand( void ) const { return m_bLoadOnDemand; } + bool BHasBeenLoaded( void ) const { return m_bHasBeenLoaded; } + const char *GetDefinitionName( void ) const { return m_pszDefinitionName; } + const char *GetItemDefinitionName( void ) const { return m_pszDefinitionName; } + const char *GetItemClass( void ) const { return m_pszItemClassname; } + const char *GetItemBaseName( void ) const { return m_pszItemBaseName; } + const char *GetBrassModelOverride( void ) const{ return m_pszBrassModelOverride; } + const char *GetItemTypeName( void ) const { return m_pszItemTypeName; } + uint8 GetMinLevel( void ) const { return m_unMinItemLevel; } + uint8 GetMaxLevel( void ) const { return m_unMaxItemLevel; } + uint8 GetItemSeries( void ) const { return m_unItemSeries; } + uint8 GetQuality( void ) const { return m_nItemQuality; } + void SetRarity( uint8 nRarity ) { Assert( m_nItemRarity == k_unItemRarity_Any ); m_nItemRarity = nRarity; } + uint8 GetRarity( void ) const { return m_nItemRarity; } + uint8 GetForcedQuality( void ) const { return m_nForcedItemQuality; } + uint16 GetDefaultDropQuantity( void ) const { return m_nDefaultDropQuantity; } + KeyValues *GetRawDefinition( void ) const { return m_pKVItem; } + const char *GetDefinitionString( const char *pszKeyName, const char *pszDefaultValue = "" ) const; + KeyValues *GetDefinitionKey( const char *pszKeyName ) const; + const CUtlVector<static_attrib_t> &GetStaticAttributes( void ) const { return m_vecStaticAttributes; } +#ifdef TF_CLIENT_DLL + uint32 GetNumConcreteItems() const { return m_unNumConcreteItems; } +#endif // TF_CLIENT_DLL + + // Data accessing + bool IsHidden( void ) const { return m_bHidden; } + bool IsImported( void ) const { return m_bImported; } + bool IsAllowedInMatch( void ) const { return m_bAllowedInThisMatch; } + bool IsBaseItem( void ) const { return m_bBaseItem; } + bool IsBundle( void ) const { return m_BundleInfo != NULL; } + bool HasProperName( void ) const { return m_bProperName; } + const char *GetClassToken( void ) const { return m_pszClassToken; } + const char *GetSlotToken( void ) const { return m_pszSlotToken; } + bool ShouldAttachToHands( void ) const { return m_bAttachToHands; } + bool ShouldAttachToHandsVMOnly( void ) const { return m_bAttachToHandsVMOnly; } + bool ShouldFlipViewmodels( void ) const { return m_bFlipViewModel; } + int GetInventoryImagePosition( int iIndex ) const { Assert( iIndex >= 0 && iIndex < 2); return m_iInventoryImagePosition[iIndex]; } + int GetInventoryImageSize( int iIndex ) const { Assert( iIndex >= 0 && iIndex < 2); return m_iInventoryImageSize[iIndex]; } + int GetDropType( void ) const { return m_iDropType; } + const char *GetHolidayRestriction( void ) const { return m_pszHolidayRestriction; } + int GetVisionFilterFlags( void ) const { return m_nVisionFilterFlags; } + int GetSubType( void ) const { return m_iSubType; } + item_capabilities_t GetCapabilities( void ) const { return m_iCapabilities; } + int GetArmoryRemap( void ) const { return m_iArmoryRemap; } + int GetStoreRemap( void ) const { return m_iStoreRemap; } + item_definition_index_t GetSetItemRemap() const { return m_unSetItemRemapDefIndex; } // what def index do we consider ourself for purposes of determining "is an item equipped that satisfies this set slot?" (ie., Festive Huntsman -> Huntsman); default is to point to itself + const char *GetXifierRemapClass() const { return m_pszXifierRemapClass; } + const char *GetBaseFunctionalItemName() const { return m_pszBaseFunctionalItemName; } + const char *GetParticleSuffix() const { return m_pszParticleSuffix; } + + const CEconItemSetDefinition *GetItemSetDefinition( void ) const { return m_pItemSetDef; } + void SetItemSetDefinition( const CEconItemSetDefinition *pItemSetDef ) { Assert( !m_pItemSetDef ); m_pItemSetDef = pItemSetDef; } + + const CEconItemCollectionDefinition *GetItemCollectionDefinition( void ) const { return m_pItemCollectionDef; } + void SetItemCollectionDefinition( const CEconItemCollectionDefinition *pItemCollectionDef ) { Assert( !m_pItemCollectionDef ); m_pItemCollectionDef = pItemCollectionDef; } + + CEconItemPaintKitDefinition *GetCustomPainkKitDefinition( void ) const { return m_pItemPaintKitDef; } + void SetItemPaintKitDefinition( CEconItemPaintKitDefinition *pItemPaintKitDef ) { Assert( !m_pItemPaintKitDef ); m_pItemPaintKitDef = pItemPaintKitDef; } + + perteamvisuals_t *GetPerTeamVisual( int iTeam ) const { return m_PerTeamVisuals[iTeam]; } + + bool IsTool() const { return m_bIsTool; } + const IEconTool *GetEconTool() const { return m_pTool; } + template < class T > + const T *GetTypedEconTool() const { return dynamic_cast<const T *>( GetEconTool() ); } + + const bundleinfo_t *GetBundleInfo( void ) const { return m_BundleInfo; } + virtual int GetBundleItemCount( void ) const { return m_BundleInfo ? m_BundleInfo->vecItemDefs.Count() : 0; } + virtual int GetBundleItem( int iIndex ) const { return m_BundleInfo ? m_BundleInfo->vecItemDefs[iIndex]->GetDefinitionIndex() : -1; } + + // Is this item contained in any bundles? GetContainingBundles() gets the CEconItemDefinitions for those bundles. + const CUtlVector< const CEconItemDefinition * > &GetContainingBundles() const { return m_vecContainingBundleItemDefs; } + uint32 GetContainingBundleCount() const { return m_vecContainingBundleItemDefs.Count(); } + + void AddSteamWorkshopContributor( uint32 unAccountID ) { if ( m_vecSteamWorkshopContributors.InvalidIndex() == m_vecSteamWorkshopContributors.Find( unAccountID ) ) { m_vecSteamWorkshopContributors.AddToTail( unAccountID ); } } + const CUtlVector< uint32 > &GetSteamWorkshopContributors() const { return m_vecSteamWorkshopContributors; } + bool BIsSteamWorkshopItem() const { return m_vecSteamWorkshopContributors.Count() > 0; } + + const char *GetIconClassname( void ) const { return m_pszItemIconClassname; } + const char *GetLogClassname( void ) const { return m_pszItemLogClassname; } + const char *GetInventoryModel( void ) const { return m_pszInventoryModel; } + const char *GetInventoryImage( void ) const { return m_pszInventoryImage; } + const char *GetInventoryOverlayImage( int idx ) const { if ( m_pszInventoryOverlayImages.IsValidIndex( idx ) ) return m_pszInventoryOverlayImages[idx]; else return NULL; } + int GetInventoryOverlayImageCount( void ) const { return m_pszInventoryOverlayImages.Count(); } + int GetInspectPanelDistance( void ) const { return m_iInspectPanelDistance; } + const char *GetIconURLSmall() const { return GetIconURL( "s" ); } // Plain small + const char *GetIconURLLarge() const { return GetIconURL( "l" ); } // Plain large + void SetIconURL( const char* pszKey, const char *szURL ) { m_pDictIcons->Insert( pszKey, CUtlString( szURL ) ); } + const char *GetIconURL( const char* pszKey ) const; + const char *GetBasePlayerDisplayModel() const { return m_pszBaseDisplayModel; } + int GetDefaultSkin() const { return m_iDefaultSkin; } + const char *GetWorldDisplayModel() const { return m_pszWorldDisplayModel; } + const char *GetCollectionReference() const { return m_pszCollectionReference; } + + // Some weapons need a custom model for icon generation. If this value is not present, the world model is used. + virtual const char *GetIconDisplayModel() const; + + const char *GetExtraWearableModel( void ) const { return m_pszWorldExtraWearableModel; } + const char *GetExtraWearableViewModel( void ) const { return m_pszWorldExtraWearableViewModel; } + const char *GetVisionFilteredDisplayModel() const { return m_pszVisionFilteredDisplayModel; } + const char *GetItemDesc( void ) const { return m_pszItemDesc; } + const char *GetArmoryDescString( void ) const { return m_pszArmoryDesc; } + RTime32 GetExpirationDate( void ) const { return m_rtExpiration; } + bool ShouldShowInArmory( void ) const { return m_bShouldShowInArmory; } + bool IsActingAsAWearable( void ) const { return m_bActAsWearable; } + bool IsActingAsAWeapon( void ) const { return m_bActAsWeapon; } + bool GetHideBodyGroupsDeployedOnly( void ) const { return m_bHideBodyGroupsDeployedOnly; } + bool IsPackBundle( void ) const { return m_bIsPackBundle; } + bool IsPackItem( void ) const { return m_bIsPackItem; } + CEconItemDefinition *GetOwningPackBundle() { return m_pOwningPackBundle; } + const CEconItemDefinition *GetOwningPackBundle() const { return m_pOwningPackBundle; } + const char *GetDatabaseAuditTableName( void ) const { return m_pszDatabaseAuditTable; } + + void SetIsPackItem( bool bIsPackItem ) { m_bIsPackItem = bIsPackItem; } + + equip_region_mask_t GetEquipRegionMask( void ) const { return m_unEquipRegionMask; } + equip_region_mask_t GetEquipRegionConflictMask( void ) const { return m_unEquipRegionConflictMask; } + + // Dynamic modification during gameplay + void SetAllowedInMatch( bool bAllowed ) { m_bAllowedInThisMatch = bAllowed; } + void SetHasBeenLoaded( bool bLoaded ) { m_bHasBeenLoaded = bLoaded; } + + // Generate and return a random level according to whatever leveling curve this definition uses. + uint32 RollItemLevel( void ) const; + + const char *GetFirstSaleDate( void ) const; + + void IterateAttributes( class IEconItemAttributeIterator *pIterator ) const; + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + // Visuals + // Attached models + int GetNumAttachedModels( int iTeam ) const; + attachedmodel_t *GetAttachedModelData( int iTeam, int iIdx ) const; + + int GetNumAttachedModelsFestivized( int iTeam ) const; + attachedmodel_t *GetAttachedModelDataFestivized( int iTeam, int iIdx ) const; + + // Attached particle systems + int GetNumAttachedParticles( int iTeam ) const; + attachedparticlesystem_t *GetAttachedParticleData( int iTeam, int iIdx ) const; + // Activities + int GetNumPlaybackActivities( int iTeam ) const; + activity_on_wearable_t *GetPlaybackActivityData( int iTeam, int iIdx ) const; + // Animations + int GetNumAnimations( int iTeam ) const; + animation_on_wearable_t *GetAnimationData( int iTeam, int iIdx ) const; + // Animation Overrides + Activity GetActivityOverride( int iTeam, Activity baseAct ) const; + const char *GetActivityOverride( int iTeam, const char *pszActivity ) const; + const char *GetReplacementForActivityOverride( int iTeam, Activity baseAct ) const; + // Should the content (meshes, etc.) for this be streamed or preloaded? + virtual bool IsContentStreamable() const; +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + + // FX Overrides + const char *GetMuzzleFlash( int iTeam ) const; + const char *GetTracerEffect( int iTeam ) const; + const char *GetParticleEffect( int iTeam ) const; + // Materials + const char *GetMaterialOverride( int iTeam ) const; + // Sounds + const char *GetCustomSound( int iTeam, int iSound ) const; + const char *GetWeaponReplacementSound( int iTeam, /*WeaponSound_t*/ int iSound ) const; + // Bodygroups + int GetHiddenParentBodygroup( int iTeam ) const; + int GetNumModifiedBodyGroups( int iTeam ) const; + const char* GetModifiedBodyGroup( int iTeam, int i, int& body ) const; + bool UsesPerClassBodygroups( int iTeam ) const; + int GetNumCodeControlledBodyGroups( int iTeam ) const; + const char* GetCodeControlledBodyGroup( int iIteam, int i, struct codecontrolledbodygroupdata_t &ccbgd ) const; + + style_index_t GetNumStyles() const; + style_index_t GetNumSelectableStyles() const; + const CEconStyleInfo *GetStyleInfo( style_index_t unStyle ) const; + + int GetViewmodelBodygroupOverride( int iTeam ) const; + int GetViewmodelBodygroupStateOverride( int iTeam ) const; + int GetWorldmodelBodygroupOverride( int iTeam ) const; + int GetWorldmodelBodygroupStateOverride( int iTeam ) const; + + int GetPopularitySeed() const { return m_nPopularitySeed; } + + bool HasEconTag( econ_tag_handle_t tag ) const { return m_vecTags.IsValidIndex( m_vecTags.Find( tag ) ); } + + bool BValidForShuffle( void ) const { return m_bValidForShuffle; } + bool BValidForSelfMade( void ) const { return m_bValidForSelfMade; } + +#ifdef GC_DLL +private: + MUST_CHECK_RETURN bool BInitializeEconItemGenerators( KeyValues *pKV, CUtlVector<CUtlString> *pVecErrors ); + +public: + // If this returns true, all relevant property generators were applied to the item instance + // passed in. If this returns false, some or none of the generators may have been applied, + // but there are no guarantees about the item state. + MUST_CHECK_RETURN bool BApplyPropertyGenerators( CEconItem *pItem ) const; + + const CUtlVector<econ_tag_handle_t>& GetEconTags() const { return m_vecTags; } // meant for internal/debug use only, not for runtime iteration + const CUtlVector<econ_item_payment_rule_t>& GetPaymentRules() const { return m_vecPaymentRules; } + +private: + int AddPaymentRule( const econ_item_payment_rule_t& newRule ); // returns which payment rule number was just created +public: +#endif // GC_DLL + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + int GetStyleSkin( style_index_t unStyle, int iTeam, bool bViewmodel ) const; + const char* GetStyleInventoryImage( style_index_t unStyle ) const; + int GetBestVisualTeamData( int iTeam ) const; +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ) + { + VALIDATE_SCOPE(); + ValidateObj( m_vecStaticAttributes ); + ValidatePtr( m_pKVItem ); + ValidatePtr( m_pProxyCriteria ); + } +#endif // DBGFLAG_VALIDATE + + +private: + // Pointer to the raw KeyValue definition of the item + KeyValues * m_pKVItem; + + // Required values from m_pKVItem: + + // The number used to refer to this definition in the DB + item_definition_index_t m_nDefIndex; + + // False if this definition has been turned off and we're not using it to generate items + bool m_bEnabled; + + // These values specify the range of item levels that an item based off this definition can be generated within. + uint8 m_unMinItemLevel; + uint8 m_unMaxItemLevel; + + // This specifies an item quality that items from this definition must be set to. Used mostly to specify unique item definitions. + uint8 m_nItemQuality; + uint8 m_nForcedItemQuality; + uint8 m_nItemRarity; + + // Default drop quantity + uint16 m_nDefaultDropQuantity; + + // Item Series + uint8 m_unItemSeries; + + // Static attributes (ones that are always on these items) + CUtlVector<static_attrib_t> m_vecStaticAttributes; + + // Seeds the popular item list with this number of the item when the list is reset. + uint8 m_nPopularitySeed; + + // --------------------------------------------- + // Display related data + // --------------------------------------------- + // The base name of this item. i.e. "The Kritz-Krieg". + const char *m_pszItemBaseName; + bool m_bProperName; // If set, the name will have "The" prepended to it, unless it's got a non-unique quality + // in which case it'll have "A" prepended to the quality. i.e. A Community Kritzkrieg + + // The base type of this item. i.e. "Rocket Launcher" or "Shotgun". + // This is often the same as the base name, but not always. + const char *m_pszItemTypeName; + + // The item's non-attribute description. + const char *m_pszItemDesc; + + // expiration time + RTime32 m_rtExpiration; + + // The .mdl file used for this item when it's displayed in inventory-style boxes. + const char *m_pszInventoryModel; + // Alternatively, the image used for this item when it's displayed in inventory-style boxes. If specified, it's used over the model. + const char *m_pszInventoryImage; + // An optional image that's overlayed over the top of the base inventory image. It'll be RGB colored by the tint color of the item. + CUtlVector<const char*> m_pszInventoryOverlayImages; + int m_iInventoryImagePosition[2]; + int m_iInventoryImageSize[2]; + int m_iInspectPanelDistance; + + const char *m_pszBaseDisplayModel; + int m_iDefaultSkin; + bool m_bLoadOnDemand; + bool m_bHasBeenLoaded; + + bool m_bHideBodyGroupsDeployedOnly; + + // The .mdl file used for the world view. + // This is inferior to using a c_model, but because the geometry of the sticky bomb launcher's + // world model is significantly different from the view model the demoman pack requires + // using two separate models for now. + const char *m_pszWorldDisplayModel; + const char *m_pszWorldExtraWearableModel; // Some weapons attach an extra wearable item to the player + const char *m_pszWorldExtraWearableViewModel; // Some weapons attach an extra wearable view model item to the player + const char *m_pszVisionFilteredDisplayModel; // Some weapons display differently depending on the viewer's filters + + const char *m_pszCollectionReference; // Reference a colletion + + // If set, we use the base hands model for a viewmodel, and bonemerge the above player model + bool m_bAttachToHands; + bool m_bAttachToHandsVMOnly; + + // If set, we will force the view model to render flipped. Good for models built left handed. + bool m_bFlipViewModel; + + // This is a wearable that sits in a non-wearable loadout slot + bool m_bActAsWearable; + + // This is a weapon that sits in a wearable slot (Action) + bool m_bActAsWeapon; + + // Is this Item a tool + bool m_bIsTool; + + // The set this item is a member of + const CEconItemSetDefinition *m_pItemSetDef; + const CEconItemCollectionDefinition *m_pItemCollectionDef; + + CEconItemPaintKitDefinition *m_pItemPaintKitDef; + + // A list of per-team visual data used to modify base model for visual recognition + perteamvisuals_t *m_PerTeamVisuals[TEAM_VISUAL_SECTIONS]; + + // Optional override for specifying a custom shell ejection model + const char *m_pszBrassModelOverride; + + IEconTool *m_pTool; + bundleinfo_t *m_BundleInfo; + item_capabilities_t m_iCapabilities; + +#ifdef TF_CLIENT_DLL + uint32 m_unNumConcreteItems; // This is the number of items that will actually end up in a user's inventory - this can be 0 for some items (e.g. map stamps in TF), 1 for a "regular" item, or many for bundles, etc. +#endif // TF_CLIENT_DLL + + CUtlDict< CUtlString >* m_pDictIcons; + + // --------------------------------------------- + // Creation related data + // --------------------------------------------- + // The entity classname for this item. + const char *m_pszItemClassname; + + // The entity name that will be displayed in log files. + const char *m_pszItemLogClassname; + + // The name of the icon used in the death notices. + const char *m_pszItemIconClassname; + + // This is the script file name of this definition. Used to generate items by script name. + const char *m_pszDefinitionName; + + // This is used for auditing purposes + const char *m_pszDatabaseAuditTable; + + bool m_bHidden; + bool m_bShouldShowInArmory; + bool m_bBaseItem; + bool m_bImported; + + // A pack bundle is a bundle that contains items that are not for sale individually + bool m_bIsPackBundle; + + // A pack item is an item which is not for sale individually and is only for sale as part of a pack bundle. A 'regular' bundle can only include a pack bundle by explicitly including all of the pack bundle's items individually. + // If this pointer is non-NULL, this item is considered to be a pack item (see CEconItemDefinition::IsPackItem()). + CEconItemDefinition *m_pOwningPackBundle; + bool m_bIsPackItem; + + // Contains information on how to describe items with this attribute in the Armory + const char *m_pszArmoryDesc; + + // Temporary(?) solution to allow xifiers to work on botkiller and festive variants of weapons + const char *m_pszXifierRemapClass; + + // Base item name -- used for grouping weapon functionality + const char *m_pszBaseFunctionalItemName; + + // For particle effects that have derivatives, what is the suffix for this item + const char *m_pszParticleSuffix; + + // --------------------------------------------- + // Remapping data for armory/store + // --------------------------------------------- + int m_iArmoryRemap; + int m_iStoreRemap; + const char *m_pszArmoryRemap; + const char *m_pszStoreRemap; + + // --------------------------------------------- + // Crafting related data + // --------------------------------------------- + const char *m_pszClassToken; + const char *m_pszSlotToken; + + // --------------------------------------------- + // Gameplay related data + // --------------------------------------------- + // How to behave when the player wearing the item dies. + int m_iDropType; + + // Holiday restriction. Item only has an appearance when the holiday is in effect. + const char *m_pszHolidayRestriction; + + // Meet the pyro makes some items invisible unless you're wearing Pyro Goggles + int m_nVisionFilterFlags; + + // Temporary. Revisit this in the engineer update. Enables an additional buildable. + int m_iSubType; + + // Whitelist support for tournament mode + bool m_bAllowedInThisMatch; + + equip_region_mask_t m_unEquipRegionMask; // which equip regions does this item cover directly + equip_region_mask_t m_unEquipRegionConflictMask; // which equip regions does equipping this item prevent from having something in them + + item_definition_index_t m_unSetItemRemapDefIndex; // reference to the definition index we want to consider this item for set matching purposes; see GetSetItemRemap() + +#ifdef GC_DLL + CUtlVector<const IEconItemPropertyGenerator *> m_vecPropertyGenerators; + CUtlVector<econ_item_payment_rule_t> m_vecPaymentRules; +#endif // GC_DLL + + // False if this definition is not allowed to be part of a shuffled crate's contents + bool m_bValidForShuffle; + + // False if this definition should not grant self-made items + bool m_bValidForSelfMade; + +protected: + // Protected to allow subclasses to add/remove game-specific tags. + CUtlVector<econ_tag_handle_t> m_vecTags; + CUtlVector<const CEconItemDefinition *> m_vecContainingBundleItemDefs; // Item definition indices for any bundles which contain this item + CUtlVector<uint32> m_vecSteamWorkshopContributors; + + friend class CEconItemSchema; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline style_index_t CEconItemDefinition::GetNumStyles() const +{ + const perteamvisuals_t *pVisData = GetPerTeamVisual( 0 ); + + if ( !pVisData ) + return 0; + + // Bad things will happen if we ever get more styles than will fit in our + // style index type. Not Very Bad things, but bad things. Mostly we'll fail + // to iterate over all our styles. + return pVisData->m_Styles.Count(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Similar to GetNumStyles, but only the selectable styles +//----------------------------------------------------------------------------- +inline style_index_t CEconItemDefinition::GetNumSelectableStyles() const +{ + const perteamvisuals_t *pVisData = GetPerTeamVisual(0); + + if (!pVisData) + return 0; + + style_index_t nCount = 0; + FOR_EACH_VEC( pVisData->m_Styles, i ) + { + if( pVisData->m_Styles[i]->IsSelectable() ) + { + ++nCount; + } + } + + return nCount; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const CEconStyleInfo *CEconItemDefinition::GetStyleInfo( style_index_t unStyle ) const +{ + const perteamvisuals_t *pBaseVisuals = GetPerTeamVisual( 0 ); + if ( !pBaseVisuals || !pBaseVisuals->m_Styles.IsValidIndex( unStyle ) ) + return NULL; + + return pBaseVisuals->m_Styles[unStyle]; +} + +#if defined(CLIENT_DLL) || defined(GAME_DLL) +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumAttachedModels( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_AttachedModels.Count(); +#else + return 0; +#endif +} +//----------------------------------------------------------------------------- +inline attachedmodel_t *CEconItemDefinition::GetAttachedModelData( int iTeam, int iIdx ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + perteamvisuals_t *pVisuals = GetPerTeamVisual(iTeam); + Assert( pVisuals ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !pVisuals ) + return NULL; + + Assert( iIdx < pVisuals->m_AttachedModels.Count() ); + if ( iIdx >= pVisuals->m_AttachedModels.Count() ) + return NULL; + + return &pVisuals->m_AttachedModels[iIdx]; +#else + return NULL; +#endif +} +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumAttachedModelsFestivized( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + perteamvisuals_t *pVisuals = GetPerTeamVisual(iTeam); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !pVisuals ) + return 0; + return pVisuals->m_AttachedModelsFestive.Count(); +#else + return 0; +#endif +} +//----------------------------------------------------------------------------- +inline attachedmodel_t *CEconItemDefinition::GetAttachedModelDataFestivized( int iTeam, int iIdx ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + perteamvisuals_t *pVisuals = GetPerTeamVisual(iTeam); + Assert( pVisuals ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !pVisuals ) + return NULL; + + Assert( iIdx < pVisuals->m_AttachedModelsFestive.Count() ); + if ( iIdx >= pVisuals->m_AttachedModelsFestive.Count() ) + return NULL; + + return &pVisuals->m_AttachedModelsFestive[iIdx]; +#else + return NULL; +#endif +} +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumPlaybackActivities( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_Activities.Count(); +#else + return 0; +#endif +} + +inline activity_on_wearable_t *CEconItemDefinition::GetPlaybackActivityData( int iTeam, int iIdx ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + Assert( GetPerTeamVisual(iTeam) ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + + Assert( iIdx < GetPerTeamVisual(iTeam)->m_Activities.Count() ); + if ( iIdx >= GetPerTeamVisual(iTeam)->m_Activities.Count() ) + return NULL; + + return &GetPerTeamVisual(iTeam)->m_Activities[iIdx]; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumAnimations( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_Animations.Count(); +#else + return 0; +#endif +} +inline animation_on_wearable_t *CEconItemDefinition::GetAnimationData( int iTeam, int iIdx ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + Assert( GetPerTeamVisual(iTeam) ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + + Assert( iIdx < GetPerTeamVisual(iTeam)->m_Animations.Count() ); + if ( iIdx >= GetPerTeamVisual(iTeam)->m_Animations.Count() ) + return NULL; + + return &GetPerTeamVisual(iTeam)->m_Animations[iIdx]; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumAttachedParticles( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_AttachedParticles.Count(); +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline attachedparticlesystem_t *CEconItemDefinition::GetAttachedParticleData( int iTeam, int iIdx ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + Assert( GetPerTeamVisual(iTeam) ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + + Assert( iIdx < GetPerTeamVisual(iTeam)->m_AttachedParticles.Count() ); + if ( iIdx >= GetPerTeamVisual(iTeam)->m_AttachedParticles.Count() ) + return NULL; + + return &GetPerTeamVisual(iTeam)->m_AttachedParticles[iIdx]; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetMaterialOverride( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + return GetPerTeamVisual(iTeam)->pszMaterialOverride; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetMuzzleFlash( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + return GetPerTeamVisual(iTeam)->pszMuzzleFlash; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetTracerEffect( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + return GetPerTeamVisual(iTeam)->pszTracerEffect; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetParticleEffect( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + return GetPerTeamVisual(iTeam)->pszParticleEffect; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetHiddenParentBodygroup( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return -1; + return GetPerTeamVisual(iTeam)->iHideParentBodyGroup; +#else + return -1; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumModifiedBodyGroups( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return -1; + return GetPerTeamVisual(iTeam)->m_Maps.m_ModifiedBodyGroupNames.Count(); +#else + return -1; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char* CEconItemDefinition::GetModifiedBodyGroup( int iTeam, int i, int& body ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + body = GetPerTeamVisual(iTeam)->m_Maps.m_ModifiedBodyGroupNames[i]; + return GetPerTeamVisual(iTeam)->m_Maps.m_ModifiedBodyGroupNames.Key(i); +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetNumCodeControlledBodyGroups( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return -1; + return GetPerTeamVisual(iTeam)->m_Maps.m_CodeControlledBodyGroupNames.Count(); +#else + return -1; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char* CEconItemDefinition::GetCodeControlledBodyGroup( int iTeam, int i, codecontrolledbodygroupdata_t &ccbgd ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + ccbgd = GetPerTeamVisual(iTeam)->m_Maps.m_CodeControlledBodyGroupNames[i]; + return GetPerTeamVisual(iTeam)->m_Maps.m_CodeControlledBodyGroupNames.Key(i); +#else + return NULL; +#endif +} + +#if defined(CLIENT_DLL) || defined(GAME_DLL) +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetStyleSkin( style_index_t unStyle, int iTeam, bool bViewmodel ) const +{ + const CEconStyleInfo *pStyle = GetStyleInfo( unStyle ); + + // Return our skin if we have a style or our default skin of -1 otherwise. + return pStyle + ? pStyle->GetSkin( iTeam, bViewmodel ) + : GetDefaultSkin(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char* CEconItemDefinition::GetStyleInventoryImage( style_index_t unStyle ) const +{ + const CEconStyleInfo *pStyle = GetStyleInfo( unStyle ); + + return pStyle ? pStyle->GetInventoryImage() : NULL; +} + +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetViewmodelBodygroupOverride( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_iViewModelBodyGroupOverride; +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetViewmodelBodygroupStateOverride( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_iViewModelBodyGroupStateOverride; +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetWorldmodelBodygroupOverride( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_iWorldModelBodyGroupOverride; +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetWorldmodelBodygroupStateOverride( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return 0; + return GetPerTeamVisual(iTeam)->m_iWorldModelBodyGroupStateOverride; +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline bool CEconItemDefinition::UsesPerClassBodygroups( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return false; + return GetPerTeamVisual(iTeam)->bUsePerClassBodygroups; +#else + return false; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetCustomSound( int iTeam, int iSound ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + if ( iSound < 0 || iSound >= MAX_VISUALS_CUSTOM_SOUNDS ) + return NULL; + return GetPerTeamVisual(iTeam)->pszCustomSounds[iSound]; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline const char *CEconItemDefinition::GetWeaponReplacementSound( int iTeam, /* WeaponSound_t */ int iSound ) const +{ +#ifndef CSTRIKE_DLL + iTeam = GetBestVisualTeamData( iTeam ); + if ( iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS || !GetPerTeamVisual(iTeam) ) + return NULL; + if ( iSound < 0 || iSound >= NUM_SHOOT_SOUND_TYPES ) + return NULL; + return GetPerTeamVisual(iTeam)->pszWeaponSoundReplacements[iSound]; +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +inline int CEconItemDefinition::GetBestVisualTeamData( int iTeam ) const +{ +#ifndef CSTRIKE_DLL + Assert( iTeam >= 0 && iTeam < TEAM_VISUAL_SECTIONS ); + // If we don't have data for the specified team, try to fall back to the base + // if ( !GetStaticData() ) + // return 0; + if ( (iTeam < 0 || iTeam >= TEAM_VISUAL_SECTIONS) || (iTeam > 0 && !GetPerTeamVisual(iTeam)) ) + return 0; + return iTeam; +#else + return 0; +#endif +} +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + +//----------------------------------------------------------------------------- +// CTimedItemRewardDefinition +// Describes a periodic item reward +//----------------------------------------------------------------------------- +class CTimedItemRewardDefinition +{ +public: + CTimedItemRewardDefinition( void ); + CTimedItemRewardDefinition( const CTimedItemRewardDefinition &that ); + CTimedItemRewardDefinition &operator=( const CTimedItemRewardDefinition& rhs ); + + ~CTimedItemRewardDefinition( void ) { } + + bool BInitFromKV( KeyValues *pKVTimedReward, CUtlVector<CUtlString> *pVecErrors = NULL ); + + uint32 GetRandomFrequency( void ) const { return RandomFloat( m_unMinFreq, m_unMaxFreq ); } + uint32 GetMinFrequency( void ) const { return m_unMinFreq; } + uint32 GetMaxFrequency( void ) const { return m_unMaxFreq; } + float GetChance( void ) const { return m_flChance; } + const CItemSelectionCriteria &GetCriteria( void ) const { return m_criteria; } + const CEconLootListDefinition *GetLootList( void ) const { return m_pLootList; } + + bool BHasRequiredItem() const { return m_iRequiredItemDef != INVALID_ITEM_DEF_INDEX; } + item_definition_index_t GetRequiredItem() const { return m_iRequiredItemDef; } + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ) + { + VALIDATE_SCOPE(); + ValidateObj( m_criteria ); + } +#endif // DBGFLAG_VALIDATE + +private: + // Frequency of how often the item is awarded + uint32 m_unMinFreq; + uint32 m_unMaxFreq; + + // The chance, between 0 and 1, that the item is rewarded + float m_flChance; + + // The criteria to use to select the item to reward + CItemSelectionCriteria m_criteria; + // Alternatively, the loot_list to use instead + const CEconLootListDefinition *m_pLootList; + + item_definition_index_t m_iRequiredItemDef; +}; + +#ifdef GC_DLL +//----------------------------------------------------------------------------- +// CExperimentDefinition +//----------------------------------------------------------------------------- +struct experiment_group_t +{ + const char* m_pName; + uint32 m_unNumParticipants; + uint32 m_unMaxParticipants; + KeyValues *m_pKeyValues; +}; + +class CExperimentDefinition +{ +public: + CExperimentDefinition( void ); + ~CExperimentDefinition( void ); + + bool BInitFromKV( KeyValues *pKVExperiment, CUtlVector<CUtlString> *pVecErrors = NULL ); + + CUtlVector< experiment_group_t > &GetGroups() { return m_vecGroups; } + + uint32 GetID() const { return m_unExperimentID; } + const char *GetName( void ) const { return m_pKeyValues->GetString( "name", "unknown" ); } + const char *GetDescription( void ) const { return m_pKeyValues->GetString( "description", "unknown" ); } + + bool IsEnabled() const { return m_bEnabled; } + bool IsFull() const { return m_unNumParticipants >= m_unMaxParticipants; } + + uint32 GetNumParticipants() const { return m_unNumParticipants; } + void SetNumParticipants( uint32 unNumParticipants ) { m_unNumParticipants = unNumParticipants; } + uint32 GetMaxParticipants() const { return m_unMaxParticipants; } + + bool ChooseGroup( uint32 &unGroup ); + +private: + bool m_bEnabled; + uint32 m_unExperimentID; + uint32 m_unNumParticipants; + uint32 m_unMaxParticipants; + KeyValues *m_pKeyValues; + CUtlVector< experiment_group_t > m_vecGroups; +}; +#endif + +//----------------------------------------------------------------------------- +// CItemLevelingDefinition +//----------------------------------------------------------------------------- +class CItemLevelingDefinition +{ +public: + CItemLevelingDefinition( void ); + CItemLevelingDefinition( const CItemLevelingDefinition &that ); + CItemLevelingDefinition &operator=( const CItemLevelingDefinition& rhs ); + + ~CItemLevelingDefinition( void ); + + bool BInitFromKV( KeyValues *pKVItemLevel, const char *pszLevelBlockName, CUtlVector<CUtlString> *pVecErrors = NULL ); + + uint32 GetLevel( void ) const { return m_unLevel; } + uint32 GetRequiredScore( void ) const { return m_unRequiredScore; } + const char *GetNameLocalizationKey( void ) const { return m_pszLocalizedName_LocalStorage; } + +private: + uint32 m_unLevel; + uint32 m_unRequiredScore; + char *m_pszLocalizedName_LocalStorage; +}; + +//----------------------------------------------------------------------------- +// AchievementAward_t +// Holds the item to give away and the Data value to audit it with ( for cross +// game achievements) +//----------------------------------------------------------------------------- +struct AchievementAward_t +{ + AchievementAward_t( const AchievementAward_t & rhs ) + : m_sNativeName( rhs.m_sNativeName ), + m_unSourceAppId( rhs.m_unSourceAppId ), + m_unAuditData( rhs.m_unAuditData ) + { + m_vecDefIndex.CopyArray( rhs.m_vecDefIndex.Base(), rhs.m_vecDefIndex.Count() ); + } + AchievementAward_t( ) {} + + CUtlString m_sNativeName; + AppId_t m_unSourceAppId; + uint32 m_unAuditData; + CUtlVector<uint16> m_vecDefIndex; +}; + +enum eTimedRewardType +{ + kTimedRewards_RegularDrop, + kTimedRewards_SupplyCrate, + kTimedRewards_FreeTrialDrop, + kTimedRewards_RecipeDrop, + kTimedRewards_EventDrop02, + kNumTimedRewards +}; + +struct kill_eater_score_type_t +{ + const char *m_pszTypeString; + const char *m_pszLevelBlockName; + bool m_bAllowBotVictims; // if true, we don't check for a valid Steam ID on the client before sending or a valid session on the GC before incrementing +#ifdef GC_DLL + bool m_bGCUpdateOnly; + bool m_AllowIncrementValues; // if true, clients are allowed to send up the amount to increment by (ie., "did 100 damage") rather than implicitly assuming a value of 1 + bool m_bIsBaseKillType; // if true, when clients send up a notification of this type we'll also look for other relevant things on the GC, like whether the victim was a friend, etc. +#endif +}; + +// Index-to-string table, currently used for attribute value string lookups. +struct schema_string_table_entry_t +{ + int m_iIndex; + const char *m_pszStr; +}; + +//----------------------------------------------------------------------------- +// CForeignAppImports +// Defines the way a single foreign app's items are mapped into this app +//----------------------------------------------------------------------------- + +class CForeignAppImports +{ +public: + CForeignAppImports() : m_mapDefinitions( DefLessFunc( uint16 ) ) {} + + void AddMapping( uint16 unForeignDefIndex, const CEconItemDefinition *pDefn ); + const CEconItemDefinition *FindMapping( uint16 unForeignDefIndex ) const; + +private: + CUtlMap< uint16, const CEconItemDefinition *> m_mapDefinitions; +}; + +//----------------------------------------------------------------------------- +// ISchemaAttributeType +//----------------------------------------------------------------------------- +#ifdef GC_DLL +namespace GCSDK +{ + class CColumnSet; + class CRecordBase; + class CWebAPIValues; +}; +#endif // GC_DLL + +// ISchemaAttributeType is the base interface for a "type" of attribute, where "type" is defined as +// "something that describes the memory layout, the DB layout, how to convert between them, etc.". +// Most of the low-level work done with attributes, including DB reading/writing, packing/unpacking +// for wire traffic, and other leaf code works exclusively through this interface. +// +// The class hierarchy looks like: +// +// ISchemaAttributeTypeBase< TAttribInMemoryType >: +// +// This describes a specific in-memory format for an attribute, without any association to +// a particular DB, wire format, etc. We can't template the base class because it's an +// interface. This implements about half of ISchemaAttributeType and has its own mini +// interface consisting of ConvertTypedValueToByteStream() and ConvertByteStreamToTypedValue(), +// both of which do work on statically-typed values that don't exist at higher levels. +// +// CSchemaAttributeTypeBase< TAttribSchType, TAttribInMemoryType >: +// +// This handles the schema-related functions on ISchemaAttributeType. These exist at a lower +// inheritance level than ISchemaAttributeTypeBase to allow code that needs to work type-safely +// on attributes in memory, but that doesn't know or need to know anything about databases, +// to exist. Examples of this include code that calls CEconItem::SetDynamicAttributeValue<T>(). +// +// Individual implementations of custom attribute type start making sense immediately as +// subclasses of CSchemaAttributeTypeBase, for example CSchemaAttributeType_Default, which +// implements all of the old, untyped attribute system logic. +// +// CSchemaAttributeTypeProtobufBase< TAttribSchType, TProtobufValueType > +// +// An easy way of automating most of the work for making a new attribute type is to have +// the in-memory format be a protobuf object, allowing reflection, automatic network support, +// etc. +// +// Creating a new custom protobuf attribute consists of three steps: +// +// - create a new DB table that will hold your attribute data. This needs an itemid_t-sized item ID +// column named "ItemID", an attrib_definition_index_t-sized definition index column named "AttrDefIndex", +// and then whatever data you want to store. +// +// - create a new protobuf message type that will hold your custom attribute contents. This exists +// on the client and the GC in the same format. +// +// - implement a subclass of CSchemaAttributeTypeProtobufBase<>, for example: +// +// class CSchemaAttributeType_StrangeScore : public CSchemaAttributeTypeProtobufBase< GC_SCH_REFERENCE( CSchItemAttributeStrangeScore ) CAttribute_StrangeScore > +// { +// virtual void ConvertEconAttributeValueToSch( itemid_t unItemId, const CEconItemAttributeDefinition *pAttrDef, const union attribute_data_union_t& value, GCSDK::CRecordBase *out_pSchRecord ) const OVERRIDE; +// virtual void LoadSchToEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const GCSDK::CRecordBase *pSchRecord ) const OVERRIDE; +// }; +// +// Implement these two GC-only functions to convert from the in-memory format to the DB format and +// vice versa and you're good to go. +// +// - register the new type in CEconItemSchema::BInitAttributeTypes(). +// +// If the attribute type can't be silently converted to an already-existing attribute value type, a few other +// places will also fail to compile -- things like typed iteration, or compile-time type checking. +// +// Functions that start with "Convert" change the format of an attribute value (in a type-safe way wherever +// possible), copying the value from one of the passed-in parameters to the other. Functions that start with +// "Load" do a format conversion, but also add the post-conversion value to the passed-in CEconItem. This +// comes up most often when generating new items, either from the DB (LoadSch), the network (LoadByteSteam), +// or creation of a new item on the GC (LoadOrGenerate). +class ISchemaAttributeType +{ +public: + virtual ~ISchemaAttributeType() { } + + // Returns a unique integer describing the C++-in-memory-layout type used by this attribute type. + // For example, something that stores "int" might return 0 and "CSomeFancyWideAttributeType" might + // return 1. The actual values don't matter and can even differ between different runs of the game/GC. + // The only important thing is that during a single run the value for a single type is consistent. + virtual unsigned int GetTypeUniqueIdentifier() const = 0; + +#ifdef GC_DLL + // What's the whole column set (and associated DB table) that this attribute uses? Meant to be + // implemented by subclasses that have DB type information. + virtual const GCSDK::CColumnSet& GetFullColumnSet() const = 0; + + // Create an instance of a schema row. Mananging the memory is the responsibility of the caller. + // Meant to be implemented by subclasses that have DB type information. + virtual GCSDK::CRecordBase *CreateTypedSchRecord() const = 0; + + // ... + virtual bool BAssetClassExportedAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const attribute_data_union_t& value ) const { return true; } + + // Prepare a DB row describing an instance of this attribute for writing. + virtual void ConvertEconAttributeValueToSch( itemid_t unItemId, const CEconItemAttributeDefinition *pAttrDef, const union attribute_data_union_t& value, GCSDK::CRecordBase *out_pSchRecord ) const = 0; + + // We have a row read from the database and an item to add it as an attribute for. This + // does the opposite work of ConvertEconAttributeValueToSch() and also adds it to the CEconItem. + virtual void LoadSchToEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const GCSDK::CRecordBase *pSchRecord ) const = 0; + + // Have this attribute type either copy the data straight out of the value union, or run the logic + // described by pszCustomLogicDesc to generate a new value. Either way, some correctly-typed data + // will wind up in an attribute on the target item. This is intended to call through to LoadEconAttributeValue() + // to do the actual assignment. This is only accessible on the GC. + virtual void LoadOrGenerateEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const static_attrib_t& staticAttrib, const CEconGameAccount *pGameAccount ) const = 0; + + virtual void GenerateEconAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const static_attrib_t& staticAttrib, const CEconGameAccount *pGameAccount, attribute_data_union_t* out_pValue ) const = 0; +#endif // GC_DLL + + // Have this attribute type copy the data out of the value union and type-copy it onto the item. This + // is accessible on clients as well as the GC. + virtual void LoadEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const union attribute_data_union_t& value ) const = 0; + + // ... + virtual void ConvertEconAttributeValueToByteStream( const union attribute_data_union_t& value, std::string *out_psBytes ) const = 0; + + // ... + virtual bool BConvertStringToEconAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const char *pszValue, union attribute_data_union_t *out_pValue, bool bEnableTerribleBackwardsCompatibilitySchemaParsingCode = false ) const = 0; + + // ... + virtual void ConvertEconAttributeValueToString( const CEconItemAttributeDefinition *pAttrDef, const attribute_data_union_t& value, std::string *out_ps ) const = 0; + + // Used to deserialize a byte stream, probably from an on-wire protobuf message, instead an instance + // of the attribute in memory. See ConvertByteStreamToTypedValue() for example implementation, or + // ConvertTypedValueToByteStream() for an example of the byte-stream generator code. + virtual void LoadByteStreamToEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const std::string& sBytes ) const = 0; + + // Give the subclass a chance to default-initialize a new value. For larger types, this may hit the + // heap. This must be called before otherwise manipulating [out_pValue] through Convert*() functions. + virtual void InitializeNewEconAttributeValue( attribute_data_union_t *out_pValue ) const = 0; + + // Free any heap-allocated memory from this attribute value. Is not responsible for zeroing out + // pointers, etc. + virtual void UnloadEconAttributeValue( union attribute_data_union_t *out_pValue ) const = 0; + + // ... + virtual bool OnIterateAttributeValue( class IEconItemAttributeIterator *pIterator, const CEconItemAttributeDefinition *pAttrDef, const attribute_data_union_t& value ) const = 0; + + // This could also be called "BIsHackyMessyOldAttributeType()". This determines whether the attribute + // can be set at runtime on a CEconItemView instance, whether the gameserver can replicate the value to + // game clients, etc. It really only makes sense for value types 32 bits or smaller. + virtual bool BSupportsGameplayModificationAndNetworking() const { return false; } +}; + +//----------------------------------------------------------------------------- +// CEconItemSchema +// Defines the way econ items can be used in a game +//----------------------------------------------------------------------------- +typedef CUtlDict<CUtlConstString, int> ArmoryStringDict_t; +typedef CUtlDict< CUtlVector<CItemLevelingDefinition> * > LevelBlockDict_t; +typedef CUtlMap<unsigned int, kill_eater_score_type_t> KillEaterScoreMap_t; +typedef CUtlDict< CUtlVector< schema_string_table_entry_t > * > SchemaStringTableDict_t; + +struct attr_type_t +{ + CUtlConstString m_sName; + const ISchemaAttributeType *m_pAttrType; + + attr_type_t( const char *pszName, const ISchemaAttributeType *pAttrType ) + : m_sName( pszName ) + , m_pAttrType( pAttrType ) + { + } +}; + +#if defined(CLIENT_DLL) || defined(GAME_DLL) +class IDelayedSchemaData +{ +public: + virtual ~IDelayedSchemaData() {} + virtual bool InitializeSchema( CEconItemSchema *pItemSchema ) = 0; + +protected: + // Passing '0' as the expected version means "we weren't expecting any version in particular" and will + // skip the sanity checking. + bool InitializeSchemaInternal( CEconItemSchema *pItemSchema, CUtlBuffer& bufRawData, bool bInitAsBinary, uint32 nExpectedVersion ); +}; +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + +class CEconStorePriceSheet; + +class CEconItemSchema +{ +public: + CEconItemSchema( ); + +private: + CEconItemSchema( const CEconItemSchema & rhs ); + CEconItemSchema &operator=( CEconItemSchema & rhs ); + +public: + virtual ~CEconItemSchema( void ) { Reset(); }; + + // Setup & parse in the item data files. + virtual bool BInit( const char *fileName, const char *pathID, CUtlVector<CUtlString> *pVecErrors = NULL ); + bool BInitBinaryBuffer( CUtlBuffer &buffer, CUtlVector<CUtlString> *pVecErrors = NULL ); + bool BInitTextBuffer( CUtlBuffer &buffer, CUtlVector<CUtlString> *pVecErrors = NULL ); +#ifdef GC_DLL + virtual bool DoPostPriceSheetLoadInit( CEconStorePriceSheet *pPriceSheet ); // Called once the price sheet's been loaded +#endif + + uint32 GetVersion() const { return m_unVersion; } + CSHA GetSchemaSHA() const { return m_schemaSHA; } + uint32 GetResetCount() const { return m_unResetCount; } + + // Dump the schema for debug purposes + bool DumpItems ( const char *fileName, const char *pathID = NULL ); + + // Perform the computation used to calculate the schema version + static uint32 CalculateKeyValuesVersion( KeyValues *pKV ); + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + // This function will immediately reinitialize the schema if it's safe to do so, or store off the data + // if it isn't safe to update at the moment. + bool MaybeInitFromBuffer( IDelayedSchemaData *pDelayedSchemaData ); + + // If there is saved schema initialization data, initialize it now. If there is no saved data, this + // will return success. + bool BInitFromDelayedBuffer(); +#endif // defined(CLIENT_DLL) || defined(GAME_DLL) + + // Accessors to the base properties + EEquipType_t GetEquipTypeFromClassIndex( int iClass ) const; + equipped_class_t GetAccountIndex() const { return m_unAccoutClassIndex; } + equipped_class_t GetFirstValidClass() const { return m_unFirstValidClass; } + equipped_class_t GetLastValidClass() const { return m_unLastValidClass; } + bool IsValidClass( equipped_class_t unClass ) { return ( unClass >= m_unFirstValidClass && unClass <= m_unLastValidClass ) || unClass == GetAccountIndex(); } + bool IsValidItemSlot( equipped_slot_t unSlot, equipped_class_t unClass ) const { return IsValidItemSlot( unSlot, unClass == m_unAccoutClassIndex ? EQUIP_TYPE_ACCOUNT : EQUIP_TYPE_CLASS ); } + bool IsValidItemSlot( equipped_slot_t unSlot, EEquipType_t eType ) const + { + return eType == EQUIP_TYPE_ACCOUNT ? unSlot >= m_unFirstValidAccountItemSlot && unSlot <= m_unLastValidAccountItemSlot + : unSlot >= m_unFirstValidClassItemSlot && unSlot <= m_unLastValidClassItemSlot; + } + + enum { kMaxItemPresetCount = 4 }; + uint32 GetNumAllowedItemPresets() const { return kMaxItemPresetCount; } + bool IsValidPreset( equipped_preset_t unPreset ) const { return unPreset <= GetNumAllowedItemPresets(); } + + uint32 GetMinLevel() const { return m_unMinLevel; } + uint32 GetMaxLevel() const { return m_unMaxLevel; } + + // Accessors to the underlying sections + typedef CUtlHashMapLarge<int, CEconItemDefinition*> ItemDefinitionMap_t; + const ItemDefinitionMap_t &GetItemDefinitionMap() const { return m_mapItems; } + + typedef CUtlMap<int, CEconItemDefinition*, int> SortedItemDefinitionMap_t; + const SortedItemDefinitionMap_t &GetSortedItemDefinitionMap() const { return m_mapItemsSorted; } + + typedef CUtlMap<int, CEconItemDefinition*, int> ToolsItemDefinitionMap_t; + const ToolsItemDefinitionMap_t &GetToolsItemDefinitionMap() const { return m_mapToolsItems; } + + typedef CUtlMap<int, CEconItemDefinition*, int> BaseItemDefinitionMap_t; + const BaseItemDefinitionMap_t &GetBaseItemDefinitionMap() const { return m_mapBaseItems; } + + typedef CUtlMap<const char*, CEconLootListDefinition *, int> LootListDefinitionMap_t; + const LootListDefinitionMap_t &GetLootLists() const { return m_mapLootLists; } + + typedef CUtlMap<int, const char*> RevolvingLootListDefinitionMap_t; + const RevolvingLootListDefinitionMap_t &GetRevolvingLootLists() const { return m_mapRevolvingLootLists; } + + typedef CUtlMap<const char*, int> BodygroupStateMap_t; + const BodygroupStateMap_t &GetDefaultBodygroupStateMap() const { return m_mapDefaultBodygroupState; } + + typedef CUtlVector<CEconColorDefinition *> ColorDefinitionsList_t; + + typedef CUtlMap<const char *, KeyValues *, int> PrefabMap_t; + +#ifdef GC_DLL + struct periodic_score_t + { + eEconPeriodicScoreEvents m_eEventType; + bool m_bGCUpdateOnly; // if set, only code that runs on the GC can initiate a change of this stat (ie., counting gifts -> true; bots killed -> false) + uint32 m_unTimePeriodLengthInSeconds; + CEconItemDefinition *m_pRewardItemDefinition; + }; + + typedef CUtlVector<periodic_score_t> PeriodicScoreTypeList_t; +#endif // GC_DLL + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + CEconItemDefinition *GetDefaultItemDefinition() { return m_pDefaultItemDefinition; } + + bool SetupPreviewItemDefinition( KeyValues *pKV ); +#endif + + const CUtlMap<int, CEconItemQualityDefinition, int > &GetQualityDefinitionMap() const { return m_mapQualities; } + const CUtlMap<int, CEconItemAttributeDefinition, int > &GetAttributeDefinitionMap() const { return m_mapAttributes; } + + typedef CUtlMap<int, CEconCraftingRecipeDefinition*, int > RecipeDefinitionMap_t; + const RecipeDefinitionMap_t &GetRecipeDefinitionMap() const { return m_mapRecipes; } + + typedef CUtlMap<const char*, CEconItemSetDefinition*, int > ItemSetMap_t; + const ItemSetMap_t &GetItemSets() const { return m_mapItemSets; } + + typedef CUtlMap<const char*, CEconItemCollectionDefinition*, int > ItemCollectionMap_t; + const ItemCollectionMap_t &GetItemCollections() const { return m_mapItemCollections; } + + typedef CUtlVector< int > ItemCollectionCrateMap_t; + const ItemCollectionCrateMap_t &GetItemCollectionCrates() const { return m_vecItemCollectionCrates; } + + typedef CUtlMap<const char*, CEconItemPaintKitDefinition*, int > ItemPaintKitMap_t; + const ItemPaintKitMap_t &GetItemPaintKits() const { return m_mapItemPaintKits; } + + typedef CUtlMap<const char*, CEconOperationDefinition*, int > OperationDefinitionMap_t; + const OperationDefinitionMap_t &GetOperationDefinitions() const { return m_mapOperationDefinitions; } + + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + const ArmoryStringDict_t &GetArmoryDataItemClasses() const { return m_dictArmoryItemClassesDataStrings; } + const ArmoryStringDict_t &GetArmoryDataItemTypes() const { return m_dictArmoryItemTypesDataStrings; } + const ArmoryStringDict_t &GetArmoryDataItems() const { return m_dictArmoryItemDataStrings; } + const ArmoryStringDict_t &GetArmoryDataAttributes() const { return m_dictArmoryAttributeDataStrings; } +#elif defined(GC_DLL) + CUtlVector< CExperimentDefinition > &GetExperiments() { return m_vecExperiments; } + + const CUtlVector< AppId_t > & GetForeignApps() const { return m_vecForeignApps; } + const CEconItemDefinition *GetAppItemImport( AppId_t unAppID, uint16 usDefIndex ) const; +#endif + + const CTimedItemRewardDefinition* GetTimedReward( eTimedRewardType type ) const; + + const CEconLootListDefinition* GetLootListByName( const char* pListName, int *out_piIndex = NULL ) const; + const CEconLootListDefinition* GetLootListByIndex( int iIdx ) const { return m_mapLootLists.IsValidIndex(iIdx) ? m_mapLootLists[iIdx] : NULL; } + + const CQuestObjectiveDefinition* GetQuestObjectiveByDefIndex( int iIdx ) const; + const CUtlMap<int, CQuestObjectiveDefinition*, int >& GetQuestObjectives() const { return m_mapQuestObjectives; } + + uint8 GetDefaultQuality() const { return AE_UNIQUE; } + + void AssignDefaultBodygroupState( const char *pszBodygroupName, int iValue ); + + equip_region_mask_t GetEquipRegionMaskByName( const char *pRegionName ) const; + + struct EquipRegion + { + CUtlConstString m_sName; + unsigned int m_unBitIndex; // which bit are we claiming ownership over? there might be multiple equip regions with the same bit if we're in a "shared" block + equip_region_mask_t m_unMask; // full region conflict mask + }; + + typedef CUtlVector<EquipRegion> EquipRegionsList_t; + const EquipRegionsList_t& GetEquipRegionsList() const { return m_vecEquipRegionsList; } + + equip_region_mask_t GetEquipRegionBitMaskByName( const char *pRegionName ) const; + + KeyValues *FindDefinitionPrefabByName( const char *pszPrefabName ) const; + const PrefabMap_t& GetPrefabMap() const { return m_mapDefinitionPrefabs; } + + CUtlVector< CEconItemDefinition * > &GetBundles() { return m_vecBundles; } // Retrieve a cached list of all bundles + + const char *FindStringTableEntry( const char *pszTableName, int iIndex ) const; + +private: + void SetEquipRegionConflict( int iRegion, unsigned int unBit ); + int GetEquipRegionIndexByName( const char *pRegionName ) const; + +public: + // Common lookup methods + bool BGetItemQualityFromName( const char *pchName, uint8 *nQuality ) const; + const CEconItemQualityDefinition *GetQualityDefinition( int nQuality ) const; + const CEconItemQualityDefinition *GetQualityDefinitionByName( const char *pszDefName ) const; + + bool BGetItemRarityFromName( const char* pchName, uint8 *nRarity ) const; + const CEconItemRarityDefinition *GetRarityDefinitionByMapIndex( int nRarityIndex ) const; + const CEconItemRarityDefinition *GetRarityDefinition( int nRarity ) const; + const CEconItemRarityDefinition *GetRarityDefinitionByName( const char *pszDefName ) const; + virtual int GetRarityDefinitionCount( void ) const { return m_mapRarities.Count(); } + virtual const char* GetRarityName( uint8 iRarity ); + virtual const char* GetRarityLocKey( uint8 iRarity ); + virtual const char* GetRarityColor( uint8 iRarity ); + virtual int GetRarityIndex( const char* pszRarity ); + + const CEconItemCollectionDefinition *GetCollectionByName( const char* pCollectionName ); + + virtual int GetItemSeriesDefinitionCount( void ) const { return m_mapItemSeries.Count(); } + bool BGetItemSeries( const char* pchName, uint8 *nItemSeries ) const; + const CEconItemSeriesDefinition *GetItemSeriesDefinition( int nRarity ) const; + + CEconItemDefinition *GetItemDefinition( int iItemIndex ); + const CEconItemDefinition *GetItemDefinition( int iItemIndex ) const; + CEconItemAttributeDefinition *GetAttributeDefinition( int iAttribIndex ); + const CEconItemAttributeDefinition *GetAttributeDefinition( int iAttribIndex ) const; + CEconItemAttributeDefinition *GetAttributeDefinitionByName( const char *pszDefName ); + const CEconItemAttributeDefinition *GetAttributeDefinitionByName( const char *pszDefName ) const; + CEconCraftingRecipeDefinition *GetRecipeDefinition( int iRecipeIndex ); + CEconColorDefinition *GetColorDefinitionByName( const char *pszDefName ); + const CEconColorDefinition *GetColorDefinitionByName( const char *pszDefName ) const; +#ifdef CLIENT_DLL + const char *GetSteamPackageLocalizationToken( uint32 unPackageId ) const; +#endif // CLIENT_DLL + + bool BCanGSCreateItems( uint32 unIP ) const; +#ifdef GC_DLL + const AchievementAward_t *GetAchievementReward( const char *pchAchievementName, AppId_t unAppID ) const; + const AchievementAward_t *GetAchievementRewardByData( uint32 unData ) const; +#endif + const AchievementAward_t *GetAchievementRewardByDefIndex( uint16 usDefIndex ) const; + bool BHasAchievementRewards( void ) const { return (m_dictAchievementRewards.Count() > 0); } + + static CUtlString ComputeAchievementName( AppId_t unAppID, const char *pchNativeAchievementName ); + + // Iterating over the item definitions. Game needs this to precache data. + CEconItemDefinition *GetItemDefinitionByName( const char *pszDefName ); + const CEconItemDefinition *GetItemDefinitionByName( const char *pszDefName ) const; + +#ifdef GC_DLL + random_attrib_t *GetRandomAttributeTemplateByName( const char *pszAttrTemplateName ) const; +#endif // GC_DLL + + attachedparticlesystem_t* GetAttributeControlledParticleSystem( int id ); + attachedparticlesystem_t* FindAttributeControlledParticleSystem( const char *pchSystemName ); + typedef CUtlMap<int, attachedparticlesystem_t > ParticleDefinitionMap_t; + const ParticleDefinitionMap_t& GetAttributeControlledParticleSystems() const { return m_mapAttributeControlledParticleSystems; } + + const CUtlVector< int > *GetWeaponUnusualParticleIndexes() const { return &m_vecAttributeControlledParticleSystemsWeapons; } + const CUtlVector< int > *GetCosmeticUnusualParticleIndexes() const { return &m_vecAttributeControlledParticleSystemsCosmetics; } + const CUtlVector< int > *GetTauntUnusualParticleIndexes() const { return &m_vecAttributeControlledParticleSystemsTaunts; } + +#ifdef CLIENT_DLL + locchar_t *GetParticleSystemLocalizedName( int index ) const; +#endif // CLIENT_DLL + +#ifdef GC_DLL + const PeriodicScoreTypeList_t& GetPeriodicScoreTypeList() const { return m_vecPeriodicScoreTypes; } + + int GetPeriodicScoreTypeCount() const { return GetPeriodicScoreTypeList().Count(); } // how many types of events are we tracking? the range goes from 0 through this return value + const periodic_score_t& GetPeriodicScoreInfo( int iPeriodicScoreIndex ) const; // get the full info block for this periodic score -- event type, time period, etc. + + // Only intended to be used for generating data for the WebAPI. + const KillEaterScoreMap_t& GetKillEaterScoreTypes() const { return m_mapKillEaterScoreTypes; } + const SchemaStringTableDict_t& GetStringTables() const { return m_dictStringTable; } +#endif // GC_DLL + + item_definition_index_t GetCommunityMarketRemappedDefinitionIndex( item_definition_index_t unSearchItemDef ) const; + + const CUtlVector<attr_type_t>& GetAttributeTypes() const { return m_vecAttributeTypes; } + const ISchemaAttributeType *GetAttributeType( const char *pszAttrTypeName ) const; + + const LevelBlockDict_t& GetItemLevelingDataDict() const { return m_vecItemLevelingData; } + + const CUtlVector<CItemLevelingDefinition> *GetItemLevelingData( const char *pszLevelBlockName ) const + { + LevelBlockDict_t::IndexType_t i = m_vecItemLevelingData.Find( pszLevelBlockName ); + if ( i == LevelBlockDict_t::InvalidIndex() ) + return NULL; + + return m_vecItemLevelingData[i]; + } + + const CItemLevelingDefinition *GetItemLevelForScore( const char *pszLevelBlockName, uint32 unScore ) const; + const char *GetKillEaterScoreTypeLocString( uint32 unScoreType ) const; + const char *GetKillEaterScoreTypeLevelingDataName( uint32 unScoreType ) const; + bool GetKillEaterScoreTypeAllowsBotVictims( uint32 unScoreType ) const; +#ifdef GC_DLL + bool GetKillEaterScoreTypeGCOnlyUpdate( uint32 unScoreType ) const; + bool GetKillEaterScoreTypeAllowsIncrementValues( uint32 unScoreType ) const; +#endif + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + void ItemTesting_CreateTestDefinition( int iCloneFromItemDef, int iNewDef, KeyValues *pNewKV ); + void ItemTesting_DiscardTestDefinition( int iDef ); +#endif + +#ifdef DBGFLAG_VALIDATE + void Validate( CValidator &validator, const char *pchName ); +#endif // DBGFLAG_VALIDATE + + econ_tag_handle_t GetHandleForTag( const char *pszTagName ); // non-const because it may create a new tag handle + + typedef CUtlDict<econ_tag_handle_t> EconTagDict_t; +#ifdef GC_DLL + const EconTagDict_t& GetEconTagDict() const { return m_dictTags; } // meant for internal/debug use only, not for runtime iteration +#endif // GC_DLL + + virtual RTime32 GetCustomExpirationDate( const char *pszExpirationDate ) const { return k_RTime32Nil; } + +public: + // Subclass interface. + virtual CEconItemDefinition *CreateEconItemDefinition() { return new CEconItemDefinition; } + virtual CEconCraftingRecipeDefinition *CreateCraftingRecipeDefinition() { return new CEconCraftingRecipeDefinition; } + virtual CEconStyleInfo *CreateEconStyleInfo() { return new CEconStyleInfo; } + virtual CQuestObjectiveDefinition *CreateQuestDefinition() { return new CQuestObjectiveDefinition; } + + virtual IEconTool *CreateEconToolImpl( const char *pszToolType, const char *pszUseString, const char *pszUsageRestriction, item_capabilities_t unCapabilities, KeyValues *pUsageKV ); + +#ifdef GC_DLL + virtual random_attrib_t *CreateRandomAttribute( const char *pszContext, KeyValues *pRandomAttributesKV, CUtlVector<CUtlString> *pVecErrors = NULL ); +#endif // GC_DLL + + virtual bool BCanStrangeFilterApplyToStrangeSlotInItem( uint32 /*strange_event_restriction_t*/ unRestrictionType, uint32 unRestrictionValue, const IEconItemInterface *pItem, int iStrangeSlot, uint32 *out_pOptionalScoreType ) const; + bool AddQuestObjective( const CQuestObjectiveDefinition **ppQuestObjective, KeyValues *pKVObjective, CUtlVector<CUtlString> *pVecErrors ); + + bool BInsertLootlist( const char *pListName, KeyValues *pKVLootList, CUtlVector<CUtlString> *pVecErrors ); + +#ifdef GC_DLL + void PerformCaseBehaviorCheck(); +#endif +protected: + virtual void Reset( void ); + + virtual bool BInitSchema( KeyValues *pKVRawDefinition, CUtlVector<CUtlString> *pVecErrors = NULL ); +#ifdef TF_CLIENT_DLL + virtual int CalculateNumberOfConcreteItems( const CEconItemDefinition *pItemDef ); // Let derived classes handle custom item types +#endif // TF_CLIENT_DLL + +private: + bool BInitGameInfo( KeyValues *pKVGameInfo, CUtlVector<CUtlString> *pVecErrors ); + bool BInitAttributeTypes( CUtlVector<CUtlString> *pVecErrors ); +#ifdef GC_DLL + bool BInitPeriodicScoring( KeyValues *pKVGameInfo, CUtlVector<CUtlString> *pVecErrors ); +#endif // GC_DLL + bool BInitDefinitionPrefabs( KeyValues *pKVPrefabs, CUtlVector<CUtlString> *pVecErrors ); + bool BInitItemSeries( KeyValues *pKVSeries, CUtlVector<CUtlString> *pVecErrors ); + bool BVerifyBaseItemNames( CUtlVector<CUtlString> *pVecErrors ); + bool BInitRarities( KeyValues *pKVRarities, KeyValues *pKVRarityWeights, CUtlVector<CUtlString> *pVecErrors ); + bool BInitQualities( KeyValues *pKVAttributes, CUtlVector<CUtlString> *pVecErrors ); + bool BInitColors( KeyValues *pKVColors, CUtlVector<CUtlString> *pVecErrors ); + bool BInitAttributes( KeyValues *pKVAttributes, CUtlVector<CUtlString> *pVecErrors ); + bool BInitEquipRegions( KeyValues *pKVEquipRegions, CUtlVector<CUtlString> *pVecErrors ); + bool BInitEquipRegionConflicts( KeyValues *pKVEquipRegions, CUtlVector<CUtlString> *pVecErrors ); + bool BInitItems( KeyValues *pKVAttributes, CUtlVector<CUtlString> *pVecErrors ); + bool BInitItemSets( KeyValues *pKVItemSets, CUtlVector<CUtlString> *pVecErrors ); + bool BInitTimedRewards( KeyValues *pKVTimeRewards, CUtlVector<CUtlString> *pVecErrors ); + bool BInitAchievementRewards( KeyValues *pKVTimeRewards, CUtlVector<CUtlString> *pVecErrors ); +#ifdef GC_DLL + bool BInitRandomAttributeTemplates( KeyValues *pKVRandomAttributeTemplates, CUtlVector<CUtlString> *pVecErrors ); +#endif // GC_DLL + bool BInitRecipes( KeyValues *pKVRecipes, CUtlVector<CUtlString> *pVecErrors ); + bool BInitLootLists( KeyValues *pKVLootLists, CUtlVector<CUtlString> *pVecErrors ); + bool BInitRevolvingLootLists( KeyValues *pKVRevolvingLootLists, CUtlVector<CUtlString> *pVecErrors ); + bool BInitItemCollections( KeyValues *pKVItemSets, CUtlVector<CUtlString> *pVecErrors ); + bool BInitCollectionReferences( CUtlVector<CUtlString> *pVecErrors ); + bool BInitItemPaintKitDefinitions( KeyValues *pKVPaintKits, CUtlVector<CUtlString> *pVecErrors ); + bool BInitOperationDefinitions( KeyValues *pKVGameInfo, KeyValues *pOperations, CUtlVector<CUtlString> *pVecErrors ); + +#ifdef TF_CLIENT_DLL + bool BInitConcreteItemCounts( CUtlVector<CUtlString> *pVecErrors ); + bool BInitSteamPackageLocalizationToken( KeyValues *pKVSteamPackages, CUtlVector<CUtlString> *pVecErrors ); +#endif // TF_CLIENT_DLL + bool BInitItemLevels( KeyValues *pKVItemLevels, CUtlVector<CUtlString> *pVecErrors ); + bool BInitKillEaterScoreTypes( KeyValues *pKVItemLevels, CUtlVector<CUtlString> *pVecErrors ); + bool BInitStringTables( KeyValues *pKVStringTables, CUtlVector<CUtlString> *pVecErrors ); + bool BInitCommunityMarketRemaps( KeyValues *pKVCommunityMarketRemaps, CUtlVector<CUtlString> *pVecErrors ); + + bool BPostSchemaInit( CUtlVector<CUtlString> *pVecErrors ) const; + bool BInitAttributeControlledParticleSystems( KeyValues *pKVParticleSystems, CUtlVector<CUtlString> *pVecErrors ); + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + bool BInitArmoryData( KeyValues *pKVArmoryData, CUtlVector<CUtlString> *pVecErrors ); +#else + bool BInitExperiements( KeyValues *pKVExperiments, CUtlVector<CUtlString> *pVecErrors ); + bool BInitForeignImports( CUtlVector<CUtlString> *pVecErrors ); + + CForeignAppImports *FindOrAddAppImports( AppId_t unAppID ); +#endif + + bool BVerifyLootListItemDropDates( const CEconLootListDefinition* pLootList, CUtlVector<CUtlString> *pVecErrors ) const; + bool BRecurseiveVerifyLootListItemDropDates( const CEconLootListDefinition* pLootList, const CEconLootListDefinition* pRootLootList, CUtlVector<CUtlString> *pVecErrors ) const; + + // Note: this returns pointers to the inside of a vector and/or NULL. Pointers are not intended to be + // saved off and used later. + const kill_eater_score_type_t *FindKillEaterScoreType( uint32 unScoreType ) const; + + uint32 m_unResetCount; + + KeyValues *m_pKVRawDefinition; + uint32 m_unVersion; + CSHA m_schemaSHA; + + // Class range + equipped_class_t m_unFirstValidClass; + equipped_class_t m_unLastValidClass; + equipped_class_t m_unAccoutClassIndex; + + // Item slot range + equipped_slot_t m_unFirstValidClassItemSlot; + equipped_slot_t m_unLastValidClassItemSlot; + equipped_slot_t m_unFirstValidAccountItemSlot; + equipped_slot_t m_unLastValidAccountItemSlot; + + // Number of allowed presets + uint32 m_unNumItemPresets; + + // Allowable range of item levels for this app + uint32 m_unMinLevel; + uint32 m_unMaxLevel; + + // Total value of all the weights of the qualities + uint32 m_unSumQualityWeights; + + // Name-to-implementation list of all unique attribute types (ie., "wide strange score"). + CUtlVector<attr_type_t> m_vecAttributeTypes; + + // Contains the list of rarity definitions + CUtlMap<int, CEconItemSeriesDefinition, int > m_mapItemSeries; + + // Contains the list of rarity definitions + CUtlMap<int, CEconItemRarityDefinition, int > m_mapRarities; + + // Contains the list of item definitions read in from all data files. + CUtlMap<int, CEconItemQualityDefinition, int > m_mapQualities; + + // Contains the list of item definitions read in from all data files. + ItemDefinitionMap_t m_mapItems; + + CUtlMap<int, CQuestObjectiveDefinition*, int > m_mapQuestObjectives; + + // A sorted version of the same map, for instances where we really want sorted data + SortedItemDefinitionMap_t m_mapItemsSorted; + + // List of all the tool items, is a sublist of mapItems + ToolsItemDefinitionMap_t m_mapToolsItems; + + // List of all base items, is a sublist of mapItems + BaseItemDefinitionMap_t m_mapBaseItems; + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + // What is the default item definition we'll return in the client code if we can't find the correct one? + CEconItemDefinition *m_pDefaultItemDefinition; +#endif + + // Contains the list of attribute definitions read in from all data files. + CUtlMap<int, CEconItemAttributeDefinition, int > m_mapAttributes; + + // Contains the list of item recipes read in from all data files. + RecipeDefinitionMap_t m_mapRecipes; + + // Contains the list of item sets. + ItemSetMap_t m_mapItemSets; + ItemCollectionMap_t m_mapItemCollections; + ItemCollectionCrateMap_t m_vecItemCollectionCrates; + + OperationDefinitionMap_t m_mapOperationDefinitions; + + // Paint Kit defintions + ItemPaintKitMap_t m_mapItemPaintKits; + + // Revolving loot lists. + CUtlMap<int, const char*> m_mapRevolvingLootLists; + + // Contains the list of loot lists. + LootListDefinitionMap_t m_mapLootLists; + + // List of events that award items based on time played + CUtlVector<CTimedItemRewardDefinition> m_vecTimedRewards; + + // list of items that will be awarded from achievements + CUtlDict< AchievementAward_t *, int > m_dictAchievementRewards; + CUtlMap< uint32, AchievementAward_t * > m_mapAchievementRewardsByData; + +#ifdef GC_DLL + // list of random attribute templates + CUtlDict< random_attrib_t * > m_dictRandomAttributeTemplates; +#endif // GC_DLL + + // Contains information for attribute attached particle systems + CUtlMap<int, attachedparticlesystem_t > m_mapAttributeControlledParticleSystems; + CUtlVector< int > m_vecAttributeControlledParticleSystemsCosmetics; + CUtlVector< int > m_vecAttributeControlledParticleSystemsWeapons; + CUtlVector< int > m_vecAttributeControlledParticleSystemsTaunts; + + + // Contains information on which equip regions conflict with each other regions and how to + // test for overlap. + EquipRegionsList_t m_vecEquipRegionsList; + + // Contains information about prefab KeyValues blocks that be can referenced elsewhere + // in the schema. + PrefabMap_t m_mapDefinitionPrefabs; + + // Contains runtime color information, looked-up by name. + ColorDefinitionsList_t m_vecColorDefs; + + // Contains information about: a) every bodygroup that appears anywhere in the schema, and + // b) whether they default to on or off. + BodygroupStateMap_t m_mapDefaultBodygroupState; + + // Various definitions can have any number of unique tags associated with them. + EconTagDict_t m_dictTags; + +#ifdef GC_DLL + // Information about our periodic score accumulators. + PeriodicScoreTypeList_t m_vecPeriodicScoreTypes; +#endif // GC_DLL + + // List of item leveling data. + KillEaterScoreMap_t m_mapKillEaterScoreTypes; + + SchemaStringTableDict_t m_dictStringTable; + + typedef CUtlMap< item_definition_index_t, item_definition_index_t, item_definition_index_t > CommunityMarketDefinitionRemapMap_t; + CommunityMarketDefinitionRemapMap_t m_mapCommunityMarketDefinitionIndexRemap; + +#ifdef CLIENT_DLL + // Steam-package-ID-to-localization-token map, used for modifying tooltips in the store. + typedef CUtlMap< uint32, const char * > SteamPackageLocalizationTokenMap_t; + SteamPackageLocalizationTokenMap_t m_mapSteamPackageLocalizationTokens; +#endif // CLIENT_DLL + + LevelBlockDict_t m_vecItemLevelingData; + +#if defined(CLIENT_DLL) || defined(GAME_DLL) + // Contains Armory data key->localization string mappings + ArmoryStringDict_t m_dictArmoryItemTypesDataStrings; + ArmoryStringDict_t m_dictArmoryItemClassesDataStrings; + ArmoryStringDict_t m_dictArmoryAttributeDataStrings; + ArmoryStringDict_t m_dictArmoryItemDataStrings; + + // Used for delaying the parsing of the item schema until its safe to swap out the back end data. + IDelayedSchemaData *m_pDelayedSchemaData; +#elif defined(GC_DLL) + // GC only + CUtlVector< CExperimentDefinition > m_vecExperiments; + CUtlMap< AppId_t, CForeignAppImports *> m_mapForeignImports; + CUtlVector< AppId_t > m_vecForeignApps; +#endif + + CUtlVector< CEconItemDefinition * > m_vecBundles; // A cached list of all bundles +}; + +#ifdef GC_DLL + void PerformIncrementKillEaterAttributeScore( CEconUserSession *pLockedOwnerSession, CEconItem *pItem, uint32 unEventType, uint32 unIncrementCount, bool bGCOrigination, GCSDK::CSharedObjectTransactionEx *pTransaction ); +#endif // GC_DLL + +extern CEconItemSchema & GEconItemSchema(); + +//----------------------------------------------------------------------------- +// CSchemaFieldHandle +//----------------------------------------------------------------------------- +template < class T > +class CSchemaFieldHandle +{ +public: + explicit CSchemaFieldHandle( const char *szName ) + : m_szName( szName ) + { + m_pRef = GetTypedRef(); + m_unSchemaGeneration = GEconItemSchema().GetResetCount(); +#if _DEBUG + m_unVersion_Debug = GEconItemSchema().GetVersion(); +#endif + } + + operator const T *( void ) const + { + uint32 unSchemaGeneration = GEconItemSchema().GetResetCount(); + if ( m_unSchemaGeneration != unSchemaGeneration ) + { + m_pRef = GetTypedRef(); + m_unSchemaGeneration = unSchemaGeneration; +#if _DEBUG + m_unVersion_Debug = GEconItemSchema().GetVersion(); +#endif + } + +#if _DEBUG + Assert( m_unVersion_Debug == GEconItemSchema().GetVersion() ); +#endif + return m_pRef; + } + + const T *operator->( void ) const + { + return static_cast<const T *>( *this ); + } + + const char *GetName( void ) const + { + return m_szName; + } + +private: + const T *GetTypedRef() const; + +private: + const char *m_szName; + + mutable const T *m_pRef; + mutable uint32 m_unSchemaGeneration; +#if _DEBUG + mutable uint32 m_unVersion_Debug; +#endif +}; + +template < > +inline const CEconColorDefinition *CSchemaFieldHandle<CEconColorDefinition>::GetTypedRef( void ) const +{ + return GEconItemSchema().GetColorDefinitionByName( m_szName ); +} + +template < > +inline const CEconItemAttributeDefinition *CSchemaFieldHandle<CEconItemAttributeDefinition>::GetTypedRef( void ) const +{ + return GEconItemSchema().GetAttributeDefinitionByName( m_szName ); +} + +template < > +inline const CEconItemDefinition *CSchemaFieldHandle<CEconItemDefinition>::GetTypedRef( void ) const +{ + return GEconItemSchema().GetItemDefinitionByName( m_szName ); +} + +template < > +inline const CEconLootListDefinition *CSchemaFieldHandle<CEconLootListDefinition>::GetTypedRef( void ) const +{ + return GEconItemSchema().GetLootListByName( m_szName ); +} + +template < > +inline const attachedparticlesystem_t *CSchemaFieldHandle<attachedparticlesystem_t>::GetTypedRef( void ) const +{ + return GEconItemSchema().FindAttributeControlledParticleSystem( m_szName ); +} + +typedef CSchemaFieldHandle<CEconColorDefinition> CSchemaColorDefHandle; +typedef CSchemaFieldHandle<CEconItemAttributeDefinition> CSchemaAttributeDefHandle; +typedef CSchemaFieldHandle<CEconItemDefinition> CSchemaItemDefHandle; +typedef CSchemaFieldHandle<CEconLootListDefinition> CSchemaLootListDefHandle; +typedef CSchemaFieldHandle<attachedparticlesystem_t> CSchemaParticleHandle; + + +struct steam_market_gc_identifier_t +{ + item_definition_index_t m_unDefIndex; + uint8 m_unQuality; + + bool operator<( const struct steam_market_gc_identifier_t& b ) const + { + return (m_unDefIndex < b.m_unDefIndex) + || ((m_unDefIndex == b.m_unDefIndex) && (m_unQuality < b.m_unQuality)); + } +}; + +// Implementation reliant on earlier class content. +inline const CEconItemAttributeDefinition *static_attrib_t::GetAttributeDefinition() const +{ + return GEconItemSchema().GetAttributeDefinition( iDefIndex ); +} + +inline const ISchemaAttributeType *static_attrib_t::GetAttributeType() const +{ + const CEconItemAttributeDefinition *pAttrDef = GetAttributeDefinition(); + if ( !pAttrDef ) + return NULL; + + return pAttrDef->GetAttributeType(); +} + +// Utility function to convert datafile strings to ints. +int StringFieldToInt( const char *szValue, const char **pValueStrings, int iNumStrings, bool bDontAssert = false ); +int StringFieldToInt( const char *szValue, const CUtlVector<const char *>& vecValueStrings, bool bDontAssert = false ); + +#ifdef GC_DLL +// Global econ-level helper functionality. +EUniverse GetUniverse(); + +bool BYieldingGetChangedItemDefinitions( int iComparisonColumn, CUtlVector<item_definition_index_t>& out_vecChangedDefIndices ); +bool BYieldingUpdateItemDefinitionStateHashValue( GCSDK::CSQLAccess& sqlAccess, item_definition_index_t unItemDef, int iUpdatedColumn ); +#endif // GC_DLL + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CAttributeLineItemLootList : public IEconLootList +{ +public: + static CSchemaAttributeDefHandle s_pAttrDef_RandomDropLineItems[4]; +#ifdef GC_DLL + static CSchemaAttributeDefHandle s_pAttrDef_RandomDropLineItemUnusualChance; + static CSchemaAttributeDefHandle s_pAttrDef_RandomDropLineItemUnusualList; +#endif // GC_DLL + static CSchemaAttributeDefHandle s_pAttrDef_RandomDropLineItemFooterDesc; + +public: + CAttributeLineItemLootList( const IEconItemInterface *pEconItem ) + : m_pEconItem( pEconItem ) + { + // + } + + virtual void EnumerateUserFacingPotentialDrops( IEconLootListIterator *pIt ) const OVERRIDE; + virtual bool BPublicListContents() const OVERRIDE { return true; } // any attribute data that clients have is public to them + virtual const char *GetLootListHeaderLocalizationKey() const OVERRIDE; + virtual const char *GetLootListFooterLocalizationKey() const OVERRIDE; + virtual const char *GetLootListCollectionReference() const OVERRIDE; + +#ifdef GC_DLL + MUST_CHECK_RETURN virtual bool BGenerateSingleRollRandomItems( const CEconGameAccount *pGameAccount, bool bFreeAccount, CUtlVector<CEconItem *> *out_pvecItems, const CUtlVector< item_definition_index_t > *pVecAvoidItemDefs = NULL ) const OVERRIDE; +#endif // GC_DLL + +private: + const IEconItemInterface *m_pEconItem; +}; + +void MergeDefinitionPrefab( KeyValues *pKVWriteItem, KeyValues *pKVSourceItem ); + +#endif //ECONITEMSCHEMA_H |