summaryrefslogtreecommitdiff
path: root/game/shared/econ/econ_store.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/econ/econ_store.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/econ/econ_store.h')
-rw-r--r--game/shared/econ/econ_store.h621
1 files changed, 621 insertions, 0 deletions
diff --git a/game/shared/econ/econ_store.h b/game/shared/econ/econ_store.h
new file mode 100644
index 0000000..56cf599
--- /dev/null
+++ b/game/shared/econ/econ_store.h
@@ -0,0 +1,621 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Common objects and utilities related to the in-game item store
+//
+//=============================================================================
+
+#ifndef ECON_STORE_H
+#define ECON_STORE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "UtlSortVector.h"
+#include "vstdlib/IKeyValuesSystem.h"
+#include "econ/econ_storecategory.h"
+#ifdef CLIENT_DLL
+#include "client_community_market.h"
+#endif // CLIENT_DLL
+//-----------------------------------------------------------------------------
+// Purpose: Error code enum for purchase messages
+//-----------------------------------------------------------------------------
+enum EPurchaseResult
+{
+ k_EPurchaseResultOK = 1, // Success
+ k_EPurchaseResultFail = 2, // Generic error
+ k_EPurchaseResultInvalidParam = 3, // Invalid parameter
+ k_EPurchaseResultInternalError = 4, // Internal error
+ k_EPurchaseResultNotApproved = 5, // Tried to finalize a transaction that has not yet been approved
+ k_EPurchaseResultAlreadyCommitted = 6, // Tried to finalize a transaction that has already been committed
+ k_EPurchaseResultUserNotLoggedIn = 7, // User is not logged into Steam
+ k_EPurchaseResultWrongCurrency = 8, // Microtransaction's currency does not match user's wallet currency
+ k_EPurchaseResultAccountError = 9, // User's account does not exist or is temporarily unavailable
+ k_EPurchaseResultInvalidItem = 10, // User is trying to purchase an item that doesn't exist or is not for sale
+ k_EPurchaseResultNotEnoughBackpackSpace = 11, // User did not have enough backpack space
+ k_EPurchaseResultLimitedQuantityItemsUnavailable = 12, // User tried to purchase limited-quantity items but there weren't enough left in stock
+
+ k_EPurchaseResultInsufficientFunds = 100, // User does not have wallet funds
+ k_EPurchaseResultTimedOut = 101, // Time limit for finalization has been exceeded
+ k_EPurchaseResultAcctDisabled = 102, // Steam account is disabled
+ k_EPurchaseResultAcctCannotPurchase = 103, // Steam account is not allowed to make a purchase
+ k_EMicroTxnResultFailedFraudChecks = 104, // Fraud checks inside of Steam failed
+
+ k_EPurchaseResultOldPriceSheet = 150, // Information on the purchase didn't match the current price sheet
+ k_EPurchaseResultTxnNotFound = 151 // Could not find the transaction specified
+};
+
+
+const char *PchNameFromEPurchaseResult( EPurchaseResult ePurchaseState );
+
+//-----------------------------------------------------------------------------
+// Purpose: State of a transaction
+//
+// WARNING: VALUES STORED IN DATABASE. DO NOT RENUMBER!!!
+//-----------------------------------------------------------------------------
+enum EPurchaseState
+{
+ k_EPurchaseStateInvalid = 0, // Invalid
+ k_EPurchaseStateInit = 1, // We have sent InitPurchase to Steam
+ k_EPurchaseStateWaitingForAuthorization = 2, // We have gotten initial authorization from Steam. Waiting for user to authorize.
+ k_EPurchaseStatePending = 3, // We are attempting to commit the transaction
+ k_EPurchaseStateComplete = 4, // The transaction was successful
+ k_EPurchaseStateFailed = 5, // The transaction failed
+ k_EPurchaseStateCanceled = 6, // The transaction was canceled
+ k_EPurchaseStateRefunded = 7, // The transaction was refunded
+ k_EPurchaseStateChargeback = 8, // The transaction was charged back
+ k_EPurchaseStateChargebackReversed = 9, // A chargeback has failed and we got the money
+ k_EPurchaseStateLast = k_EPurchaseStateChargebackReversed,
+};
+
+const char *PchNameFromEPurchaseState( EPurchaseState ePurchaseState );
+
+// DO NOT RENUMBER! These values are stored in the audit log table.
+enum EGCTransactionAuditReason
+{
+ k_EGCTransactionAudit_GCTransactionCompleted = 0, // The transaction completed successfully on the GC.
+ k_EGCTransactionAudit_GCTransactionInit = 1, // The transaction was initialized.
+ k_EGCTransactionAudit_GCTransactionPostInit = 2, // The result of attempting to initialize the transaction. This is where the SteamTxnID is set.
+ k_EGCTransactionAudit_GCTransactionFinalize = 3, // We have started to finalize the transaction (so probably set it to pending).
+ k_EGCTransactionAudit_GCTransactionFinalizeFailed = 4, // Our attempt to finalize the transaction failed for some reason (not due to a timeout).
+ k_EGCTransactionAudit_GCTransactionCanceled = 5, // The client requested that we cancel the transaction.
+ k_EGCTransactionAudit_SteamFailedMismatch = 6, // Steam failed the transaction but we did not.
+ k_EGCTransactionAudit_GCRemovePurchasedItems = 7, // We are attempting to remove the purchased items from their backpack (due to rollback or failure).
+ k_EGCTransactionAudit_GCTransactionInsert = 8, // We are inserting a transaction, usually one created by a web interface (i.e.: a cd-key operation) instead of a standard store interaction.
+ k_EGCTransactionAudit_GCTransactionCompletedPostChargeback = 9, // We thought this transaction had been charged back but Steam came back later and told us it was successful after all.
+
+ k_EGCTransactionAuditLast = k_EGCTransactionAudit_GCTransactionCompletedPostChargeback,
+};
+
+const char *PchNameFromEGCTransactionAuditReason( EGCTransactionAuditReason eAuditReason );
+
+enum EGCTransactionAuditInsertReason
+{
+ k_EGCTransactionAuditInsert_Invalid = 0, //
+ k_EGCTransactionAuditInsert_CDKey = 1, // A CD Key was used for this transaction.
+ k_EGCTransactionAuditInsert_SettlementNoMatch_Failed = 2, // We inserted a failed record during settlement to unblock the process.
+ k_EGCTransactionAuditInsert_SettlementNoMatch_Pending = 3, // We inserted a pending record during settlement to unblock the process.
+
+ k_EGCTransactionAuditInsertLast = k_EGCTransactionAuditInsert_SettlementNoMatch_Pending,
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Currencies we support
+//
+// WARNING: VALUES STORED IN DATABASE. DO NOT RENUMBER!!!
+// WARNING: THESE DON'T MATCH THE STEAM NUMERIC IDS!!! WE TALK USING CURRENCY
+// CODES LIKE "VND" AND IF YOU SAY "15" TERRIBLE THINGS WILL HAPPEN
+//-----------------------------------------------------------------------------
+enum ECurrency
+{
+ k_ECurrencyFirst = 0,
+ k_ECurrencyUSD = 0,
+ k_ECurrencyGBP = 1,
+ k_ECurrencyEUR = 2,
+ k_ECurrencyRUB = 3,
+ k_ECurrencyBRL = 4,
+ // space for Dota currencies
+ k_ECurrencyJPY = 8,
+ k_ECurrencyNOK = 9,
+ k_ECurrencyIDR = 10,
+ k_ECurrencyMYR = 11,
+ k_ECurrencyPHP = 12,
+ k_ECurrencySGD = 13,
+ k_ECurrencyTHB = 14,
+ k_ECurrencyVND = 15,
+ k_ECurrencyKRW = 16,
+ k_ECurrencyTRY = 17,
+ k_ECurrencyUAH = 18,
+ k_ECurrencyMXN = 19,
+ k_ECurrencyCAD = 20,
+ k_ECurrencyAUD = 21,
+ k_ECurrencyNZD = 22,
+ k_ECurrencyPLN = 23,
+ k_ECurrencyCHF = 24,
+ k_ECurrencyCNY = 25,
+ k_ECurrencyTWD = 26,
+ k_ECurrencyHKD = 27,
+ k_ECurrencyINR = 28,
+ k_ECurrencyAED = 29,
+ k_ECurrencySAR = 30,
+ k_ECurrencyZAR = 31,
+ k_ECurrencyCOP = 32,
+ k_ECurrencyPEN = 33,
+ k_ECurrencyCLP = 34,
+
+ // NOTE: Not actually the Maximum currency value, but the Terminator for the possible currency code range.
+ k_ECurrencyMax = 35,
+
+ // make this a big number so we can avoid having to move it when we add another currency type
+ k_ECurrencyInvalid = 255,
+ k_ECurrencyCDKeyTransaction = k_ECurrencyInvalid,
+};
+
+// Macro for looping across all valid currencies
+#define FOR_EACH_CURRENCY( _i ) for ( ECurrency _i = GetFirstValidCurrency(); _i != k_ECurrencyInvalid; _i = GetNextValidCurrency( _i ) )
+
+const char *PchNameFromECurrency( ECurrency eCurrency ); // NOTE: Defined with ENUMSTRINGS_START/ENUMSTRINGS_REVERSE macros
+ECurrency ECurrencyFromName( const char *pchName ); //
+
+inline bool BIsCurrencyValid( ECurrency eCurrency )
+{
+ switch ( eCurrency )
+ {
+ case k_ECurrencyUSD:
+ case k_ECurrencyGBP:
+ case k_ECurrencyEUR:
+ case k_ECurrencyRUB:
+ case k_ECurrencyBRL:
+ case k_ECurrencyJPY:
+ case k_ECurrencyNOK:
+ case k_ECurrencyIDR:
+ case k_ECurrencyMYR:
+ case k_ECurrencyPHP:
+ case k_ECurrencySGD:
+ case k_ECurrencyTHB:
+ case k_ECurrencyVND:
+ case k_ECurrencyKRW:
+ case k_ECurrencyTRY:
+ case k_ECurrencyUAH:
+ case k_ECurrencyMXN:
+ case k_ECurrencyCAD:
+ case k_ECurrencyAUD:
+ case k_ECurrencyNZD:
+ //case k_ECurrencyPLN:
+ case k_ECurrencyCHF:
+ case k_ECurrencyCNY:
+ case k_ECurrencyTWD:
+ case k_ECurrencyHKD:
+ case k_ECurrencyINR:
+ case k_ECurrencyAED:
+ case k_ECurrencySAR:
+ case k_ECurrencyZAR:
+ case k_ECurrencyCOP:
+ case k_ECurrencyPEN:
+ case k_ECurrencyCLP:
+ return true;
+ }
+
+ return false;
+}
+
+inline ECurrency GetFirstValidCurrency()
+{
+ for ( int i = k_ECurrencyFirst; i < k_ECurrencyMax; i++ )
+ {
+ if ( BIsCurrencyValid( (ECurrency)i ) )
+ return (ECurrency)i;
+ }
+ return k_ECurrencyInvalid;
+}
+
+inline ECurrency GetNextValidCurrency( ECurrency ePrevious )
+{
+ for ( int i = ePrevious + 1; i < k_ECurrencyMax; i++ )
+ {
+ if ( BIsCurrencyValid( (ECurrency)i ) )
+ return (ECurrency)i;
+ }
+ return k_ECurrencyInvalid;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple struct for pairing a sort type with a localization string
+//-----------------------------------------------------------------------------
+struct ItemSortTypeData_t
+{
+ const char *szSortDesc; // localization string
+ uint32 iSortType; // maps to the GC-specific sort value
+};
+
+// Description of a single item for sale
+struct econ_store_entry_t
+{
+ // Constructor
+ econ_store_entry_t()
+ : m_pchCategoryTags( NULL ),
+ m_unGiftSteamPackageID( 0 ),
+ m_bHighlighted( false )
+ {
+ V_memset( m_unBaseCosts, 0, sizeof(m_unBaseCosts) );
+ V_memset( m_unSaleCosts, 0, sizeof(m_unSaleCosts) );
+ }
+
+ void SetItemDefinitionIndex( item_definition_index_t usDefIndex );
+ item_definition_index_t GetItemDefinitionIndex() const { return m_usDefIndex; }
+
+ void InitCategoryTags( const char *pTags ); // Sets m_pchCategoryTags and initializes m_vecTagIds and m_fRentalPriceScale
+
+ bool IsListedInCategory( StoreCategoryID_t unID ) const; // Is this item listed in the given category?
+ bool IsListedInSubcategories( const CEconStoreCategoryManager::StoreCategory_t &Category ) const; // Is this item listed in one of Category's subcategories?
+ bool IsListedInCategoryOrSubcategories( const CEconStoreCategoryManager::StoreCategory_t &Category ) const; // Is this item listed in Category or one of Category's subcategories?
+
+ bool IsOnSale( ECurrency eCurrency ) const;
+ bool IsRentable() const;
+#ifdef CLIENT_DLL
+ bool HasDiscount( ECurrency eCurrency, item_price_t *out_punOptionalBasePrice ) const; // returns true if we're on sale or if we're a bundle with a discounted total price
+#endif // CLIENT_DLL
+ item_price_t GetCurrentPrice( ECurrency eCurrency ) const;
+ float GetRentalPriceScale() const;
+
+ uint32 GetGiftSteamPackageID() const { return m_unGiftSteamPackageID; }
+
+ // Helper function -- so we do this calculation in a single place.
+ static item_price_t GetDiscountedPrice( ECurrency eCurrency, item_price_t unBasePrice, float fDiscountPercentage );
+
+ static item_price_t CalculateSalePrice( const econ_store_entry_t* pSaleStoreEntry, ECurrency eCurrency, float fDiscountPercentage, int32 *out_pAdjustedDiscountPercentage = NULL );
+
+ item_price_t GetBasePrice( ECurrency eCurrency ) const
+ {
+ Assert( eCurrency >= k_ECurrencyFirst );
+ Assert( eCurrency < k_ECurrencyMax );
+ if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
+ return 0;
+#ifdef CLIENT_DLL
+ if ( m_bIsMarketItem )
+ {
+ const client_market_data_t *pClientMarketData = GetClientMarketData( GetItemDefinitionIndex(), AE_UNIQUE );
+ if ( !pClientMarketData )
+ return 0;
+ return pClientMarketData->m_unLowestPrice;
+ }
+#endif
+ // Weird-looking pattern: we're making sure that the value we're about to return fits correctly
+ // into the variable we're about to put it into. We do this to avoid integer conversion problems,
+ // especially overflow (!) where someone changes one of the return type or the storage type but
+ // not the other.
+ Assert( (item_price_t)m_unBaseCosts[eCurrency] == m_unBaseCosts[eCurrency] );
+ return m_unBaseCosts[eCurrency];
+ }
+
+ item_price_t GetSalePrice( ECurrency eCurrency ) const
+ {
+ Assert( eCurrency >= k_ECurrencyFirst );
+ Assert( eCurrency < k_ECurrencyMax );
+ if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
+ return 0;
+#ifdef CLIENT_DLL
+ if ( m_bIsMarketItem )
+ {
+ const client_market_data_t *pClientMarketData = GetClientMarketData( GetItemDefinitionIndex(), AE_UNIQUE );
+ if ( !pClientMarketData )
+ return 0;
+ return pClientMarketData->m_unLowestPrice;
+ }
+#endif
+ // Weird-looking pattern: we're making sure that the value we're about to return fits correctly
+ // into the variable we're about to put it into. We do this to avoid integer conversion problems,
+ // especially overflow (!) where someone changes one of the return type or the storage type but
+ // not the other.
+ Assert( (item_price_t)m_unSaleCosts[eCurrency] == m_unSaleCosts[eCurrency] );
+ return m_unSaleCosts[eCurrency];
+ }
+
+ uint16 GetQuantity() const
+ {
+ return m_usQuantity;
+ }
+
+ const char* GetDate() const
+ {
+ return m_strDate.Get();
+ }
+
+ bool CanPreview() const
+ {
+ // No previewing of new items or weapons.
+ return m_bPreviewAllowed;
+ }
+
+ void SetQuantity( uint16 usQuantity )
+ {
+ Assert( usQuantity > 0 );
+ m_usQuantity = usQuantity;
+ }
+
+ void ValidatePrice( ECurrency eCurrency, item_price_t unPrice );
+
+ void SetBasePrice( ECurrency eCurrency, item_price_t unPrice )
+ {
+ Assert( eCurrency >= k_ECurrencyFirst );
+ Assert( eCurrency < k_ECurrencyMax );
+ if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
+ return;
+
+ ValidatePrice( eCurrency, unPrice );
+
+ m_unBaseCosts[eCurrency] = unPrice;
+ }
+
+ void SetSalePrice( ECurrency eCurrency, item_price_t unPrice )
+ {
+ Assert( eCurrency >= k_ECurrencyFirst );
+ Assert( eCurrency < k_ECurrencyMax );
+ if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
+ return;
+
+ ValidatePrice( eCurrency, unPrice );
+
+ // It's legal to have a sale price of zero, meaninig "this item is not on sale" in this
+ // currency.
+ // Assert( unPrice > 0 );
+ m_unSaleCosts[eCurrency] = unPrice;
+ }
+
+ void SetSteamGiftPackageID( uint32 unGiftSteamPackageID )
+ {
+ m_unGiftSteamPackageID = unGiftSteamPackageID;
+ }
+
+ void SetDate( const char* pszDate )
+ {
+ m_strDate.Set( pszDate );
+ }
+
+
+ bool IsValidCategoryTagIndex( uint32 iIndex ) const
+ {
+ AssertMsg( m_vecCategoryTags.IsValidIndex( iIndex ), "Category tag index out of range." );
+ return m_vecCategoryTags.IsValidIndex( iIndex );
+ }
+
+ uint32 GetCategoryTagCount() const
+ {
+ return m_vecCategoryTags.Count();
+ }
+
+ const char *GetCategoryTagNameFromIndex( uint32 iIndex ) const
+ {
+ if ( !IsValidCategoryTagIndex( iIndex ) )
+ return NULL;
+
+ return m_vecCategoryTags[ iIndex ].m_strName;
+ }
+
+ StoreCategoryID_t GetCategoryTagIDFromIndex( uint32 iIndex ) const;
+
+ const char *GetCategoryTagString() const
+ {
+ return m_pchCategoryTags;
+ }
+
+ bool m_bLimited; // Item is a limited sale
+ bool m_bNew; // Item is new
+ bool m_bHighlighted; // Item is highlighted
+ CUtlString m_strDate; // Date Added
+ bool m_bSoldOut; // True if the item is sold out from the store (for example if the item is a ticket or another physical item)
+ bool m_bPreviewAllowed; // Is this item previewable?
+ bool m_bIsPackItem; // Is this item a pack item? Pack items are items which are not individually for sale, but are sold via a bundle known as a "pack bundle"
+
+ bool m_bIsMarketItem; // Is Market Item Link
+
+private:
+ item_definition_index_t m_usDefIndex; // DefIndex of the item
+
+ // Private data so that we can check in the accessor functions that the data fits before returning it.
+ item_price_t m_unBaseCosts[k_ECurrencyMax]; // Costs of the items indexed by ECurrency -- if the items are on sale, this will be the current sale price
+ item_price_t m_unSaleCosts[k_ECurrencyMax]; // Original costs of the items indexed by ECurrency -- if the items are on sale, this will be the pre-sale price
+ uint16 m_usQuantity; // Quantity sold in a single purchase (ie., dueling pistols come in stacks of five)
+ float m_fRentalPriceScale; // 100.0 or greater means "unavailable to rent"
+ uint32 m_unGiftSteamPackageID; // if non-zero, when this item is purchased (including inside bundles, etc.), grant a gift copy of this Steam package
+
+ struct CategoryTag_t
+ {
+ CUtlString m_strName; // Individual tag name, like "Weapons," "New," etc.
+ StoreCategoryID_t m_unID; // The category ID
+ };
+ CCopyableUtlVector< CategoryTag_t > m_vecCategoryTags; // Category tag data
+
+ const char *m_pchCategoryTags; // All tags - this string will something like: "New" or "Weapons+New" etc.
+};
+
+#ifdef GC_DLL
+struct econ_store_timed_sale_item_t
+{
+ item_definition_index_t m_unItemDef;
+ float m_fPricePercentage; // 100.0 = regular price; 50.0 = half price
+};
+
+struct econ_store_timed_sale_t
+{
+ bool m_bSaleCurrentlyActive; // set in ::UpdatePricesForTimedSales()
+ CUtlConstString m_sIdentifier; // can't point to memory in the base KV because we toss it afterwards
+ RTime32 m_SaleStartTime;
+ RTime32 m_SaleEndTime;
+ CUtlVector<econ_store_timed_sale_item_t> m_vecSaleItems;
+
+ // Work around protected default vector constructor.
+ econ_store_timed_sale_t() { }
+ econ_store_timed_sale_t( const econ_store_timed_sale_t& other )
+ : m_bSaleCurrentlyActive( other.m_bSaleCurrentlyActive )
+ , m_sIdentifier( other.m_sIdentifier )
+ , m_SaleStartTime( other.m_SaleStartTime )
+ , m_SaleEndTime( other.m_SaleEndTime )
+ {
+ m_vecSaleItems.CopyArray( other.m_vecSaleItems.Base(), other.m_vecSaleItems.Count() );
+ }
+};
+#endif // GC_DLL
+
+// Spend xxx amount of money, get a free item from the loot list
+struct store_promotion_spend_for_free_item_t
+{
+ const CEconItemDefinition *m_pItemDef;
+ item_price_t m_rgusPriceThreshold[k_ECurrencyMax]; // Price threshold to get an item from the loot list indexed by ECurrency
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Class that represents what's currently for sale in TF
+//-----------------------------------------------------------------------------
+typedef enum
+{
+ kEconStoreSortType_Price_HighestToLowest = 0,
+ kEconStoreSortType_Price_LowestToHighest = 1,
+ kEconStoreSortType_DevName_AToZ = 2,
+ kEconStoreSortType_DevName_ZToA = 3,
+ kEconStoreSortType_Name_AToZ = 4,
+ kEconStoreSortType_Name_ZToA = 5,
+ kEconStoreSortType_ItemDefIndex = 6,
+ kEconStoreSortType_ReverseItemDefIndex = 7,
+ kEconStoreSortType_DateNewest = 8,
+ kEconStoreSortType_DateOldest = 9,
+} eEconStoreSortType;
+
+struct price_point_map_key_t
+{
+ item_price_t m_unPriceUSD;
+ ECurrency m_eCurrency;
+
+ static bool Less( const price_point_map_key_t& a, const price_point_map_key_t& b )
+ {
+ if ( a.m_eCurrency == b.m_eCurrency )
+ return a.m_unPriceUSD < b.m_unPriceUSD;
+
+ return a.m_eCurrency < b.m_eCurrency;
+ }
+};
+
+typedef CUtlMap<price_point_map_key_t, item_price_t> CurrencyPricePointMap_t;
+
+class CEconStorePriceSheet
+{
+public:
+ typedef CUtlMap<item_definition_index_t, econ_store_entry_t> StoreEntryMap_t;
+ typedef CUtlMap<const char *, float> RentalPriceScaleMap_t;
+ typedef CUtlVector<item_definition_index_t> FeaturedItems_t;
+
+ CEconStorePriceSheet();
+ ~CEconStorePriceSheet();
+
+ bool InitFromKV( KeyValues *pKVPrices );
+
+ // Gets or sets the version stamp. This is just a number the GC can use
+ // to know if the client is in sync without sending it down on every
+ // request.
+ RTime32 GetVersionStamp( void ) const { return m_RTimeVersionStamp; }
+ void SetVersionStamp( RTime32 stamp ) { m_RTimeVersionStamp = stamp; }
+
+ uint32 GetHashForAllItems() const { return m_unHashForAllItems; }
+
+ typedef CUtlMap<uint16, econ_store_entry_t> EconStoreEntryMap_t;
+ EconStoreEntryMap_t &GetEntries() { return m_mapEntries; }
+
+#ifdef GC_DLL
+ econ_store_entry_t *GetEntryWriteable( item_definition_index_t unDefIndex );
+#endif // GC_DLL
+
+ const StoreEntryMap_t &GetEntries() const { return m_mapEntries; }
+ const CEconStoreCategoryManager::StoreCategory_t *GetFeaturedItems( void ) { return &m_FeaturedItems; }
+ const econ_store_entry_t *GetEntry( item_definition_index_t usDefIndex ) const;
+
+ uint32 GetFeaturedItemIndex() const { return m_unFeaturedItemIndex; }
+ void SetFeaturedItemIndex( uint32 unIdx ) { m_unFeaturedItemIndex = unIdx; }
+
+ void SetEconStoreSortType( eEconStoreSortType eType ) { m_eEconStoreSortType = eType; }
+ eEconStoreSortType GetEconStoreSortType() { return m_eEconStoreSortType; }
+
+ const store_promotion_spend_for_free_item_t *GetStorePromotion_SpendForFreeItem() const { return &m_StorePromotionSpendForFreeItem; }
+ const CEconItemDefinition * GetStorePromotion_FirstTimePurchaseItem() const { return m_pStorePromotionFirstTimePurchaseItem; }
+ const CEconItemDefinition * GetStorePromotion_FirstTimeWebPurchaseItem() const { return m_pStorePromotionFirstTimeWebPurchaseItem; }
+
+ uint32 GetPreviewPeriod() const { return m_unPreviewPeriod; }
+ uint32 GetBonusDiscountPeriod() const { return m_unBonusDiscountPeriod; }
+ float GetPreviewPeriodDiscount() const { return m_flPreviewPeriodDiscount; }
+
+ bool BItemExistsInPriceSheet( item_definition_index_t unDefIndex ) const;
+
+ float GetRentalPriceScale( const char *pszCategory ) const
+ {
+ RentalPriceScaleMap_t::IndexType_t i = m_mapRentalPriceScales.Find( pszCategory );
+ if ( i == RentalPriceScaleMap_t::InvalidIndex() )
+ return 1.0f;
+
+ return m_mapRentalPriceScales[i];
+ }
+
+ KeyValues *GetRawData() const { return m_pKVRaw; }
+
+#ifdef GC_DLL
+ void UpdatePricesForTimedSales( const RTime32 curTime );
+ void DumpTimeSaleState( const RTime32 curTime ) const;
+#endif // GC_DLL
+
+#ifdef CLIENT_DLL
+ const FeaturedItems_t& GetFeaturedItems() const { return m_vecFeaturedItems; }
+#endif // CLIENT_DLL
+
+private:
+ bool BInitEntryFromKV( KeyValues *pKVEntry );
+#ifdef CLIENT_DLL
+ bool BInitMarketEntryFromKV( KeyValues *pKVEntry );
+#endif // CLIENT_DLL
+
+#ifdef GC_DLL
+ bool InitTimedSaleEntryFromKV( KeyValues *pKVTimedSaleEntry );
+ bool VerifyTimedSaleEntries();
+#endif // GC_DLL
+
+private:
+ void Clear();
+ uint32 CalculateHashFromItems() const;
+
+ KeyValues *m_pKVRaw;
+ RTime32 m_RTimeVersionStamp;
+ CEconStoreCategoryManager::StoreCategory_t m_FeaturedItems; // Special section, not a tab, kept outside m_vecContents
+ StoreEntryMap_t m_mapEntries;
+ RentalPriceScaleMap_t m_mapRentalPriceScales;
+ store_promotion_spend_for_free_item_t m_StorePromotionSpendForFreeItem;
+ CEconItemDefinition* m_pStorePromotionFirstTimePurchaseItem;
+ CEconItemDefinition* m_pStorePromotionFirstTimeWebPurchaseItem;
+
+#ifdef CLIENT_DLL
+ FeaturedItems_t m_vecFeaturedItems;
+#endif // CLIENT_DLL
+
+#ifdef GC_DLL
+ CUtlVector<econ_store_timed_sale_t> m_vecTimedSales;
+#endif // GC_DLL
+
+ // changes based on experiments
+ uint32 m_unFeaturedItemIndex;
+ eEconStoreSortType m_eEconStoreSortType;
+
+ uint32 m_unPreviewPeriod;
+ uint32 m_unBonusDiscountPeriod;
+ float m_flPreviewPeriodDiscount;
+ uint32 m_unHashForAllItems;
+
+ // price point lookup
+ CurrencyPricePointMap_t m_mapCurrencyPricePoints;
+};
+
+#ifdef CLIENT_DLL
+void MakeMoneyString( wchar_t *pchDest, uint32 nDest, item_price_t unPrice, ECurrency eCurrencyCode );
+
+bool ShouldUseNewStore();
+int GetStoreVersion();
+#endif // CLIENT_DLL
+
+const CEconStorePriceSheet *GetEconPriceSheet();
+
+#endif // ECON_STORE_H