summaryrefslogtreecommitdiff
path: root/game/shared/econ/econ_item_constants.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/econ/econ_item_constants.cpp')
-rw-r--r--game/shared/econ/econ_item_constants.cpp970
1 files changed, 970 insertions, 0 deletions
diff --git a/game/shared/econ/econ_item_constants.cpp b/game/shared/econ/econ_item_constants.cpp
new file mode 100644
index 0000000..ffb7784
--- /dev/null
+++ b/game/shared/econ/econ_item_constants.cpp
@@ -0,0 +1,970 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Holds constants for the econ item system
+//
+//=============================================================================
+
+#include "cbase.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *g_szQualityStrings[] =
+{
+ "Normal",
+ "rarity1", // Genuine
+ "rarity2", // Customized
+ "vintage", // Vintage has to stay at 3 for backwards compatibility
+ "rarity3", // Well-Designed
+ "rarity4", // Unusual
+ "Unique",
+ "community",
+ "developer",
+ "selfmade",
+ "customized",
+ "strange",
+ "completed",
+ "haunted",
+ "collectors",
+ "paintkitWeapon",
+
+ "default", // AE_RARITY_DEFAULT,
+ "common", // AE_RARITY_COMMON,
+ "uncommon", // AE_RARITY_UNCOMMON,
+ "rare", // AE_RARITY_RARE,
+ "mythical", // AE_RARITY_MYTHICAL,
+ "legendary", // AE_RARITY_LEGENDARY,
+ "ancient", // AE_RARITY_ANCIENT,
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityStrings ) == AE_MAX_TYPES );
+
+const char *EconQuality_GetQualityString( EEconItemQuality eQuality )
+{
+ // This is a runtime check and not an assert because we could theoretically bounce the GC with new
+ // qualities while the client is running.
+ if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
+ return g_szQualityStrings[ eQuality ];
+
+ return NULL;
+}
+
+EEconItemQuality EconQuality_GetQualityFromString( const char* pszQuality )
+{
+ // Convert to lowercase
+ CUtlString strLoweredInput( pszQuality );
+ strLoweredInput.ToLower();
+
+ // Guaranteed with the compile time assert above that AE_MAX_TYPES is
+ // the size of the string qualities
+ for( int i = 0; i < AE_MAX_TYPES; ++i )
+ {
+ // Convert to lowercase
+ CUtlString strLoweredQuality( g_szQualityStrings[i] );
+ strLoweredQuality.ToLower();
+
+ if( !Q_stricmp( strLoweredInput.Get(), strLoweredQuality.Get() ) )
+ return EEconItemQuality(i);
+ }
+
+ return AE_UNDEFINED;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *g_szQualityColorStrings[] =
+{
+ "QualityColorNormal",
+ "QualityColorrarity1",
+ "QualityColorrarity2",
+ "QualityColorVintage",
+ "QualityColorrarity3",
+ "QualityColorrarity4", // AE_UNUSUAL
+ "QualityColorUnique",
+ "QualityColorCommunity",
+ "QualityColorDeveloper",
+ "QualityColorSelfMade",
+ "QualityColorSelfMadeCustomized",
+ "QualityColorStrange",
+ "QualityColorCompleted",
+ "QualityColorHaunted", // AE_HAUNTED
+ "QualityColorCollectors", // AE_COLLECTORS
+ "QualityColorPaintkitWeapon", // AE_PAINTKITWEAPON
+
+ "ItemRarityDefault" , // AE_RARITY_DEFAULT,
+ "ItemRarityCommon" , // AE_RARITY_COMMON,
+ "ItemRarityUncommon" , // AE_RARITY_UNCOMMON,
+ "ItemRarityRare" , // AE_RARITY_RARE,
+ "ItemRarityMythical" , // AE_RARITY_MYTHICAL,
+ "ItemRarityLegendary" , // AE_RARITY_LEGENDARY,
+ "ItemRarityAncient" , // AE_RARITY_ANCIENT,
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityColorStrings ) == AE_MAX_TYPES );
+
+const char *EconQuality_GetColorString( EEconItemQuality eQuality )
+{
+ if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
+ return g_szQualityColorStrings[ eQuality ];
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *g_szQualityLocalizationStrings[] =
+{
+ "#Normal",
+ "#rarity1", // Genuine
+ "#rarity2",
+ "#vintage",
+ "#rarity3", // Artisan
+ "#rarity4", // Unusual
+ "#unique",
+ "#community",
+ "#developer",
+ "#selfmade",
+ "#customized",
+ "#strange",
+ "#completed",
+ "#haunted",
+ "#collectors",
+ "#paintkitWeapon",
+
+ "#Rarity_Default",
+ "#Rarity_Common",
+ "#Rarity_Uncommon",
+ "#Rarity_Rare",
+ "#Rarity_Mythical",
+ "#Rarity_Legendary",
+ "#Rarity_Ancient"
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityLocalizationStrings ) == AE_MAX_TYPES );
+
+const char *EconQuality_GetLocalizationString( EEconItemQuality eQuality )
+{
+ if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
+ return g_szQualityLocalizationStrings[ eQuality ];
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sort order for rarities
+// Small Numbers sort to front
+//-----------------------------------------------------------------------------
+int g_nRarityScores[] =
+{
+ 15, // AE_NORMAL,
+ 10, // AE_RARITY1, // Geniune
+ 102, // AE_RARITY2, // Customized (unused)
+ 11, // AE_VINTAGE,
+ 101, // AE_RARITY3, // Artisan (unused)
+ 0, // AE_UNUSUAL,
+ 14, // AE_UNIQUE,
+ -1, // AE_COMMUNITY,
+ -3, // AE_DEVELOPER,
+ -2, // AE_SELFMADE,
+ 100, // AE_CUSTOMIZED, // Unused
+ 9, // AE_STRANGE,
+ 103, // AE_COMPLETED, // Unused
+ 13, // AE_HAUNTED
+ 12, // AE_COLLECTORS
+ 8, // AE_PAINTKITWEAPON
+ 7, // AE_RARITY_DEFAULT,
+ 6, // AE_RARITY_COMMON,
+ 5, // AE_RARITY_UNCOMMON,
+ 4, // AE_RARITY_RARE,
+ 3, // AE_RARITY_MYTHICAL,
+ 2, // AE_RARITY_LEGENDARY,
+ 1, // AE_RARITY_ANCIENT,
+};
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_nRarityScores ) == AE_MAX_TYPES );
+
+//-----------------------------------------------------------------------------
+int EconQuality_GetRarityScore( EEconItemQuality eQuality )
+{
+ if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
+ return g_nRarityScores[ eQuality ];
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+const char *g_pchWearAmountStrings[] =
+{
+ "#TFUI_InvTooltip_None",
+ "#TFUI_InvTooltip_FactoryNew",
+ "#TFUI_InvTooltip_MinimalWear",
+ "#TFUI_InvTooltip_FieldTested",
+ "#TFUI_InvTooltip_WellWorn",
+ "#TFUI_InvTooltip_BattleScared"
+};
+
+//-----------------------------------------------------------------------------
+int EconWear_ToIntCategory( float flWear )
+{
+ if ( flWear <= 0.2f )
+ {
+ return 1;
+ }
+ else if ( flWear <= 0.4f )
+ {
+ return 2;
+ }
+ else if ( flWear <= 0.6f )
+ {
+ return 3;
+ }
+ else if ( flWear <= 0.8f )
+ {
+ return 4;
+ }
+ else if ( flWear <= 1.0f )
+ {
+ return 5;
+ }
+
+ return 3; // default wear
+}
+
+// -------------------------------------------------------------------------
+// Shim to return a value for buckets. For strange we bucket all of them in to 1 non-instance data group
+int EconStrange_ToStrangeBucket( float value )
+{
+ return 0;
+}
+float EconStrange_FromStrangeBucket( int value )
+{
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+const char *GetWearLocalizationString( float flWear )
+{
+ int nIndex = EconWear_ToIntCategory( flWear );
+ return g_pchWearAmountStrings[ nIndex ];
+}
+//-----------------------------------------------------------------------------
+bool EconWear_IsValidValue( int nWear )
+{
+ return nWear > 0 && nWear <= 5;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CSchemaColorDefHandle g_AttribColorDefs[] =
+{
+ CSchemaColorDefHandle( "desc_level" ), // ATTRIB_COL_LEVEL
+ CSchemaColorDefHandle( "desc_attrib_neutral" ), // ATTRIB_COL_NEUTRAL
+ CSchemaColorDefHandle( "desc_attrib_positive" ), // ATTRIB_COL_POSITIVE
+ CSchemaColorDefHandle( "desc_attrib_negative" ), // ATTRIB_COL_NEGATIVE
+ CSchemaColorDefHandle( "desc_itemset_name" ), // ATTRIB_COL_ITEMSET_NAME
+ CSchemaColorDefHandle( "desc_itemset_equipped" ), // ATTRIB_COL_ITEMSET_EQUIPPED
+ CSchemaColorDefHandle( "desc_itemset_missing" ), // ATTRIB_COL_ITEMSET_MISSING
+ CSchemaColorDefHandle( "desc_bundle" ), // ATTRIB_COL_BUNDLE_ITEM
+ CSchemaColorDefHandle( "desc_limited_use" ), // ATTRIB_COL_LIMITED_USE
+ CSchemaColorDefHandle( "desc_flags" ), // ATTRIB_COL_component_flags
+ CSchemaColorDefHandle( "desc_limited_quantity" ), // ATTRIB_COL_LIMITED_QUANTITY
+
+ CSchemaColorDefHandle( "desc_default" ), // ATTRIB_COL_RARITY_DEFAULT
+ CSchemaColorDefHandle( "desc_common" ), // ATTRIB_COL_RARITY_COMMON
+ CSchemaColorDefHandle( "desc_uncommon" ), // ATTRIB_COL_RARITY_UNCOMMON
+ CSchemaColorDefHandle( "desc_rare" ), // ATTRIB_COL_RARITY_RARE
+ CSchemaColorDefHandle( "desc_mythical" ), // ATTRIB_COL_RARITY_MYTHICAL
+ CSchemaColorDefHandle( "desc_legendary" ), // ATTRIB_COL_RARITY_LEGENDARY
+ CSchemaColorDefHandle( "desc_ancient" ), // ATTRIB_COL_RARITY_ANCIENT
+ CSchemaColorDefHandle( "desc_immortal" ), // ATTRIB_COL_RARITY_IMMORTAL
+ CSchemaColorDefHandle( "desc_arcana" ), // ATTRIB_COL_RARITY_ARCANA
+
+ CSchemaColorDefHandle( "desc_strange" ), // ATTRIB_COL_STRANGE
+ CSchemaColorDefHandle( "desc_unusual" ), // ATTRIB_COL_UNUSUAL
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_AttribColorDefs ) == NUM_ATTRIB_COLORS );
+
+attrib_colors_t GetAttribColorIndexForName( const char* pszName )
+{
+ for ( int i = 0; i < NUM_ATTRIB_COLORS; ++i )
+ {
+ if ( !Q_strcmp( g_AttribColorDefs[i].GetName(), pszName ) )
+ return (attrib_colors_t)i;
+ }
+
+ return (attrib_colors_t)0;
+}
+
+const char *GetColorNameForAttribColor( attrib_colors_t unAttribColor )
+{
+ Assert( unAttribColor >= 0 );
+ Assert( unAttribColor < NUM_ATTRIB_COLORS );
+
+ return g_AttribColorDefs[unAttribColor]
+ ? g_AttribColorDefs[unAttribColor]->GetColorName()
+ : "ItemAttribNeutral";
+}
+
+const char *GetHexColorForAttribColor( attrib_colors_t unAttribColor )
+{
+ Assert( unAttribColor >= 0 );
+ Assert( unAttribColor < NUM_ATTRIB_COLORS );
+
+ return g_AttribColorDefs[unAttribColor]
+ ? g_AttribColorDefs[unAttribColor]->GetHexColor()
+ : "#ebe2ca";
+}
+
+entityquality_t GetItemQualityFromString( const char *sQuality )
+{
+ for ( int i = 0; i < AE_MAX_TYPES; i++ )
+ {
+ if ( !Q_strnicmp( sQuality, g_szQualityStrings[i], 16 ) )
+ return (entityquality_t)i;
+ }
+
+ return AE_NORMAL;
+}
+
+const char *g_szRecipeCategoryStrings[] =
+{
+ "crafting", // RECIPE_CATEGORY_CRAFTINGITEMS = 0,
+ "commonitem", // RECIPE_CATEGORY_COMMONITEMS,
+ "rareitem", // RECIPE_CATEGORY_RAREITEMS,
+ "special", // RECIPE_CATEGORY_SPECIAL,
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_szRecipeCategoryStrings ) == NUM_RECIPE_CATEGORIES );
+
+//-----------------------------------------------------------------------------
+// Item acquisition.
+//-----------------------------------------------------------------------------
+// Strings shown to the local player in the pickup dialog
+const char *g_pszItemPickupMethodStrings[] =
+{
+ "#NewItemMethod_Dropped", // UNACK_ITEM_DROPPED = 1,
+ "#NewItemMethod_Crafted", // UNACK_ITEM_CRAFTED,
+ "#NewItemMethod_Traded", // UNACK_ITEM_TRADED,
+ "#NewItemMethod_Purchased", // UNACK_ITEM_PURCHASED,
+ "#NewItemMethod_FoundInCrate", // UNACK_ITEM_FOUND_IN_CRATE,
+ "#NewItemMethod_Gifted", // UNACK_ITEM_GIFTED,
+ "#NewItemMethod_Support", // UNACK_ITEM_SUPPORT,
+ "#NewItemMethod_Promotion", // UNACK_ITEM_PROMOTION,
+ "#NewItemMethod_Earned", // UNACK_ITEM_EARNED,
+ "#NewItemMethod_Refunded", // UNACK_ITEM_REFUNDED,
+ "#NewItemMethod_GiftWrapped", // UNACK_ITEM_GIFT_WRAPPED,
+ "#NewItemMethod_Foreign", // UNACK_ITEM_FOREIGN,
+ "#NewItemMethod_CollectionReward", // UNACK_ITEM_COLLECTION_REWARD
+ "#NewItemMethod_PreviewItem", // UNACK_ITEM_PREVIEW_ITEM
+ "#NewItemMethod_PreviewItemPurchased", // UNACK_ITEM_PREVIEW_ITEM_PURCHASED
+ "#NewItemMethod_PeriodicScoreReward",// UNACK_ITEM_PERIODIC_SCORE_REWARD
+ "#NewItemMethod_MvMBadgeCompletionReward",// UNACK_ITEM_MVM_MISSION_COMPLETION_REWARD
+ "#NewItemMethod_MvMSquadSurplusReward",// UNACK_ITEM_MVM_SQUAD_SURPLUS_REWARD
+ "#NewItemMethod_HolidayGift", // UNACK_ITEM_FOUND_HOLIDAY_GIFT
+ "#NewItemMethod_CommunityMarketPurchase", // UNACK_ITEM_COMMUNITY_MARKET_PURCHASE
+ "#NewItemMethod_RecipeOutput", // UNACK_ITEM_RECIPE_OUTPUT
+ NULL, // UNACK_ITEM_HIDDEN_QUEST_ITEM
+ "#NewItemMethod_QuestOutput", // UNACK_ITEM_QUEST_OUTPUT
+ "#NewItemMethod_QuestLoaner", // UNACK_ITEM_QUEST_LOANER
+ "#NewItemMethod_TradeUp", // UNACK_ITEM_TRADE_UP
+ "#NewItemMethod_QuestMerasmissionOutput", //UNACK_ITEM_QUEST_MERASMISSION_OUTPUT
+ "#NewItemMethod_ViralCompetitiveBetaPassSpread", //UNACK_ITEM_VIRAL_COMPETITIVE_BETA_PASS_SPREAD
+#ifdef ENABLE_STORE_RENTAL_BACKEND
+ "#NewItemMethod_RentalPurchase", // UNACK_ITEM_RENTAL_PURCHASE
+#endif
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszItemPickupMethodStrings ) == (UNACK_NUM_METHODS - 1) ); // -1 because UNACK_ITEM_DROPPED is index 1, not 0
+
+const char *g_pszItemPickupMethodStringsUnloc[] =
+{
+ "dropped", // UNACK_ITEM_DROPPED = 1,
+ "crafted", // UNACK_ITEM_CRAFTED,
+ "traded", // UNACK_ITEM_TRADED,
+ "purchased", // UNACK_ITEM_PURCHASED,
+ "found_in_crate", // UNACK_ITEM_FOUND_IN_CRATE,
+ "gifted", // UNACK_ITEM_GIFTED,
+ "support", // UNACK_ITEM_SUPPORT,
+ "promotion", // UNACK_ITEM_PROMOTION,
+ "earned", // UNACK_ITEM_EARNED,
+ "refunded", // UNACK_ITEM_REFUNDED,
+ "gift_wrapped", // UNACK_ITEM_GIFT_WRAPPED
+ "foreign", // UNACK_ITEM_FOREIGN
+ "collection_reward",// UNACK_ITEM_COLLECTION_REWARD
+ "preview_item", // UNACK_ITEM_PREVIEW_ITEM
+ "preview_item_purchased", // UNACK_ITEM_PREVIEW_ITEM_PURCHASED
+ "periodic_score_reward", // UNACK_ITEM_PERIODIC_SCORE_REWARD
+ "mvm_badge_completion_reward", // UNACK_ITEM_MVM_MISSION_COMPLETION_REWARD
+ "mvm_squad_surplus_reward", // UNACK_ITEM_MVM_SQUAD_SURPLUS_REWARD
+ "holiday_gift", // UNACK_ITEM_FOUND_HOLIDAY_GIFT
+ "market_purchase", // UNACK_ITEM_COMMUNITY_MARKET_PURCHASE
+ "recipe_output", // UNACK_ITEM_RECIPE_OUTPUT
+ "hidden_quest", // UNACK_ITEM_HIDDEN_QUEST_ITEM
+ "quest_output", // UNACK_ITEM_QUEST_OUTPUT
+ "trade_up", // UNACK_ITEM_TRADE_UP
+ "quest_output", // UNACK_ITEM_QUEST_MERASMISSION_OUTPUT
+ "viral_competitive_beta_pass", //UNACK_ITEM_VIRAL_COMPETITIVE_BETA_PASS_SPREAD
+#ifdef ENABLE_STORE_RENTAL_BACKEND
+ "rental_purchase", // UNACK_ITEM_RENTAL_PURCHASE
+#endif
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszItemPickupMethodStringsUnloc ) == (UNACK_NUM_METHODS - 1) );
+
+// Strings shown to other players in the chat dialog
+const char *g_pszItemFoundMethodStrings[] =
+{
+ "#Item_Found", // UNACK_ITEM_DROPPED = 1,
+ "#Item_Crafted", // UNACK_ITEM_CRAFTED,
+ "#Item_Traded", // UNACK_ITEM_TRADED,
+ NULL, // UNACK_ITEM_PURCHASED,
+ "#Item_FoundInCrate", // UNACK_ITEM_FOUND_IN_CRATE,
+ "#Item_Gifted", // UNACK_ITEM_GIFTED,
+ NULL, // UNACK_ITEM_SUPPORT,
+ NULL, // UNACK_ITEM_PROMOTION
+ "#Item_Earned", // UNACK_ITEM_EARNED
+ "#Item_Refunded", // UNACK_ITEM_REFUNDED
+ "#Item_GiftWrapped", // UNACK_ITEM_GIFT_WRAPPED
+ "#Item_Foreign", // UNACK_ITEM_FOREIGN
+ "#Item_CollectionReward", // UNACK_ITEM_COLLECTION_REWARD
+ "#Item_PreviewItem", // UNACK_ITEM_PREVIEW_ITEM
+ "#Item_PreviewItemPurchased",// UNACK_ITEM_PREVIEW_ITEM_PURCHASED
+ "#Item_PeriodicScoreReward",// UNACK_ITEM_PERIODIC_SCORE_REWARD
+ "#Item_MvMBadgeCompletionReward",// UNACK_ITEM_MVM_MISSION_COMPLETION_REWARD
+ "#Item_MvMSquadSurplusReward",// UNACK_ITEM_MVM_SQUAD_SURPLUS_REWARD
+ "#Item_HolidayGift", // UNACK_ITEM_FOUND_HOLIDAY_GIFT
+ NULL, // UNACK_ITEM_COMMUNITY_MARKET_PURCHASE
+ "#Item_RecipeOutput", // UNACK_ITEM_RECIPE_OUTPUT
+ NULL, // UNACK_ITEM_HIDDEN_QUEST_ITEM
+ "#Item_QuestOutput", // UNACK_ITEM_QUEST_OUTPUT
+ NULL, // UNACK_ITEM_QUEST_LOANER
+ "#Item_TradeUp", // UNACK_ITEM_TRADE_UP
+ "#Item_QuestMerasmissionOutput", // UNACK_ITEM_QUEST_MERASMISSION_OUTPUT
+ "#Item_ViralCompetitiveBetaPassSpread", //UNACK_ITEM_VIRAL_COMPETITIVE_BETA_PASS_SPREAD
+#ifdef ENABLE_STORE_RENTAL_BACKEND
+ NULL, // UNACK_ITEM_RENTAL_PURCHASE
+#endif
+};
+
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszItemFoundMethodStrings ) == (UNACK_NUM_METHODS - 1) );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+struct strange_attr_set_t
+{
+ strange_attr_set_t( const char *pScoreAttrName, const char *pTypeAttrName, const char *pRestrictionAttrName, const char *pRestrictionValueAttrName, bool bIsUserCustomizable )
+ : m_attrScore( pScoreAttrName )
+ , m_attrType( pTypeAttrName )
+ , m_attrRestriction( pRestrictionAttrName )
+ , m_attrRestrictionValue( pRestrictionValueAttrName )
+ , m_bIsUserCustomizable( bIsUserCustomizable )
+ {
+ //
+ }
+
+ CSchemaAttributeDefHandle m_attrScore;
+ CSchemaAttributeDefHandle m_attrType;
+ CSchemaAttributeDefHandle m_attrRestriction;
+ CSchemaAttributeDefHandle m_attrRestrictionValue;
+ bool m_bIsUserCustomizable;
+};
+
+strange_attr_set_t g_KillEaterAttr[] =
+{
+ strange_attr_set_t( "kill eater", "kill eater score type", "strange restriction type 1", "strange restriction value 1", false ),
+ strange_attr_set_t( "kill eater 2", "kill eater score type 2", "strange restriction type 2", "strange restriction value 2", false ),
+ strange_attr_set_t( "kill eater 3", "kill eater score type 3", "strange restriction type 3", "strange restriction value 3", false ),
+
+ // assumption: all of the user-customizable attributes will follow all of the schema-specified attributes
+ strange_attr_set_t( "kill eater user 1", "kill eater user score type 1", "strange restriction user type 1", "strange restriction user value 1", true ),
+ strange_attr_set_t( "kill eater user 2", "kill eater user score type 2", "strange restriction user type 2", "strange restriction user value 2", true ),
+ strange_attr_set_t( "kill eater user 3", "kill eater user score type 3", "strange restriction user type 3", "strange restriction user value 3", true ),
+};
+
+int GetKillEaterAttrCount()
+{
+#ifdef DBGFLAG_ASSERT
+ // Verify our commented assumption that all of the non-user-customizable attributes will be followed by
+ // all of the user-customizable attributes.
+ bool bInUserCustomizableBlock = false;
+
+ for ( int i = 0; i < ARRAYSIZE( g_KillEaterAttr ); i++ )
+ {
+ if ( bInUserCustomizableBlock )
+ {
+ AssertMsg( g_KillEaterAttr[i].m_bIsUserCustomizable, "Ordering assumption for g_KillEaterAttr violated! User-customizable attributes should all be at the end of the list!" );
+ }
+
+ bInUserCustomizableBlock |= g_KillEaterAttr[i].m_bIsUserCustomizable;
+ }
+#endif
+
+ return ARRAYSIZE( g_KillEaterAttr );
+}
+
+int GetKillEaterAttrCount_UserCustomizable()
+{
+ int iCount = 0;
+ for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
+ {
+ if ( GetKillEaterAttr_IsUserCustomizable( i ) )
+ {
+ iCount++;
+ }
+ }
+
+ return iCount;
+}
+
+const CEconItemAttributeDefinition *GetKillEaterAttr_Score( int i )
+{
+ Assert( i >= 0 );
+ Assert( i < GetKillEaterAttrCount() );
+
+ const CEconItemAttributeDefinition *pAttrRes = g_KillEaterAttr[i].m_attrScore;
+ AssertMsg1( pAttrRes, "Missing Killeater attr score %s", g_KillEaterAttr[ i ].m_attrScore.GetName() );
+
+ return pAttrRes;
+}
+
+const CEconItemAttributeDefinition *GetKillEaterAttr_Type( int i )
+{
+ Assert( i >= 0 );
+ Assert( i < GetKillEaterAttrCount() );
+
+ const CEconItemAttributeDefinition *pAttrRes = g_KillEaterAttr[i].m_attrType;
+ AssertMsg1( pAttrRes, "Missing Killeater attr type %s", g_KillEaterAttr[ i ].m_attrType.GetName() );
+
+ return pAttrRes;
+}
+
+const CEconItemAttributeDefinition *GetKillEaterAttr_Restriction( int i )
+{
+ Assert( i >= 0 );
+ Assert( i < GetKillEaterAttrCount() );
+
+ const CEconItemAttributeDefinition *pAttrRes = g_KillEaterAttr[i].m_attrRestriction;
+ AssertMsg1( pAttrRes, "Missing Killeater attr restriction %s", g_KillEaterAttr[ i ].m_attrRestriction.GetName() );
+
+ return pAttrRes;
+}
+
+const CEconItemAttributeDefinition *GetKillEaterAttr_RestrictionValue( int i )
+{
+ Assert( i >= 0 );
+ Assert( i < GetKillEaterAttrCount() );
+
+ const CEconItemAttributeDefinition *pAttrRes = g_KillEaterAttr[i].m_attrRestrictionValue;
+ AssertMsg1( pAttrRes, "Missing Killeater attr restriction value %s", g_KillEaterAttr[ i ].m_attrRestrictionValue.GetName() );
+
+ return pAttrRes;
+}
+
+bool GetKillEaterAttr_IsUserCustomizable( int i )
+{
+ Assert( i >= 0 );
+ Assert( i < GetKillEaterAttrCount() );
+
+ return g_KillEaterAttr[i].m_bIsUserCustomizable;
+}
+
+
+bool GetKilleaterValueByEvent( const IEconItemInterface* pItem, const kill_eater_event_t& EEventType, uint32& value )
+{
+ for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
+ {
+ const CEconItemAttributeDefinition *pAttribKillEater = GetKillEaterAttr_Score( i );
+ const CEconItemAttributeDefinition *pAttribKillEaterScoreType = GetKillEaterAttr_Type( i );
+
+ Assert( pAttribKillEater && pAttribKillEaterScoreType );
+ if ( !pAttribKillEater || !pAttribKillEaterScoreType )
+ return false;
+
+ // make sure this item even has a kill count attribute we're looking for
+ uint32 unKillEaterAttrValue;
+ if ( !pItem->FindAttribute( pAttribKillEater, &unKillEaterAttrValue ) )
+ continue;
+
+ uint32 unKillEaterScoreTypeAttrValue = kKillEaterEvent_PlayerKill;
+
+ float fKillEaterScoreTypeAttrValue;
+ if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pItem, pAttribKillEaterScoreType, &fKillEaterScoreTypeAttrValue ) )
+ {
+ unKillEaterScoreTypeAttrValue = (uint32)fKillEaterScoreTypeAttrValue;
+ }
+
+ // this isn't the attribute we're trying to find
+ if ( EEventType != (kill_eater_event_t)unKillEaterScoreTypeAttrValue )
+ continue;
+
+ value = unKillEaterAttrValue;
+ return true;
+ }
+
+ return false;
+}
+
+// Does this thing have kill eater
+bool BIsItemStrange( const IEconItemInterface *pItem )
+{
+ // Go over the attributes of the item, if it has any strange attributes the item is strange and don't apply
+ uint32 unKillEaterAttr;
+ for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
+ {
+ if ( pItem->FindAttribute( GetKillEaterAttr_Score( i ), &unKillEaterAttr ) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get a localization token that describes why an item is not usable
+// in the trade-up crafting. Returns NULL if no reason. Can pass in
+// another item to compare against, which causes extra consistency checks
+//-----------------------------------------------------------------------------
+const char* GetCollectionCraftingInvalidReason( const IEconItemInterface *pTestItem, const IEconItemInterface *pSourceItem )
+{
+ if ( !pTestItem )
+ {
+ return "#TF_CollectionCrafting_NoItem";
+ }
+
+ // Needs to have a collection
+ const CEconItemCollectionDefinition* pTestCollection = pTestItem->GetItemDefinition()->GetItemCollectionDefinition();
+ if ( !pTestCollection )
+ {
+ return "#TF_CollectionCrafting_NoCollection";
+ }
+
+ // Make sure this item is a part of the collection it claims to be in
+ {
+ item_definition_index_t nThisDefIndex = pTestItem->GetItemDefIndex();
+ bool bFound = false;
+ for( int i=0; i < pTestCollection->m_iItemDefs.Count() && !bFound; ++i )
+ {
+ bFound |= pTestCollection->m_iItemDefs[i] == nThisDefIndex;
+ }
+
+ if ( !bFound )
+ {
+ return "#TF_CollectionCrafting_NoCollection";
+ }
+ }
+
+ // Needs rarity
+ uint8 nRarity = pTestItem->GetItemDefinition()->GetRarity();
+ if( nRarity == k_unItemRarity_Any )
+ {
+ return "#TF_CollectionCrafting_NoRarity";
+ }
+
+ // Can't use items with rarity at the "top" of a collection (what would they craft into?)
+ if ( nRarity == pTestCollection->GetMaxRarity() )
+ {
+ return "#TF_CollectionCrafting_MaxRarity";
+ }
+
+ // No self mades or community items
+ uint32 eQuality = pTestItem->GetQuality();
+ if ( eQuality == AE_SELFMADE || eQuality == AE_COMMUNITY )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ // This is how we test for unusuals. Don't let unusuals be crafted
+ static CSchemaAttributeDefHandle pAttrDef_ParticleEffect( "attach particle effect" );
+ if ( pTestItem->FindAttribute( pAttrDef_ParticleEffect ) )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ static CSchemaAttributeDefHandle pAttrDef_TauntUnusualAttr( "on taunt attach particle index" );
+ if ( pTestItem->FindAttribute( pAttrDef_TauntUnusualAttr ) )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ // Not allowed to be crafted?
+ if ( !pTestItem->IsUsableInCrafting() )
+ {
+ return "#TF_CollectionCrafting_NotCraftable";
+ }
+
+ // If another item was passed in, we have a few consistency checks to make
+ if ( pSourceItem )
+ {
+ // Need to have the same rarity
+ if ( nRarity != pSourceItem->GetItemDefinition()->GetRarity() )
+ {
+ return "#TF_CollectionCrafting_MismatchRarity";
+ }
+
+ // Need to have the same strangeness
+ if ( BIsItemStrange( pSourceItem ) != BIsItemStrange( pTestItem ) )
+ {
+ return "#TF_CollectionCrafting_MismatchStrange";
+ }
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get a localization token that describes why an item is not usable
+// in the Halloween Offering. Returns NULL if no reason. Can pass in
+// another item to compare against, which causes extra consistency checks
+//-----------------------------------------------------------------------------
+const char* GetHalloweenOfferingInvalidReason( const IEconItemInterface *pTestItem, const IEconItemInterface *pSourceItem )
+{
+ // Must either be a Cosmetic
+ // Taunt
+ // Allowable Tool (Strange part, Paint, name tag, killstreak). Not crates, keys
+ // Marketable Weapon ie Strange, Genuine, Vintage, paintkit
+
+ // Cannot be Unusual
+
+ if ( !pTestItem )
+ {
+ return "#TF_CollectionCrafting_NoItem";
+ }
+
+ // No self mades or community items
+ uint32 eQuality = pTestItem->GetQuality();
+ if ( eQuality == AE_SELFMADE || eQuality == AE_COMMUNITY )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ // This is how we test for unusuals. Don't let unusuals be crafted
+ static CSchemaAttributeDefHandle pAttrDef_ParticleEffect( "attach particle effect" );
+ if ( pTestItem->FindAttribute( pAttrDef_ParticleEffect ) )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ static CSchemaAttributeDefHandle pAttrDef_TauntUnusualAttr( "on taunt attach particle index" );
+ if ( pTestItem->FindAttribute( pAttrDef_TauntUnusualAttr ) )
+ {
+ return "#TF_CollectionCrafting_NoUnusual";
+ }
+
+ // Invalid Items
+ static CSchemaAttributeDefHandle pAttrDef_CannotTransmute( "cannot_transmute" );
+ if ( pTestItem->FindAttribute( pAttrDef_CannotTransmute ) )
+ {
+ return "#TF_HalloweenOffering_Invalid";
+ }
+
+ static CSchemaAttributeDefHandle pAttrDef_CannotDelete( "cannot delete" );
+ if ( pTestItem->FindAttribute( pAttrDef_CannotDelete ) )
+ {
+ return "#TF_HalloweenOffering_Invalid";
+ }
+
+ const CEconItemDefinition *pItemDef = pTestItem->GetItemDefinition();
+ if ( pItemDef == NULL )
+ {
+ return "#TF_CollectionCrafting_NoItem";
+ }
+
+ if ( pTestItem->IsTemporaryItem() )
+ {
+ return "#TF_CollectionCrafting_NoItem";
+ }
+
+ // If you are a taunt or a cosmetic you are allowed
+ if ( pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_MISC || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_TAUNT )
+ {
+ // do not 'medal' equip region items
+ if ( pTestItem->GetItemDefinition()->GetEquipRegionMask() & GetItemSchema()->GetEquipRegionBitMaskByName( "medal" ) )
+ {
+ return "#TF_HalloweenOffering_Invalid";
+ }
+
+ return NULL;
+ }
+
+ // Do not allow Crates
+ if ( ( pItemDef->GetCapabilities() & ITEM_CAP_DECODABLE ) != 0 )
+ {
+ return "#TF_HalloweenOffering_Invalid";
+ }
+
+ // Cause of weird legacy items lets be explicit about what we allow
+ if ( pItemDef->IsTool() )
+ {
+ // ignore everything that is not a paint can tool
+ const IEconTool *pEconTool = pItemDef->GetEconTool();
+ if ( !pEconTool )
+ return "#TF_HalloweenOffering_Invalid";
+
+ const char *pToolType = pEconTool->GetTypeName();
+
+ if ( !V_strcmp( pToolType, "paint_can" ) )
+ return NULL;
+ else if ( !V_strcmp( pToolType, "strange_part" ) )
+ return NULL;
+ else if ( !V_strcmp( pToolType, "name" ) )
+ return NULL;
+ else if ( !V_strcmp( pToolType, "desc" ) )
+ return NULL;
+ else if ( !V_strcmp( pToolType, "killstreakifier" ) )
+ return NULL;
+ else if ( !V_strcmp( pToolType, "strangifier" ) )
+ return NULL;
+
+ // Not a tool we are allowing
+ return "#TF_HalloweenOffering_Invalid";
+ }
+
+ // Otherwise you must be a weapon or we won't allow
+ if ( pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_PRIMARY
+ || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_SECONDARY
+ || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_MELEE
+ || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_BUILDING
+ || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_PDA
+ || pTestItem->GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_PDA2
+ ) {
+ // Must be strange, genuine, vintage, haunted or paintkit (ie a marketable weapon)
+ eQuality = pTestItem->GetQuality();
+ if ( eQuality == AE_RARITY1
+ || eQuality == AE_VINTAGE
+ || eQuality == AE_HAUNTED
+ || eQuality == AE_COLLECTORS
+ || eQuality == AE_PAINTKITWEAPON
+ ) {
+ return NULL;
+ }
+
+ // Weapons with rarity are allowed
+ uint8 nRarity = pTestItem->GetItemDefinition()->GetRarity();
+ if ( nRarity != k_unItemRarity_Any )
+ {
+ return NULL;
+ }
+
+ // Strange items. Dont just check for strange quality, actually check for a strange attribute.
+ // See if we've got any strange attributes.
+ for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
+ {
+ if ( pTestItem->FindAttribute( GetKillEaterAttr_Score( i ) ) )
+ {
+ return NULL;
+ }
+ }
+ }
+
+ return "#TF_HalloweenOffering_Invalid";
+}
+
+const char* GetCraftCommonStatClockInvalidReason( const class IEconItemInterface *pTestItem, const class IEconItemInterface *pSourceItem )
+{
+ if ( !pTestItem )
+ {
+ return "#TF_CollectionCrafting_NoItem";
+ }
+
+ // Not allowed to be crafted?
+ if ( !pTestItem->IsUsableInCrafting() )
+ {
+ return "#TF_CollectionCrafting_NotCraftable";
+ }
+
+ // No self mades or community items
+ uint32 eQuality = pTestItem->GetQuality();
+ if ( eQuality == AE_SELFMADE || eQuality == AE_COMMUNITY )
+ return "#TF_CollectionCrafting_NoUnusual";
+
+ // This is how we test for unusuals. Don't let unusuals be crafted
+ static CSchemaAttributeDefHandle pAttrDef_ParticleEffect( "attach particle effect" );
+ if ( pTestItem->FindAttribute( pAttrDef_ParticleEffect ) )
+ return "#TF_CollectionCrafting_NoUnusual";
+
+ static CSchemaAttributeDefHandle pAttrDef_TauntUnusualAttr( "on taunt attach particle index" );
+ if ( pTestItem->FindAttribute( pAttrDef_TauntUnusualAttr ) )
+ return "#TF_CollectionCrafting_NoUnusual";
+
+ const CEconItemDefinition *pItemDef = pTestItem->GetItemDefinition();
+ if ( pItemDef == NULL )
+ return "#TF_CollectionCrafting_NoItem";
+
+ if ( pTestItem->IsTemporaryItem() )
+ return "#TF_CollectionCrafting_NoItem";
+
+ // Strange items. Dont just check for strange quality, actually check for a strange attribute.
+ // See if we've got any strange attributes.
+ for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
+ {
+ if ( pTestItem->FindAttribute( GetKillEaterAttr_Score( i ) ) )
+ {
+ return NULL;
+ }
+ }
+
+ // Needs Rarity
+ uint8 nRarity = pTestItem->GetItemDefinition()->GetRarity();
+ if ( nRarity != k_unItemRarity_Any && nRarity > 1 ) // do not allow default nor common rarity
+ {
+ return NULL;
+ }
+
+ return "#TF_MannCoTrade_ItemInvalid";
+}
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+enum { kMaxCardUpgradesPerItem = 2 };
+
+int GetMaxCardUpgradesPerItem()
+{
+ return kMaxCardUpgradesPerItem;
+}
+
+const CEconItemAttributeDefinition *GetCardUpgradeForIndex( const IEconItemInterface *pItem, int i )
+{
+ Assert( pItem );
+ Assert( i >= 0 );
+ Assert( i < kMaxCardUpgradesPerItem );
+
+ class CGetNthUserGeneratedAttributeIterator : public IEconItemUntypedAttributeIterator
+ {
+ public:
+ CGetNthUserGeneratedAttributeIterator( int iTargetIndex )
+ : m_iCount( iTargetIndex )
+ , m_pAttrDef( NULL )
+ {
+ }
+
+ virtual bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef ) OVERRIDE
+ {
+ if ( pAttrDef->GetUserGenerationType() != 0 && m_iCount-- == 0 )
+ {
+ m_pAttrDef = pAttrDef;
+ return false;
+ }
+
+ return true;
+ }
+
+ const CEconItemAttributeDefinition *GetAttrDef() const { return m_pAttrDef; }
+
+ private:
+ int m_iCount;
+ const CEconItemAttributeDefinition *m_pAttrDef;
+ };
+
+ CGetNthUserGeneratedAttributeIterator findNthAttrIterator( i );
+ pItem->IterateAttributes( &findNthAttrIterator );
+
+ return findNthAttrIterator.GetAttrDef();
+}