//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Container that allows client & server access to data in player inventories & loadouts // //============================================================================= #ifndef TF_ITEM_INVENTORY_H #define TF_ITEM_INVENTORY_H #ifdef _WIN32 #pragma once #endif #include "econ_item_inventory.h" #include "tf_shareddefs.h" #include "econ_item_constants.h" #include "tf_item_constants.h" #ifdef CLIENT_DLL #include "econ_notifications.h" #endif #define LOADOUT_SLOT_USE_BASE_ITEM 0 namespace vgui { class Panel; } struct baseitemcriteria_t; //=============================================================================================================== //----------------------------------------------------------------------------- // Purpose: A single TF player's inventory. // On the client, the inventory manager contains an instance of this for the local player. // On the server, each player contains an instance of this. //----------------------------------------------------------------------------- class CTFPlayerInventory : public CPlayerInventory { DECLARE_CLASS( CTFPlayerInventory, CPlayerInventory ); public: CTFPlayerInventory(); virtual ~CTFPlayerInventory(); virtual CEconItemView *GetItemInLoadout( int iClass, int iSlot ); #ifdef CLIENT_DLL // Removes any item in a loadout slot. If the slot has a base item, // the player essentially returns to using that item. // NOTE: This can fail if the player has no backpack space to contain the equipped item. bool ClearLoadoutSlot( int iClass, int iSlot ); CEconItemView *GetCacheServerItemInLoadout( int iClass, int iSlot ); void UpdateWeaponSkinRequest(); #endif virtual int GetMaxItemCount( void ) const; virtual bool CanPurchaseItems( int iItemCount ) const; virtual int GetPreviewItemDef( void ) const; // Derived inventory hooks virtual void ItemHasBeenUpdated( CEconItemView *pItem, bool bUpdateAckFile, bool bWriteAckFile ) OVERRIDE; virtual void ItemIsBeingRemoved( CEconItemView *pItem ); bool UpdateEquipStateForClass( const itemid_t& itemID, equipped_slot_t nSlot, itemid_t *pLoadout, int nCount ); // Debugging virtual void DumpInventoryToConsole( bool bRoot ); bool ClassLoadoutHasChanged( int iClass ) { return m_bLoadoutChanged[iClass]; } void ClearClassLoadoutChangeTracking( void ); virtual void NotifyHasNewItems() { OnHasNewItems(); } #ifdef CLIENT_DLL virtual ITexture *GetWeaponSkinBaseLowRes( itemid_t nItemId, int iTeam ) const; #endif void OnHasNewQuest(); static CEconItemView *GetFirstItemOfItemDef( item_definition_index_t nDefIndex, CPlayerInventory* pInventory = NULL ); protected: virtual void SOCreated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE; #ifdef CLIENT_DLL // Converts an old format inventory to the new format. void ConvertOldFormatInventoryToNew( void ); virtual void PostSOUpdate( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE; virtual void SOCacheSubscribed( const CSteamID & steamIDOwner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE; virtual bool AddEconItem( CEconItem * pItem, bool bUpdateAckFile, bool bWriteAckFile, bool bCheckForNewItems ) OVERRIDE; void VerifyChangedLoadoutsAreValid(); void VerifyLoadoutItemsAreValid( int iClass ); #endif virtual void OnHasNewItems(); virtual void ValidateInventoryPositions( void ); // Extracts the position that should be used to sort items in the inventory from the backend position. // Necessary if your inventory packs a bunch of info into the position instead of using it just as a position. virtual int ExtractInventorySortPosition( uint32 iBackendPosition ) { // Consider unack'd items as -1, so they get stacked up before the 0th slot item if ( IsUnacknowledged(iBackendPosition) ) return -1; return ExtractBackpackPositionFromBackend(iBackendPosition); } virtual void SOUpdated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE; #ifdef CLIENT_DLL private: void CheckSaxtonMaskAchievement( const CEconItem *pEconItem ); void UpdateCachedServerLoadoutItems(); #endif protected: // Global indices of the items in our inventory in the loadout slots #ifdef CLIENT_DLL struct SkinRequest_t { int m_nTeam; itemid_t m_nID; MDLHandle_t m_hModel; }; CUtlVector< SkinRequest_t > m_vecWeaponSkinRequestList; itemid_t m_CachedServerLoadoutItems[ TF_CLASS_COUNT ][ CLASS_LOADOUT_POSITION_COUNT ]; CUtlMap< itemid_t, ITexture* > m_CachedBaseTextureLowRes[ TF_TEAM_COUNT ]; #endif // CLIENT_DLL itemid_t m_LoadoutItems[ TF_CLASS_COUNT ][ CLASS_LOADOUT_POSITION_COUNT ]; bool m_bLoadoutChanged[ TF_CLASS_COUNT ]; itemid_t m_AccountLoadoutItems[ ACCOUNT_LOADOUT_POSITION_COUNT ]; friend class CTFInventoryManager; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CTFInventoryManager : public CInventoryManager { DECLARE_CLASS( CTFInventoryManager, CInventoryManager ); public: CTFInventoryManager(); ~CTFInventoryManager(); virtual void PostInit( void ); #ifdef CLIENT_DLL virtual CPlayerInventory *GeneratePlayerInventoryObject() const { return new CTFPlayerInventory; } //----------------------------------------------------------------------- // CLIENT PICKUP UI HANDLING //----------------------------------------------------------------------- // Get the number of items picked up virtual int GetNumItemPickedUpItems( void ); // Show the player a pickup screen with any items they've collected recently, if any virtual bool ShowItemsPickedUp( bool bForce = false, bool bReturnToGame = true, bool bNoPanel = false ); // Show the player a pickup screen with the items they've crafted virtual void ShowItemsCrafted( CUtlVector *vecCraftedIndices ); // Force the player to discard an item to make room for a new item, if they have one virtual bool CheckForRoomAndForceDiscard( void ); // Tells the GC that the player has acknowledged an item and attempts to move it in to the first available BP slot virtual void AcknowledgeItem( CEconItemView *pItem, bool bMoveToBackpack = true ); // Gets called each frame virtual void Update( float frametime ) OVERRIDE; #endif // Returns the item data for the base item in the loadout slot for a given class CEconItemView *GetBaseItemForClass( int iClass, int iSlot ); void GenerateBaseItems( void ); // Gets the specified inventory for the steam ID CTFPlayerInventory *GetInventoryForPlayer( const CSteamID &playerID ); // Returns the item in the specified loadout slot for a given class CEconItemView *GetItemInLoadoutForClass( int iClass, int iSlot, CSteamID *pID = NULL ); CEconItemView *GetItemInLoadoutForAccount( int nSlot, CSteamID *pID = NULL ); // Fills out the vector with the sets that are currently active on the specified player & class void GetActiveSets( CUtlVector *pItemSets, CSteamID steamIDForPlayer, int iClass ); // We're generating a base item. We need to add the game-specific keys to the criteria so that it'll find the right base item. virtual void AddBaseItemCriteria( baseitemcriteria_t *pCriteria, CItemSelectionCriteria *pSelectionCriteria ); bool SlotContainsBaseItems( EEquipType_t eType, int iSlot ); int GetBaseItemCount( ) { return m_pBaseLoadoutItems.Count(); } CEconItemView* GetBaseItem( int iIndex ) { return m_pBaseLoadoutItems[iIndex]; } private: // Base items, returned for slots that the player doesn't have anything in CEconItemView *m_pDefaultItem; CUtlVector m_pBaseLoadoutItems; #ifdef CLIENT_DLL // On the client, we have a single inventory for the local player. Stored here, instead of in the // local player entity, because players need to access it while not being connected to a server. public: CPlayerInventory *GetLocalInventory( void ) { return &m_LocalInventory; } CTFPlayerInventory *GetLocalTFInventory( void ); // Try and equip the specified item in the specified class's loadout slot bool EquipItemInLoadout( int iClass, int iSlot, itemid_t iItemID ); // Fills out pList with all inventory items that could fit into the specified loadout slot for a given class int GetAllUsableItemsForSlot( int iClass, int iSlot, CUtlVector *pList ); virtual int GetBackpackPositionFromBackend( uint32 iBackendPosition ) { return ExtractBackpackPositionFromBackend(iBackendPosition); } // Fills out pList with all quest item in the local inventory int GetAllQuestItems( CUtlVector *pList ); private: CTFPlayerInventory m_LocalInventory; #endif // CLIENT_DLL }; CTFInventoryManager *TFInventoryManager( void ); #ifdef CLIENT_DLL //----------------------------------------------------------------------------- // Econ Notifications //----------------------------------------------------------------------------- class CEconNotification_HasNewItems : public CEconNotification { public: CEconNotification_HasNewItems(); ~CEconNotification_HasNewItems(); virtual void SetLifetime( float flSeconds ) { m_flExpireTime = engine->Time() + flSeconds; } virtual float GetExpireTime() const { if ( m_flExpireTime != 0 ) return -1.0f; return 0; } virtual float GetInGameLifeTime() const { return m_flExpireTime; } virtual void MarkForDeletion() { m_bHasTriggered = true; CEconNotification::MarkForDeletion(); } virtual EType NotificationType() { return eType_Trigger; } virtual void Trigger() { m_bHasTriggered = true; TFInventoryManager()->ShowItemsPickedUp( true ); MarkForDeletion(); } virtual bool BShowInGameElements() const { return m_bShowInGame; } static bool IsNotificationType( CEconNotification *pNotification ) { return dynamic_cast( pNotification ) != NULL; } protected: bool m_bHasTriggered; bool m_bShowInGame; }; //----------------------------------------------------------------------------- class CEconNotification_HasNewItemsOnKill : public CEconNotification_HasNewItems { public: CEconNotification_HasNewItemsOnKill( int iVictimID ); virtual EType NotificationType() { return eType_Basic; } virtual void Trigger() {} static bool HasUnacknowledgedItems(); static bool IsNotificationType( CEconNotification *pNotification ) { return dynamic_cast( pNotification ) != NULL; } }; #endif #endif // TF_ITEM_INVENTORY_H