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

970 lines
31 KiB

//========= 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();
}