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.

621 lines
23 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Common objects and utilities related to the in-game item store
  4. //
  5. //=============================================================================
  6. #ifndef ECON_STORE_H
  7. #define ECON_STORE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "UtlSortVector.h"
  12. #include "vstdlib/IKeyValuesSystem.h"
  13. #include "econ/econ_storecategory.h"
  14. #ifdef CLIENT_DLL
  15. #include "client_community_market.h"
  16. #endif // CLIENT_DLL
  17. //-----------------------------------------------------------------------------
  18. // Purpose: Error code enum for purchase messages
  19. //-----------------------------------------------------------------------------
  20. enum EPurchaseResult
  21. {
  22. k_EPurchaseResultOK = 1, // Success
  23. k_EPurchaseResultFail = 2, // Generic error
  24. k_EPurchaseResultInvalidParam = 3, // Invalid parameter
  25. k_EPurchaseResultInternalError = 4, // Internal error
  26. k_EPurchaseResultNotApproved = 5, // Tried to finalize a transaction that has not yet been approved
  27. k_EPurchaseResultAlreadyCommitted = 6, // Tried to finalize a transaction that has already been committed
  28. k_EPurchaseResultUserNotLoggedIn = 7, // User is not logged into Steam
  29. k_EPurchaseResultWrongCurrency = 8, // Microtransaction's currency does not match user's wallet currency
  30. k_EPurchaseResultAccountError = 9, // User's account does not exist or is temporarily unavailable
  31. k_EPurchaseResultInvalidItem = 10, // User is trying to purchase an item that doesn't exist or is not for sale
  32. k_EPurchaseResultNotEnoughBackpackSpace = 11, // User did not have enough backpack space
  33. k_EPurchaseResultLimitedQuantityItemsUnavailable = 12, // User tried to purchase limited-quantity items but there weren't enough left in stock
  34. k_EPurchaseResultInsufficientFunds = 100, // User does not have wallet funds
  35. k_EPurchaseResultTimedOut = 101, // Time limit for finalization has been exceeded
  36. k_EPurchaseResultAcctDisabled = 102, // Steam account is disabled
  37. k_EPurchaseResultAcctCannotPurchase = 103, // Steam account is not allowed to make a purchase
  38. k_EMicroTxnResultFailedFraudChecks = 104, // Fraud checks inside of Steam failed
  39. k_EPurchaseResultOldPriceSheet = 150, // Information on the purchase didn't match the current price sheet
  40. k_EPurchaseResultTxnNotFound = 151 // Could not find the transaction specified
  41. };
  42. const char *PchNameFromEPurchaseResult( EPurchaseResult ePurchaseState );
  43. //-----------------------------------------------------------------------------
  44. // Purpose: State of a transaction
  45. //
  46. // WARNING: VALUES STORED IN DATABASE. DO NOT RENUMBER!!!
  47. //-----------------------------------------------------------------------------
  48. enum EPurchaseState
  49. {
  50. k_EPurchaseStateInvalid = 0, // Invalid
  51. k_EPurchaseStateInit = 1, // We have sent InitPurchase to Steam
  52. k_EPurchaseStateWaitingForAuthorization = 2, // We have gotten initial authorization from Steam. Waiting for user to authorize.
  53. k_EPurchaseStatePending = 3, // We are attempting to commit the transaction
  54. k_EPurchaseStateComplete = 4, // The transaction was successful
  55. k_EPurchaseStateFailed = 5, // The transaction failed
  56. k_EPurchaseStateCanceled = 6, // The transaction was canceled
  57. k_EPurchaseStateRefunded = 7, // The transaction was refunded
  58. k_EPurchaseStateChargeback = 8, // The transaction was charged back
  59. k_EPurchaseStateChargebackReversed = 9, // A chargeback has failed and we got the money
  60. k_EPurchaseStateLast = k_EPurchaseStateChargebackReversed,
  61. };
  62. const char *PchNameFromEPurchaseState( EPurchaseState ePurchaseState );
  63. // DO NOT RENUMBER! These values are stored in the audit log table.
  64. enum EGCTransactionAuditReason
  65. {
  66. k_EGCTransactionAudit_GCTransactionCompleted = 0, // The transaction completed successfully on the GC.
  67. k_EGCTransactionAudit_GCTransactionInit = 1, // The transaction was initialized.
  68. k_EGCTransactionAudit_GCTransactionPostInit = 2, // The result of attempting to initialize the transaction. This is where the SteamTxnID is set.
  69. k_EGCTransactionAudit_GCTransactionFinalize = 3, // We have started to finalize the transaction (so probably set it to pending).
  70. k_EGCTransactionAudit_GCTransactionFinalizeFailed = 4, // Our attempt to finalize the transaction failed for some reason (not due to a timeout).
  71. k_EGCTransactionAudit_GCTransactionCanceled = 5, // The client requested that we cancel the transaction.
  72. k_EGCTransactionAudit_SteamFailedMismatch = 6, // Steam failed the transaction but we did not.
  73. k_EGCTransactionAudit_GCRemovePurchasedItems = 7, // We are attempting to remove the purchased items from their backpack (due to rollback or failure).
  74. 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.
  75. 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.
  76. k_EGCTransactionAuditLast = k_EGCTransactionAudit_GCTransactionCompletedPostChargeback,
  77. };
  78. const char *PchNameFromEGCTransactionAuditReason( EGCTransactionAuditReason eAuditReason );
  79. enum EGCTransactionAuditInsertReason
  80. {
  81. k_EGCTransactionAuditInsert_Invalid = 0, //
  82. k_EGCTransactionAuditInsert_CDKey = 1, // A CD Key was used for this transaction.
  83. k_EGCTransactionAuditInsert_SettlementNoMatch_Failed = 2, // We inserted a failed record during settlement to unblock the process.
  84. k_EGCTransactionAuditInsert_SettlementNoMatch_Pending = 3, // We inserted a pending record during settlement to unblock the process.
  85. k_EGCTransactionAuditInsertLast = k_EGCTransactionAuditInsert_SettlementNoMatch_Pending,
  86. };
  87. //-----------------------------------------------------------------------------
  88. // Purpose: Currencies we support
  89. //
  90. // WARNING: VALUES STORED IN DATABASE. DO NOT RENUMBER!!!
  91. // WARNING: THESE DON'T MATCH THE STEAM NUMERIC IDS!!! WE TALK USING CURRENCY
  92. // CODES LIKE "VND" AND IF YOU SAY "15" TERRIBLE THINGS WILL HAPPEN
  93. //-----------------------------------------------------------------------------
  94. enum ECurrency
  95. {
  96. k_ECurrencyFirst = 0,
  97. k_ECurrencyUSD = 0,
  98. k_ECurrencyGBP = 1,
  99. k_ECurrencyEUR = 2,
  100. k_ECurrencyRUB = 3,
  101. k_ECurrencyBRL = 4,
  102. // space for Dota currencies
  103. k_ECurrencyJPY = 8,
  104. k_ECurrencyNOK = 9,
  105. k_ECurrencyIDR = 10,
  106. k_ECurrencyMYR = 11,
  107. k_ECurrencyPHP = 12,
  108. k_ECurrencySGD = 13,
  109. k_ECurrencyTHB = 14,
  110. k_ECurrencyVND = 15,
  111. k_ECurrencyKRW = 16,
  112. k_ECurrencyTRY = 17,
  113. k_ECurrencyUAH = 18,
  114. k_ECurrencyMXN = 19,
  115. k_ECurrencyCAD = 20,
  116. k_ECurrencyAUD = 21,
  117. k_ECurrencyNZD = 22,
  118. k_ECurrencyPLN = 23,
  119. k_ECurrencyCHF = 24,
  120. k_ECurrencyCNY = 25,
  121. k_ECurrencyTWD = 26,
  122. k_ECurrencyHKD = 27,
  123. k_ECurrencyINR = 28,
  124. k_ECurrencyAED = 29,
  125. k_ECurrencySAR = 30,
  126. k_ECurrencyZAR = 31,
  127. k_ECurrencyCOP = 32,
  128. k_ECurrencyPEN = 33,
  129. k_ECurrencyCLP = 34,
  130. // NOTE: Not actually the Maximum currency value, but the Terminator for the possible currency code range.
  131. k_ECurrencyMax = 35,
  132. // make this a big number so we can avoid having to move it when we add another currency type
  133. k_ECurrencyInvalid = 255,
  134. k_ECurrencyCDKeyTransaction = k_ECurrencyInvalid,
  135. };
  136. // Macro for looping across all valid currencies
  137. #define FOR_EACH_CURRENCY( _i ) for ( ECurrency _i = GetFirstValidCurrency(); _i != k_ECurrencyInvalid; _i = GetNextValidCurrency( _i ) )
  138. const char *PchNameFromECurrency( ECurrency eCurrency ); // NOTE: Defined with ENUMSTRINGS_START/ENUMSTRINGS_REVERSE macros
  139. ECurrency ECurrencyFromName( const char *pchName ); //
  140. inline bool BIsCurrencyValid( ECurrency eCurrency )
  141. {
  142. switch ( eCurrency )
  143. {
  144. case k_ECurrencyUSD:
  145. case k_ECurrencyGBP:
  146. case k_ECurrencyEUR:
  147. case k_ECurrencyRUB:
  148. case k_ECurrencyBRL:
  149. case k_ECurrencyJPY:
  150. case k_ECurrencyNOK:
  151. case k_ECurrencyIDR:
  152. case k_ECurrencyMYR:
  153. case k_ECurrencyPHP:
  154. case k_ECurrencySGD:
  155. case k_ECurrencyTHB:
  156. case k_ECurrencyVND:
  157. case k_ECurrencyKRW:
  158. case k_ECurrencyTRY:
  159. case k_ECurrencyUAH:
  160. case k_ECurrencyMXN:
  161. case k_ECurrencyCAD:
  162. case k_ECurrencyAUD:
  163. case k_ECurrencyNZD:
  164. //case k_ECurrencyPLN:
  165. case k_ECurrencyCHF:
  166. case k_ECurrencyCNY:
  167. case k_ECurrencyTWD:
  168. case k_ECurrencyHKD:
  169. case k_ECurrencyINR:
  170. case k_ECurrencyAED:
  171. case k_ECurrencySAR:
  172. case k_ECurrencyZAR:
  173. case k_ECurrencyCOP:
  174. case k_ECurrencyPEN:
  175. case k_ECurrencyCLP:
  176. return true;
  177. }
  178. return false;
  179. }
  180. inline ECurrency GetFirstValidCurrency()
  181. {
  182. for ( int i = k_ECurrencyFirst; i < k_ECurrencyMax; i++ )
  183. {
  184. if ( BIsCurrencyValid( (ECurrency)i ) )
  185. return (ECurrency)i;
  186. }
  187. return k_ECurrencyInvalid;
  188. }
  189. inline ECurrency GetNextValidCurrency( ECurrency ePrevious )
  190. {
  191. for ( int i = ePrevious + 1; i < k_ECurrencyMax; i++ )
  192. {
  193. if ( BIsCurrencyValid( (ECurrency)i ) )
  194. return (ECurrency)i;
  195. }
  196. return k_ECurrencyInvalid;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Purpose: Simple struct for pairing a sort type with a localization string
  200. //-----------------------------------------------------------------------------
  201. struct ItemSortTypeData_t
  202. {
  203. const char *szSortDesc; // localization string
  204. uint32 iSortType; // maps to the GC-specific sort value
  205. };
  206. // Description of a single item for sale
  207. struct econ_store_entry_t
  208. {
  209. // Constructor
  210. econ_store_entry_t()
  211. : m_pchCategoryTags( NULL ),
  212. m_unGiftSteamPackageID( 0 ),
  213. m_bHighlighted( false )
  214. {
  215. V_memset( m_unBaseCosts, 0, sizeof(m_unBaseCosts) );
  216. V_memset( m_unSaleCosts, 0, sizeof(m_unSaleCosts) );
  217. }
  218. void SetItemDefinitionIndex( item_definition_index_t usDefIndex );
  219. item_definition_index_t GetItemDefinitionIndex() const { return m_usDefIndex; }
  220. void InitCategoryTags( const char *pTags ); // Sets m_pchCategoryTags and initializes m_vecTagIds and m_fRentalPriceScale
  221. bool IsListedInCategory( StoreCategoryID_t unID ) const; // Is this item listed in the given category?
  222. bool IsListedInSubcategories( const CEconStoreCategoryManager::StoreCategory_t &Category ) const; // Is this item listed in one of Category's subcategories?
  223. bool IsListedInCategoryOrSubcategories( const CEconStoreCategoryManager::StoreCategory_t &Category ) const; // Is this item listed in Category or one of Category's subcategories?
  224. bool IsOnSale( ECurrency eCurrency ) const;
  225. bool IsRentable() const;
  226. #ifdef CLIENT_DLL
  227. 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
  228. #endif // CLIENT_DLL
  229. item_price_t GetCurrentPrice( ECurrency eCurrency ) const;
  230. float GetRentalPriceScale() const;
  231. uint32 GetGiftSteamPackageID() const { return m_unGiftSteamPackageID; }
  232. // Helper function -- so we do this calculation in a single place.
  233. static item_price_t GetDiscountedPrice( ECurrency eCurrency, item_price_t unBasePrice, float fDiscountPercentage );
  234. static item_price_t CalculateSalePrice( const econ_store_entry_t* pSaleStoreEntry, ECurrency eCurrency, float fDiscountPercentage, int32 *out_pAdjustedDiscountPercentage = NULL );
  235. item_price_t GetBasePrice( ECurrency eCurrency ) const
  236. {
  237. Assert( eCurrency >= k_ECurrencyFirst );
  238. Assert( eCurrency < k_ECurrencyMax );
  239. if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
  240. return 0;
  241. #ifdef CLIENT_DLL
  242. if ( m_bIsMarketItem )
  243. {
  244. const client_market_data_t *pClientMarketData = GetClientMarketData( GetItemDefinitionIndex(), AE_UNIQUE );
  245. if ( !pClientMarketData )
  246. return 0;
  247. return pClientMarketData->m_unLowestPrice;
  248. }
  249. #endif
  250. // Weird-looking pattern: we're making sure that the value we're about to return fits correctly
  251. // into the variable we're about to put it into. We do this to avoid integer conversion problems,
  252. // especially overflow (!) where someone changes one of the return type or the storage type but
  253. // not the other.
  254. Assert( (item_price_t)m_unBaseCosts[eCurrency] == m_unBaseCosts[eCurrency] );
  255. return m_unBaseCosts[eCurrency];
  256. }
  257. item_price_t GetSalePrice( ECurrency eCurrency ) const
  258. {
  259. Assert( eCurrency >= k_ECurrencyFirst );
  260. Assert( eCurrency < k_ECurrencyMax );
  261. if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
  262. return 0;
  263. #ifdef CLIENT_DLL
  264. if ( m_bIsMarketItem )
  265. {
  266. const client_market_data_t *pClientMarketData = GetClientMarketData( GetItemDefinitionIndex(), AE_UNIQUE );
  267. if ( !pClientMarketData )
  268. return 0;
  269. return pClientMarketData->m_unLowestPrice;
  270. }
  271. #endif
  272. // Weird-looking pattern: we're making sure that the value we're about to return fits correctly
  273. // into the variable we're about to put it into. We do this to avoid integer conversion problems,
  274. // especially overflow (!) where someone changes one of the return type or the storage type but
  275. // not the other.
  276. Assert( (item_price_t)m_unSaleCosts[eCurrency] == m_unSaleCosts[eCurrency] );
  277. return m_unSaleCosts[eCurrency];
  278. }
  279. uint16 GetQuantity() const
  280. {
  281. return m_usQuantity;
  282. }
  283. const char* GetDate() const
  284. {
  285. return m_strDate.Get();
  286. }
  287. bool CanPreview() const
  288. {
  289. // No previewing of new items or weapons.
  290. return m_bPreviewAllowed;
  291. }
  292. void SetQuantity( uint16 usQuantity )
  293. {
  294. Assert( usQuantity > 0 );
  295. m_usQuantity = usQuantity;
  296. }
  297. void ValidatePrice( ECurrency eCurrency, item_price_t unPrice );
  298. void SetBasePrice( ECurrency eCurrency, item_price_t unPrice )
  299. {
  300. Assert( eCurrency >= k_ECurrencyFirst );
  301. Assert( eCurrency < k_ECurrencyMax );
  302. if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
  303. return;
  304. ValidatePrice( eCurrency, unPrice );
  305. m_unBaseCosts[eCurrency] = unPrice;
  306. }
  307. void SetSalePrice( ECurrency eCurrency, item_price_t unPrice )
  308. {
  309. Assert( eCurrency >= k_ECurrencyFirst );
  310. Assert( eCurrency < k_ECurrencyMax );
  311. if ( !( eCurrency >= 0 && eCurrency < k_ECurrencyMax ) )
  312. return;
  313. ValidatePrice( eCurrency, unPrice );
  314. // It's legal to have a sale price of zero, meaninig "this item is not on sale" in this
  315. // currency.
  316. // Assert( unPrice > 0 );
  317. m_unSaleCosts[eCurrency] = unPrice;
  318. }
  319. void SetSteamGiftPackageID( uint32 unGiftSteamPackageID )
  320. {
  321. m_unGiftSteamPackageID = unGiftSteamPackageID;
  322. }
  323. void SetDate( const char* pszDate )
  324. {
  325. m_strDate.Set( pszDate );
  326. }
  327. bool IsValidCategoryTagIndex( uint32 iIndex ) const
  328. {
  329. AssertMsg( m_vecCategoryTags.IsValidIndex( iIndex ), "Category tag index out of range." );
  330. return m_vecCategoryTags.IsValidIndex( iIndex );
  331. }
  332. uint32 GetCategoryTagCount() const
  333. {
  334. return m_vecCategoryTags.Count();
  335. }
  336. const char *GetCategoryTagNameFromIndex( uint32 iIndex ) const
  337. {
  338. if ( !IsValidCategoryTagIndex( iIndex ) )
  339. return NULL;
  340. return m_vecCategoryTags[ iIndex ].m_strName;
  341. }
  342. StoreCategoryID_t GetCategoryTagIDFromIndex( uint32 iIndex ) const;
  343. const char *GetCategoryTagString() const
  344. {
  345. return m_pchCategoryTags;
  346. }
  347. bool m_bLimited; // Item is a limited sale
  348. bool m_bNew; // Item is new
  349. bool m_bHighlighted; // Item is highlighted
  350. CUtlString m_strDate; // Date Added
  351. 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)
  352. bool m_bPreviewAllowed; // Is this item previewable?
  353. 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"
  354. bool m_bIsMarketItem; // Is Market Item Link
  355. private:
  356. item_definition_index_t m_usDefIndex; // DefIndex of the item
  357. // Private data so that we can check in the accessor functions that the data fits before returning it.
  358. 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
  359. 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
  360. uint16 m_usQuantity; // Quantity sold in a single purchase (ie., dueling pistols come in stacks of five)
  361. float m_fRentalPriceScale; // 100.0 or greater means "unavailable to rent"
  362. uint32 m_unGiftSteamPackageID; // if non-zero, when this item is purchased (including inside bundles, etc.), grant a gift copy of this Steam package
  363. struct CategoryTag_t
  364. {
  365. CUtlString m_strName; // Individual tag name, like "Weapons," "New," etc.
  366. StoreCategoryID_t m_unID; // The category ID
  367. };
  368. CCopyableUtlVector< CategoryTag_t > m_vecCategoryTags; // Category tag data
  369. const char *m_pchCategoryTags; // All tags - this string will something like: "New" or "Weapons+New" etc.
  370. };
  371. #ifdef GC_DLL
  372. struct econ_store_timed_sale_item_t
  373. {
  374. item_definition_index_t m_unItemDef;
  375. float m_fPricePercentage; // 100.0 = regular price; 50.0 = half price
  376. };
  377. struct econ_store_timed_sale_t
  378. {
  379. bool m_bSaleCurrentlyActive; // set in ::UpdatePricesForTimedSales()
  380. CUtlConstString m_sIdentifier; // can't point to memory in the base KV because we toss it afterwards
  381. RTime32 m_SaleStartTime;
  382. RTime32 m_SaleEndTime;
  383. CUtlVector<econ_store_timed_sale_item_t> m_vecSaleItems;
  384. // Work around protected default vector constructor.
  385. econ_store_timed_sale_t() { }
  386. econ_store_timed_sale_t( const econ_store_timed_sale_t& other )
  387. : m_bSaleCurrentlyActive( other.m_bSaleCurrentlyActive )
  388. , m_sIdentifier( other.m_sIdentifier )
  389. , m_SaleStartTime( other.m_SaleStartTime )
  390. , m_SaleEndTime( other.m_SaleEndTime )
  391. {
  392. m_vecSaleItems.CopyArray( other.m_vecSaleItems.Base(), other.m_vecSaleItems.Count() );
  393. }
  394. };
  395. #endif // GC_DLL
  396. // Spend xxx amount of money, get a free item from the loot list
  397. struct store_promotion_spend_for_free_item_t
  398. {
  399. const CEconItemDefinition *m_pItemDef;
  400. item_price_t m_rgusPriceThreshold[k_ECurrencyMax]; // Price threshold to get an item from the loot list indexed by ECurrency
  401. };
  402. //-----------------------------------------------------------------------------
  403. // Purpose: Class that represents what's currently for sale in TF
  404. //-----------------------------------------------------------------------------
  405. typedef enum
  406. {
  407. kEconStoreSortType_Price_HighestToLowest = 0,
  408. kEconStoreSortType_Price_LowestToHighest = 1,
  409. kEconStoreSortType_DevName_AToZ = 2,
  410. kEconStoreSortType_DevName_ZToA = 3,
  411. kEconStoreSortType_Name_AToZ = 4,
  412. kEconStoreSortType_Name_ZToA = 5,
  413. kEconStoreSortType_ItemDefIndex = 6,
  414. kEconStoreSortType_ReverseItemDefIndex = 7,
  415. kEconStoreSortType_DateNewest = 8,
  416. kEconStoreSortType_DateOldest = 9,
  417. } eEconStoreSortType;
  418. struct price_point_map_key_t
  419. {
  420. item_price_t m_unPriceUSD;
  421. ECurrency m_eCurrency;
  422. static bool Less( const price_point_map_key_t& a, const price_point_map_key_t& b )
  423. {
  424. if ( a.m_eCurrency == b.m_eCurrency )
  425. return a.m_unPriceUSD < b.m_unPriceUSD;
  426. return a.m_eCurrency < b.m_eCurrency;
  427. }
  428. };
  429. typedef CUtlMap<price_point_map_key_t, item_price_t> CurrencyPricePointMap_t;
  430. class CEconStorePriceSheet
  431. {
  432. public:
  433. typedef CUtlMap<item_definition_index_t, econ_store_entry_t> StoreEntryMap_t;
  434. typedef CUtlMap<const char *, float> RentalPriceScaleMap_t;
  435. typedef CUtlVector<item_definition_index_t> FeaturedItems_t;
  436. CEconStorePriceSheet();
  437. ~CEconStorePriceSheet();
  438. bool InitFromKV( KeyValues *pKVPrices );
  439. // Gets or sets the version stamp. This is just a number the GC can use
  440. // to know if the client is in sync without sending it down on every
  441. // request.
  442. RTime32 GetVersionStamp( void ) const { return m_RTimeVersionStamp; }
  443. void SetVersionStamp( RTime32 stamp ) { m_RTimeVersionStamp = stamp; }
  444. uint32 GetHashForAllItems() const { return m_unHashForAllItems; }
  445. typedef CUtlMap<uint16, econ_store_entry_t> EconStoreEntryMap_t;
  446. EconStoreEntryMap_t &GetEntries() { return m_mapEntries; }
  447. #ifdef GC_DLL
  448. econ_store_entry_t *GetEntryWriteable( item_definition_index_t unDefIndex );
  449. #endif // GC_DLL
  450. const StoreEntryMap_t &GetEntries() const { return m_mapEntries; }
  451. const CEconStoreCategoryManager::StoreCategory_t *GetFeaturedItems( void ) { return &m_FeaturedItems; }
  452. const econ_store_entry_t *GetEntry( item_definition_index_t usDefIndex ) const;
  453. uint32 GetFeaturedItemIndex() const { return m_unFeaturedItemIndex; }
  454. void SetFeaturedItemIndex( uint32 unIdx ) { m_unFeaturedItemIndex = unIdx; }
  455. void SetEconStoreSortType( eEconStoreSortType eType ) { m_eEconStoreSortType = eType; }
  456. eEconStoreSortType GetEconStoreSortType() { return m_eEconStoreSortType; }
  457. const store_promotion_spend_for_free_item_t *GetStorePromotion_SpendForFreeItem() const { return &m_StorePromotionSpendForFreeItem; }
  458. const CEconItemDefinition * GetStorePromotion_FirstTimePurchaseItem() const { return m_pStorePromotionFirstTimePurchaseItem; }
  459. const CEconItemDefinition * GetStorePromotion_FirstTimeWebPurchaseItem() const { return m_pStorePromotionFirstTimeWebPurchaseItem; }
  460. uint32 GetPreviewPeriod() const { return m_unPreviewPeriod; }
  461. uint32 GetBonusDiscountPeriod() const { return m_unBonusDiscountPeriod; }
  462. float GetPreviewPeriodDiscount() const { return m_flPreviewPeriodDiscount; }
  463. bool BItemExistsInPriceSheet( item_definition_index_t unDefIndex ) const;
  464. float GetRentalPriceScale( const char *pszCategory ) const
  465. {
  466. RentalPriceScaleMap_t::IndexType_t i = m_mapRentalPriceScales.Find( pszCategory );
  467. if ( i == RentalPriceScaleMap_t::InvalidIndex() )
  468. return 1.0f;
  469. return m_mapRentalPriceScales[i];
  470. }
  471. KeyValues *GetRawData() const { return m_pKVRaw; }
  472. #ifdef GC_DLL
  473. void UpdatePricesForTimedSales( const RTime32 curTime );
  474. void DumpTimeSaleState( const RTime32 curTime ) const;
  475. #endif // GC_DLL
  476. #ifdef CLIENT_DLL
  477. const FeaturedItems_t& GetFeaturedItems() const { return m_vecFeaturedItems; }
  478. #endif // CLIENT_DLL
  479. private:
  480. bool BInitEntryFromKV( KeyValues *pKVEntry );
  481. #ifdef CLIENT_DLL
  482. bool BInitMarketEntryFromKV( KeyValues *pKVEntry );
  483. #endif // CLIENT_DLL
  484. #ifdef GC_DLL
  485. bool InitTimedSaleEntryFromKV( KeyValues *pKVTimedSaleEntry );
  486. bool VerifyTimedSaleEntries();
  487. #endif // GC_DLL
  488. private:
  489. void Clear();
  490. uint32 CalculateHashFromItems() const;
  491. KeyValues *m_pKVRaw;
  492. RTime32 m_RTimeVersionStamp;
  493. CEconStoreCategoryManager::StoreCategory_t m_FeaturedItems; // Special section, not a tab, kept outside m_vecContents
  494. StoreEntryMap_t m_mapEntries;
  495. RentalPriceScaleMap_t m_mapRentalPriceScales;
  496. store_promotion_spend_for_free_item_t m_StorePromotionSpendForFreeItem;
  497. CEconItemDefinition* m_pStorePromotionFirstTimePurchaseItem;
  498. CEconItemDefinition* m_pStorePromotionFirstTimeWebPurchaseItem;
  499. #ifdef CLIENT_DLL
  500. FeaturedItems_t m_vecFeaturedItems;
  501. #endif // CLIENT_DLL
  502. #ifdef GC_DLL
  503. CUtlVector<econ_store_timed_sale_t> m_vecTimedSales;
  504. #endif // GC_DLL
  505. // changes based on experiments
  506. uint32 m_unFeaturedItemIndex;
  507. eEconStoreSortType m_eEconStoreSortType;
  508. uint32 m_unPreviewPeriod;
  509. uint32 m_unBonusDiscountPeriod;
  510. float m_flPreviewPeriodDiscount;
  511. uint32 m_unHashForAllItems;
  512. // price point lookup
  513. CurrencyPricePointMap_t m_mapCurrencyPricePoints;
  514. };
  515. #ifdef CLIENT_DLL
  516. void MakeMoneyString( wchar_t *pchDest, uint32 nDest, item_price_t unPrice, ECurrency eCurrencyCode );
  517. bool ShouldUseNewStore();
  518. int GetStoreVersion();
  519. #endif // CLIENT_DLL
  520. const CEconStorePriceSheet *GetEconPriceSheet();
  521. #endif // ECON_STORE_H