diff options
Diffstat (limited to 'game/shared/econ/econ_item_constants.cpp')
| -rw-r--r-- | game/shared/econ/econ_item_constants.cpp | 970 |
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(); +} |