diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/econ/econ_item_interface.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/econ/econ_item_interface.cpp')
| -rw-r--r-- | game/shared/econ/econ_item_interface.cpp | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/game/shared/econ/econ_item_interface.cpp b/game/shared/econ/econ_item_interface.cpp new file mode 100644 index 0000000..f915846 --- /dev/null +++ b/game/shared/econ/econ_item_interface.cpp @@ -0,0 +1,412 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "cbase.h" +#include "econ_item_interface.h" +#include "econ_item_tools.h" // needed for CEconTool_WrappedGift definition for IsMarketable() +#include "rtime.h" + +#ifdef STAGING_ONLY +ConVar tf_paint_kit_force_wear( "tf_paint_kit_force_wear", "0", FCVAR_REPLICATED, "Set to force the wear level of paink kit weapons and ignore the GC dynamic attribute value." ); +#endif + +// -------------------------------------------------------------------------- +bool IEconItemInterface::GetCustomPaintKitWear( float &flWear ) const +{ + +#ifdef STAGING_ONLY + // don't assert in staging if this ConVar is set + if ( tf_paint_kit_force_wear.GetInt() > 0 ) + { + flWear = tf_paint_kit_force_wear.GetFloat(); + return true; + } +#endif // STAGING_ONLY + + static CSchemaAttributeDefHandle pAttrDef_PaintKitWear( "set_item_texture_wear" ); + float flPaintKitWear = 0; + if ( pAttrDef_PaintKitWear && FindAttribute_UnsafeBitwiseCast<attrib_value_t>( this, pAttrDef_PaintKitWear, &flPaintKitWear ) ) + { + flWear = flPaintKitWear; + return true; + } + + static CSchemaAttributeDefHandle pAttrDef_DefaultWear( "texture_wear_default" ); + if ( pAttrDef_DefaultWear && FindAttribute_UnsafeBitwiseCast<attrib_value_t>( this, pAttrDef_DefaultWear, &flPaintKitWear ) ) + { + flWear = flPaintKitWear; + return true; + } + // If you have no wear, you also should not have a paint kit + AssertMsg( !GetCustomPainkKitDefinition(), "No Wear Found on Item [%llu - %s] that has a Paintkit!", GetID(), GetItemDefinition()->GetDefinitionName() ); + + return false; +} + +// -------------------------------------------------------------------------- +// Purpose: +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsTemporaryItem() const +{ + // store preview items are also temporary + if ( GetOrigin() == kEconItemOrigin_PreviewItem ) + return true; + + RTime32 rtTime = GetExpirationDate(); + if ( rtTime > 0 ) + return true; + + return false; +} + +// -------------------------------------------------------------------------- +RTime32 IEconItemInterface::GetExpirationDate() const +{ + COMPILE_TIME_ASSERT( sizeof( float ) == sizeof( RTime32 ) ); + + // dynamic attributes, if present, will override any static expiration timer + static CSchemaAttributeDefHandle pAttrib_ExpirationDate( "expiration date" ); + + attrib_value_t unAttribExpirationTimeBits; + COMPILE_TIME_ASSERT( sizeof( unAttribExpirationTimeBits ) == sizeof( RTime32 ) ); + + if ( pAttrib_ExpirationDate && FindAttribute( pAttrib_ExpirationDate, &unAttribExpirationTimeBits ) ) + return *(RTime32 *)&unAttribExpirationTimeBits; + + // do we have a static timer set in the schema for all instances to expire? + return GetItemDefinition() + ? GetItemDefinition()->GetExpirationDate() + : RTime32( 0 ); +} + +// -------------------------------------------------------------------------- +// Purpose: +// -------------------------------------------------------------------------- +RTime32 IEconItemInterface::GetTradableAfterDateTime() const +{ + static CSchemaAttributeDefHandle pAttrib_TradableAfter( "tradable after date" ); + Assert( pAttrib_TradableAfter ); + + if ( !pAttrib_TradableAfter ) + return 0; + + RTime32 rtTimestamp; + if ( !FindAttribute( pAttrib_TradableAfter, &rtTimestamp ) ) + return 0; + + return rtTimestamp; +} + +// -------------------------------------------------------------------------- +// Purpose: Return true if this item can never be traded +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsPermanentlyUntradable() const +{ + if ( GetItemDefinition() == NULL ) + return true; + + // tagged to not be a part of the economy? + if ( ( kEconItemFlag_NonEconomy & GetFlags() ) != 0 ) + return true; + + // check attributes + + static CSchemaAttributeDefHandle pAttrib_AlwaysTradable( "always tradable" ); + static CSchemaAttributeDefHandle pAttrib_CannotTrade( "cannot trade" ); + static CSchemaAttributeDefHandle pAttrib_NonEconomy( "non economy" ); + + Assert( pAttrib_AlwaysTradable != NULL ); + Assert( pAttrib_CannotTrade != NULL ); + + if ( pAttrib_AlwaysTradable == NULL || pAttrib_CannotTrade == NULL || pAttrib_NonEconomy == NULL ) + return true; + + // Order matters, check for nonecon first. Always tradable overrides cannot trade. + if ( FindAttribute( pAttrib_NonEconomy ) ) + return true; + + if ( FindAttribute( pAttrib_AlwaysTradable ) ) // *sigh* + return false; + + if ( FindAttribute( pAttrib_CannotTrade ) ) + return true; + + // items gained in this way are not tradable + switch ( GetOrigin() ) + { + case kEconItemOrigin_Invalid: + case kEconItemOrigin_Achievement: + case kEconItemOrigin_Foreign: + case kEconItemOrigin_PreviewItem: + case kEconItemOrigin_SteamWorkshopContribution: + return true; + } + + // temporary items (items that will expire for any reason) cannot be traded + if ( IsTemporaryItem() ) + return true; + + // certain quality levels are not tradable + if ( GetQuality() >= AE_COMMUNITY && GetQuality() <= AE_SELFMADE ) + return true; + + // explicitly marked cannot trade? + if ( ( kEconItemFlag_CannotTrade & GetFlags() ) != 0 ) + return true; + + return false; +} + +// -------------------------------------------------------------------------- +// Purpose: Return true if this item is a commodity on the Market (can place buy orders) +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsCommodity() const +{ + if ( GetItemDefinition() == NULL ) + return false; + + static CSchemaAttributeDefHandle pAttrib_IsCommodity( "is commodity" ); + if ( FindAttribute( pAttrib_IsCommodity ) ) + return true; + + return false; +} + +// -------------------------------------------------------------------------- +// Purpose: Return true if temporarily untradable +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsTemporarilyUntradable() const +{ + // Temporary untradability does NOT take "always tradable" into account + if ( GetTradableAfterDateTime() >= CRTime::RTime32TimeCur() ) + return true; + + return false; +} + +// -------------------------------------------------------------------------- +// Purpose: Return true if this item is untradable +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsTradable() const +{ + // Items that are expired are never listable, regardless of other rules. + //RTime32 timeExpirationDate = GetExpirationDate(); + //if ( timeExpirationDate > 0 && timeExpirationDate < CRTime::RTime32TimeCur() ) + // return false; + + return GetUntradabilityFlags() == 0; +} + +// -------------------------------------------------------------------------- +// Purpose: Return untradability flags +// -------------------------------------------------------------------------- +int IEconItemInterface::GetUntradabilityFlags() const +{ + int nFlags = 0; + if ( IsTemporarilyUntradable() ) + { + nFlags |= k_Untradability_Temporary; + } + + if ( IsPermanentlyUntradable() ) + { + nFlags |= k_Untradability_Permanent; + } + + return nFlags; +} + +// -------------------------------------------------------------------------- +// Purpose: +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsUsableInCrafting() const +{ + if ( GetItemDefinition() == NULL ) + return false; + + // tagged to not be a part of the economy? + if ( ( kEconItemFlag_NonEconomy & GetFlags() ) != 0 ) + return false; + + // always craftable? + static CSchemaAttributeDefHandle pAttrib_AlwaysUsableInCraft( "always tradable" ); + Assert( pAttrib_AlwaysUsableInCraft ); + + if ( FindAttribute( pAttrib_AlwaysUsableInCraft ) ) + return true; + + // never craftable? + static CSchemaAttributeDefHandle pAttrib_NeverCraftable( "never craftable" ); + Assert( pAttrib_NeverCraftable ); + + if ( FindAttribute( pAttrib_NeverCraftable ) ) + return false; + + // temporary items (items that will expire for any reason) cannot be turned into + // permanent items + if ( IsTemporaryItem() ) + return false; + + // explicitly marked not usable in crafting? + if ( ( kEconItemFlag_CannotBeUsedInCrafting & GetFlags() ) != 0 ) + return false; + + // items gained in this way are not craftable + switch ( GetOrigin() ) + { + case kEconItemOrigin_Invalid: + case kEconItemOrigin_Foreign: + case kEconItemOrigin_StorePromotion: + case kEconItemOrigin_SteamWorkshopContribution: + return false; + + // purchased items can be used in crafting if explicitly tagged, but not by default + case kEconItemOrigin_Purchased: + // deny items the GC didn't flag at purchase time + if ( (GetFlags() & kEconItemFlag_PurchasedAfterStoreCraftabilityChanges2012) == 0 ) + return false; + + // deny items that can never be used + if ( (GetItemDefinition()->GetCapabilities() & ITEM_CAP_CAN_BE_CRAFTED_IF_PURCHASED) == 0 ) + return false; + + break; + } + + // certain quality levels are not craftable + if ( GetQuality() >= AE_COMMUNITY && GetQuality() <= AE_SELFMADE ) + return false; + + return true; +} + +// -------------------------------------------------------------------------- +// Purpose: +// -------------------------------------------------------------------------- +bool IEconItemInterface::IsMarketable() const +{ + const CEconItemDefinition *pItemDef = GetItemDefinition(); + if ( pItemDef == NULL ) + return false; + + // Untradeable items can never be marketed, regardless of other rules. + // Temporarily untradable items can be marketed, only permanent untradable items cannot be marketed + if ( IsPermanentlyUntradable() ) + return false; + + // Items that are expired are never listable, regardless of other rules. + RTime32 timeExpirationDate = GetExpirationDate(); + if ( timeExpirationDate > 0 && timeExpirationDate < CRTime::RTime32TimeCur() ) + return false; + + // Initially, only TF2 supports listing items in the Marketplace. +#if defined( TF_DLL ) || defined( TF_CLIENT_DLL ) || defined( TF_GC_DLL ) + { + // User-created wrapped gifts are untradeable for the moment. This would provide a backdoor + // for users to sell anything they wanted, which is interesting but not what we want in + // the initial launch. + if ( pItemDef->GetTypedEconTool<CEconTool_WrappedGift>() ) + return false; + + // All other tools are listable. This includes keys, paints, backpack expanders, strange + // parts, Halloween spells, wedding rings, etc. It does not includes gifts (see above), + // noisemakers, or crates (see below). + if ( pItemDef->IsTool() ) + return true; + + // All crates are listable. Anything with the "decodable" flag is considered a crate. + if ( (pItemDef->GetCapabilities() & ITEM_CAP_DECODABLE) != 0 ) + return true; + + // Genuine-quality items come from time-limited purchase promos and are listable. Vintage + // items are from one-time transitions and are all finite quality. Haunted quality items are + // TF-Halloween-event specific. Some of the older haunted items didn't generate revenue, but + // the content is all old and there seems to be little harm in letting it be listed. The + // haunted items from 2013 all come from crates, which means they all generated revenue. + // Collectors items are created from a finite set of recipes. + // Paintkit Weapons are from cases or operations + if ( GetQuality() == AE_RARITY1 || GetQuality() == AE_VINTAGE || GetQuality() == AE_HAUNTED + || GetQuality() == AE_COLLECTORS || GetQuality() == AE_PAINTKITWEAPON ) + return true; + + // All festive items are from time-limited holiday crates and are listable. This code seems + // safe. (...) (This code is in fact so safe that if we just do a substring match we'll also + // allow "A Rather Festive Tree".) + if ( !V_strncmp( pItemDef->GetDefinitionName(), "Festive", 7 ) ) + return true; + + // All botkiller items come from MvM rewards and are listable. This does a substring search + // to find all varieties (gold, silver, rust, etc.), etc. + if ( V_strstr( pItemDef->GetDefinitionName(), " Botkiller " ) ) + return true; + + // Mvm V2 Robit Parts + if ( V_strstr( pItemDef->GetDefinitionName(), "Robits " ) ) + return true; + + // MvM Killstreak Weapons + static CSchemaAttributeDefHandle pAttr_killstreak( "killstreak tier" ); + if ( FindAttribute( pAttr_killstreak ) ) + return true; + + // Australium Items + static CSchemaAttributeDefHandle pAttrDef_IsAustralium( "is australium item" ); + if ( FindAttribute( pAttrDef_IsAustralium ) ) + return true; + + // Glitch GateHat Replacement Item + static CSchemaItemDefHandle pItemDef_GlitchedCircuit( "Glitched Circuit Board" ); + if ( pItemDef == pItemDef_GlitchedCircuit ) + return true; + + // Anything that says it wants to be marketable. + static CSchemaAttributeDefHandle pAttrDef_IsMarketable( "is marketable" ); + if ( FindAttribute( pAttrDef_IsMarketable ) ) + return true; + + // Anything that is of limited quantity (ie limited promos) + static CSchemaAttributeDefHandle pAttrDef_IsLimited( "limited quantity item" ); + if ( FindAttribute( pAttrDef_IsLimited ) ) + return true; + + // Allow the Giving items (not a wrapped_gift but a gift, ie Secret Saxton, Pile O Gifts, Pallet of Keys) + const CEconTool_Gift *pEconToolGift = pItemDef->GetTypedEconTool<CEconTool_Gift>(); + if ( pEconToolGift ) + return true; + + // Unusual Cosmetics and Taunts + if ( GetQuality() == AE_UNUSUAL && ( GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_MISC || GetItemDefinition()->GetLoadoutSlot( 0 ) == LOADOUT_POSITION_TAUNT ) ) + return true; + + // 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 ( FindAttribute( GetKillEaterAttr_Score( i ) ) ) + { + return true; + } + } + } +#endif // defined( TF_DLL ) || defined( TF_CLIENT_DLL ) || defined( TF_GC_DLL ) + + // By default, items aren't listable. + return false; +} + +// -------------------------------------------------------------------------- +const char *IEconItemInterface::GetDefinitionString( const char *pszKeyName, const char *pszDefaultValue ) const +{ + const GameItemDefinition_t *pDef = GetItemDefinition(); + if ( pDef ) + return pDef->GetDefinitionString( pszKeyName, pszDefaultValue ); + return pszDefaultValue; +} + +// -------------------------------------------------------------------------- +KeyValues *IEconItemInterface::GetDefinitionKey( const char *pszKeyName ) const +{ + const GameItemDefinition_t *pDef = GetItemDefinition(); + if ( pDef ) + return pDef->GetDefinitionKey( pszKeyName ); + return NULL; +} |