summaryrefslogtreecommitdiff
path: root/game/shared/econ/econ_storecategory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/econ/econ_storecategory.cpp')
-rw-r--r--game/shared/econ/econ_storecategory.cpp267
1 files changed, 267 insertions, 0 deletions
diff --git a/game/shared/econ/econ_storecategory.cpp b/game/shared/econ/econ_storecategory.cpp
new file mode 100644
index 0000000..610f2da
--- /dev/null
+++ b/game/shared/econ/econ_storecategory.cpp
@@ -0,0 +1,267 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Base class for generating store meta data. Abstract methods need
+// to be overridden on a per-product basis.
+//
+//-------------------------------------------------------------------------------------------------------------------------------
+
+#include "cbase.h"
+#include "econ_storecategory.h"
+#include "econ_store.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Invalid = (StoreCategoryID_t)0;
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_New = CEconStoreCategoryManager::GetCategoryID( "New" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Weapons = CEconStoreCategoryManager::GetCategoryID( "Weapons" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Limited = CEconStoreCategoryManager::GetCategoryID( "Limited" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Maps = CEconStoreCategoryManager::GetCategoryID( "Maps" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Cosmetics = CEconStoreCategoryManager::GetCategoryID( "Cosmetics" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Taunts = CEconStoreCategoryManager::GetCategoryID( "Taunts" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Tools = CEconStoreCategoryManager::GetCategoryID( "Tools" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Bundles = CEconStoreCategoryManager::GetCategoryID( "Bundles" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Collections= CEconStoreCategoryManager::GetCategoryID( "Collections" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Popular = CEconStoreCategoryManager::GetCategoryID( "Popular" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_OnSale = CEconStoreCategoryManager::GetCategoryID( "OnSale" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Featured = CEconStoreCategoryManager::GetCategoryID( "Featured" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_ClassBundles = CEconStoreCategoryManager::GetCategoryID( "Class_Bundles" );
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Highlighted = CEconStoreCategoryManager::GetCategoryID( "Highlighted" );
+
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+CEconStoreCategoryManager::CEconStoreCategoryManager()
+{
+ m_unHomeCategoryID = k_CategoryID_Invalid;
+}
+
+bool CEconStoreCategoryManager::BInit( CEconStorePriceSheet *pPriceSheet, KeyValues *pStoreMetaDataKV )
+{
+ KeyValues *pCategoriesKV = pStoreMetaDataKV->FindKey( "categories" );
+ if ( !pCategoriesKV )
+ {
+ AssertMsg( 0, "Could not find 'categories' subkey!" );
+ return false;
+ }
+
+ FOR_EACH_TRUE_SUBKEY( pCategoriesKV, pKVCurCategory )
+ {
+ const int iIndex = m_vecCategories.AddToTail();
+ StoreCategory_t &curCategory = m_vecCategories[ iIndex ];
+ if ( !BInitCategory( pPriceSheet, &curCategory, pKVCurCategory ) )
+ return false;
+
+ // If the current category is the home page, cache off its ID
+ if ( curCategory.m_bIsHome )
+ {
+ m_unHomeCategoryID = curCategory.m_unID;
+ }
+ }
+
+ // Verify that any parents point to valid categories
+ FOR_EACH_VEC( m_vecCategories, i )
+ {
+ const StoreCategory_t &curCategory = m_vecCategories[i];
+
+ // Skip current category if it refers to invalid, which is fine
+ if ( curCategory.m_unParentCategoryID == k_CategoryID_Invalid )
+ continue;
+
+ // A category can't be a parent to itself
+ if ( curCategory.m_unID == curCategory.m_unParentCategoryID )
+ {
+ AssertMsg( 0, "Store category %s is using itself as a parent category!", curCategory.m_pchName );
+ }
+
+ // Attempt to find the current section's parent ID
+ bool bFound = false;
+ FOR_EACH_VEC( m_vecCategories, j )
+ {
+ // Don't compare against self
+ if ( i == j )
+ continue;
+
+ if ( m_vecCategories[j].m_unID == curCategory.m_unParentCategoryID )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If we couldn't find the current section's parent ID, assert
+ if ( !bFound )
+ {
+ AssertMsg( 0, "Category %s refers to an unknown parent category - check your spelling!", curCategory.m_pchName );
+ }
+ }
+
+ // Setup child category lists - looping twice to keep this code clean and easy to read
+ FOR_EACH_VEC( m_vecCategories, i )
+ {
+ const StoreCategory_t &curCategory = m_vecCategories[i];
+
+ if ( k_CategoryID_Invalid == curCategory.m_unParentCategoryID )
+ continue;
+
+ StoreCategory_t *pParentCategory = GetStoreCategoryFromID( curCategory.m_unParentCategoryID );
+ if ( !pParentCategory )
+ continue;
+
+ pParentCategory->m_vecSubcategories.AddToTail( &curCategory );
+ }
+
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+bool CEconStoreCategoryManager::BInitCategory( CEconStorePriceSheet *pPriceSheet, StoreCategory_t *pCategory, KeyValues* pKVTab )
+{
+ const char *pDefaultResFile = "Resource/UI/econ/store/v2/StorePage.res";
+
+ // Get the main category name
+ const char* pCategoryName = pKVTab->GetName();
+ if ( !pCategoryName || !pCategoryName[0] )
+ {
+ AssertMsg( 0, "Invalid category name!" );
+ return false;
+ }
+
+ const bool bIsHome = pKVTab->GetBool( "home", false );
+ pCategory->m_bIsHome = bIsHome;
+
+ pCategory->m_pchRawName = pCategoryName;
+ pCategory->m_unID = GetCategoryID( pCategoryName );
+
+ pCategory->m_bUseLargeCells = pKVTab->GetBool( "use_large_cells", false );
+ pCategory->m_bVisible = pKVTab->GetBool( "visible", true );
+ pCategory->m_bInGameOnly = pKVTab->GetBool( "ingame_only", false );
+ pCategory->m_bDefaultTab = pKVTab->GetBool( "default", false );
+
+#if defined( GC_DLL )
+ // Until we replace the in-game store with the web store, we have this hacky override property, so
+ // that we can call the home page "HOME" in the game client and "TOP SELLERS" on the web. The home page
+ // will be evolving shortly to include a lot more than just a list of top sellers.
+ const char *pchLabelTokenWebOverride = pKVTab->GetString( "web_label_token_override", NULL );
+#else
+ const char *pchLabelTokenWebOverride = NULL;
+#endif
+ pCategory->m_pchName = pchLabelTokenWebOverride ? pchLabelTokenWebOverride : pKVTab->GetString( "label_token", "#Store_Unknown" );
+
+ pCategory->m_pchPageClass = pKVTab->GetString( "page_class", "CStorePage" );
+ pCategory->m_pchPageRes = pKVTab->GetString( "page_res", pDefaultResFile );
+ pCategory->m_pchSortType = pKVTab->GetString( "sort_type", "" );
+
+ // Important for web store but not needed for VGUI store
+#if defined( GC_DLL )
+ if ( !bIsHome )
+ {
+ const char *pchDropdownPrefabName = pKVTab->GetString( "dropdown_prefab", NULL );
+ pCategory->m_pDropdownPrefab = GEconStoreMetaData()->FindDropdownPrefab( pchDropdownPrefabName );
+ if ( !pCategory->m_pDropdownPrefab )
+ {
+ AssertMsg( pCategory->m_pDropdownPrefab, CFmtStr( "Invalid dropdown prefab name, '%s'!", pchDropdownPrefabName ).Access() );
+ return false;
+ }
+ }
+ else
+ {
+ pCategory->m_pDropdownPrefab = NULL;
+ }
+#endif
+
+ // Look for a parent category for non-home categories
+ if ( !bIsHome )
+ {
+ const char *pParentCategoryName = pKVTab->GetString( "parent", NULL );
+ if ( pParentCategoryName )
+ {
+ pCategory->m_unParentCategoryID = GetCategoryID( pParentCategoryName );
+ }
+ else
+ {
+ pCategory->m_unParentCategoryID = k_CategoryID_Invalid;
+ }
+ }
+
+ return true;
+}
+
+bool CEconStoreCategoryManager::BOnPriceSheetLoaded( CEconStorePriceSheet *pPriceSheet )
+{
+ // Go through all categories/subcategories and add a list of items to each.
+ // If an item belongs to a subcategory, it will also be added to its parent category. For example,
+ // a hat will be added to both the "hats" subcategory and the "items" parent category.
+ FOR_EACH_VEC( m_vecCategories, iCategory )
+ {
+ StoreCategory_t &Category = m_vecCategories[iCategory];
+
+ // find all entries that match
+ const CEconStorePriceSheet::EconStoreEntryMap_t &mapEntries = pPriceSheet->GetEntries();
+ FOR_EACH_MAP_FAST( mapEntries, idx )
+ {
+ const econ_store_entry_t &entry = mapEntries[idx];
+
+ if ( entry.IsListedInCategoryOrSubcategories( Category ) )
+ {
+ Category.m_vecEntries.InsertNoSort( entry.GetItemDefinitionIndex() );
+ }
+ }
+ }
+
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+/*static*/ StoreCategoryID_t CEconStoreCategoryManager::GetCategoryID( const char *pCategoryName )
+{
+ // Make the input lower case
+ CUtlString strLowerCase = pCategoryName;
+ strLowerCase.ToLower();
+
+ return CRC32_ProcessSingleBuffer( (void*)strLowerCase.Get(), strLowerCase.Length() );
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+const CEconStoreCategoryManager::StoreCategory_t *CEconStoreCategoryManager::GetStoreCategoryFromID( StoreCategoryID_t unID ) const
+{
+ return const_cast< CEconStoreCategoryManager * >( this )->GetStoreCategoryFromID( unID );
+}
+
+CEconStoreCategoryManager::StoreCategory_t *CEconStoreCategoryManager::GetStoreCategoryFromID( StoreCategoryID_t unID )
+{
+ if ( k_CategoryID_Invalid != unID )
+ {
+ FOR_EACH_VEC( m_vecCategories, i )
+ {
+ if ( unID == m_vecCategories[i].m_unID )
+ return &m_vecCategories[i];
+ }
+ }
+
+ return NULL;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+static CEconStoreCategoryManager *gs_pEconStoreCategoryManager = NULL;
+CEconStoreCategoryManager *GEconStoreCategoryManager()
+{
+ if ( !gs_pEconStoreCategoryManager )
+ {
+ gs_pEconStoreCategoryManager = new CEconStoreCategoryManager();
+ }
+
+ return gs_pEconStoreCategoryManager;
+}
+
+void ClearEconStoreCategoryManager()
+{
+ delete gs_pEconStoreCategoryManager;
+ gs_pEconStoreCategoryManager = NULL;
+} \ No newline at end of file