This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,732 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "attribute_manager.h"
#include "saverestore.h"
#include "saverestore_utlvector.h"
#include "fmtstr.h"
#include "keyvalues.h"
#include "econ_item_system.h"
#define PROVIDER_PARITY_BITS 6
#define PROVIDER_PARITY_MASK ((1<<PROVIDER_PARITY_BITS)-1)
//==================================================================================================================
// ATTRIBUTE MANAGER SAVE/LOAD & NETWORKING
//===================================================================================================================
BEGIN_DATADESC_NO_BASE( CAttributeManager )
DEFINE_UTLVECTOR( m_Providers, FIELD_EHANDLE ),
DEFINE_FIELD( m_iReapplyProvisionParity, FIELD_INTEGER ),
DEFINE_FIELD( m_hOuter, FIELD_EHANDLE ),
// DEFINE_FIELD( m_bPreventLoopback, FIELD_BOOLEAN ), // Don't need to save
DEFINE_FIELD( m_ProviderType, FIELD_INTEGER ),
END_DATADESC()
BEGIN_DATADESC( CAttributeContainer )
DEFINE_EMBEDDED( m_Item ),
END_DATADESC()
#if defined( TF_DLL ) || defined( CSTRIKE_DLL )
BEGIN_DATADESC( CAttributeContainerPlayer )
END_DATADESC()
#endif
#ifndef CLIENT_DLL
EXTERN_SEND_TABLE( DT_ScriptCreatedItem );
#else
EXTERN_RECV_TABLE( DT_ScriptCreatedItem );
#endif
BEGIN_NETWORK_TABLE_NOBASE( CAttributeManager, DT_AttributeManager )
#ifndef CLIENT_DLL
SendPropEHandle( SENDINFO(m_hOuter) ),
SendPropInt( SENDINFO(m_ProviderType), 4, SPROP_UNSIGNED ),
SendPropInt( SENDINFO(m_iReapplyProvisionParity), PROVIDER_PARITY_BITS, SPROP_UNSIGNED ),
#else
RecvPropEHandle( RECVINFO(m_hOuter) ),
RecvPropInt( RECVINFO(m_ProviderType) ),
RecvPropInt( RECVINFO(m_iReapplyProvisionParity) ),
#endif
END_NETWORK_TABLE()
BEGIN_NETWORK_TABLE_NOBASE( CAttributeContainer, DT_AttributeContainer )
#ifndef CLIENT_DLL
SendPropEHandle( SENDINFO(m_hOuter) ),
SendPropInt( SENDINFO(m_ProviderType), 4, SPROP_UNSIGNED ),
SendPropInt( SENDINFO(m_iReapplyProvisionParity), PROVIDER_PARITY_BITS, SPROP_UNSIGNED ),
SendPropDataTable(SENDINFO_DT(m_Item), &REFERENCE_SEND_TABLE(DT_ScriptCreatedItem)),
#else
RecvPropEHandle( RECVINFO(m_hOuter) ),
RecvPropInt( RECVINFO(m_ProviderType) ),
RecvPropInt( RECVINFO(m_iReapplyProvisionParity) ),
RecvPropDataTable(RECVINFO_DT(m_Item), 0, &REFERENCE_RECV_TABLE(DT_ScriptCreatedItem)),
#endif
END_NETWORK_TABLE()
#if defined( TF_DLL ) || defined( CSTRIKE_DLL )
BEGIN_NETWORK_TABLE_NOBASE( CAttributeContainerPlayer, DT_AttributeContainerPlayer )
#ifndef CLIENT_DLL
SendPropEHandle( SENDINFO(m_hOuter) ),
SendPropInt( SENDINFO(m_ProviderType), 4, SPROP_UNSIGNED ),
SendPropInt( SENDINFO(m_iReapplyProvisionParity), PROVIDER_PARITY_BITS, SPROP_UNSIGNED ),
SendPropEHandle( SENDINFO(m_hPlayer) ),
#else
RecvPropEHandle( RECVINFO(m_hOuter) ),
RecvPropInt( RECVINFO(m_ProviderType) ),
RecvPropInt( RECVINFO(m_iReapplyProvisionParity) ),
RecvPropEHandle( RECVINFO( m_hPlayer ) ),
#endif
END_NETWORK_TABLE()
#endif
template< class T > T AttributeConvertFromFloat( float flValue )
{
return static_cast<T>( flValue );
}
template<> float AttributeConvertFromFloat<float>( float flValue )
{
return flValue;
}
template<> int AttributeConvertFromFloat<int>( float flValue )
{
return RoundFloatToInt( flValue );
}
//-----------------------------------------------------------------------------
// All fields in the object are all initialized to 0.
//-----------------------------------------------------------------------------
void *CAttributeManager::operator new( size_t stAllocateBlock )
{
ASSERT_MEMALLOC_WILL_ALIGN( CAttributeManager );
void *pMem = MemAlloc_Alloc( stAllocateBlock );
memset( pMem, 0, stAllocateBlock );
return pMem;
};
void *CAttributeManager::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine )
{
ASSERT_MEMALLOC_WILL_ALIGN( CAttributeManager );
void *pMem = MemAlloc_Alloc( stAllocateBlock, pFileName, nLine );
memset( pMem, 0, stAllocateBlock );
return pMem;
}
#ifdef CLIENT_DLL
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::OnPreDataChanged( DataUpdateType_t updateType )
{
m_iOldReapplyProvisionParity = m_iReapplyProvisionParity;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::OnDataChanged( DataUpdateType_t updateType )
{
if ( m_iReapplyProvisionParity != m_iOldReapplyProvisionParity )
{
// We've changed who we're providing to in some way. Reapply it.
IHasAttributes *pAttribInterface = dynamic_cast<IHasAttributes *>( GetOuter() );
if ( pAttribInterface )
{
pAttribInterface->ReapplyProvision();
}
ClearCache();
m_iOldReapplyProvisionParity = m_iReapplyProvisionParity.Get();
}
}
#endif // CLIENT_DLL
//-----------------------------------------------------------------------------
// Purpose: Call this inside your entity's Spawn()
//-----------------------------------------------------------------------------
void CAttributeManager::InitializeAttributes( CBaseEntity *pEntity )
{
Assert( dynamic_cast<IHasAttributes*>( pEntity ) );
m_hOuter = pEntity;
m_bPreventLoopback = false;
}
//=====================================================================================================
// ATTRIBUTE PROVIDERS
//=====================================================================================================
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::ProvideTo( CBaseEntity *pProvider )
{
IHasAttributes *pOwnerAttribInterface = dynamic_cast<IHasAttributes *>( pProvider );
if ( pOwnerAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pOwnerAttribInterface->GetAttributeManager() )
pAttrMgrForUse->AddProvider( m_hOuter.Get() );
#ifndef CLIENT_DLL
m_iReapplyProvisionParity = (m_iReapplyProvisionParity + 1) & PROVIDER_PARITY_MASK;
NetworkStateChanged();
#endif
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::StopProvidingTo( CBaseEntity *pProvider )
{
IHasAttributes *pOwnerAttribInterface = dynamic_cast<IHasAttributes *>( pProvider );
if ( pOwnerAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pOwnerAttribInterface->GetAttributeManager() )
pAttrMgrForUse->RemoveProvider( m_hOuter.Get() );
#ifndef CLIENT_DLL
m_iReapplyProvisionParity = (m_iReapplyProvisionParity + 1) & PROVIDER_PARITY_MASK;
NetworkStateChanged();
#endif
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::AddProvider( CBaseEntity *pProvider )
{
// Make sure he's not already in our list, and prevent circular provision
Assert( !IsBeingProvidedToBy(pProvider) );
Assert( !IsProvidingTo(pProvider) );
// Ensure he's allowed to provide
Assert( dynamic_cast<IHasAttributes *>(pProvider) );
m_Providers.AddToTail( pProvider );
ClearCache();
/*
#ifdef CLIENT_DLL
Msg("CLIENT PROVIDER UPDATE: %s now has %d providers:\n", STRING(GetOuter()->GetDebugName()), m_Providers.Count() );
for ( int i = 0; i < m_Providers.Count(); i++ )
{
Msg(" %d: %s\n", i, STRING(m_Providers[i]->GetDebugName()) );
}
#else
Msg("SERVER PROVIDER UPDATE: %s now has %d providers:\n", GetOuter()->GetDebugName(), m_Providers.Count() );
for ( int i = 0; i < m_Providers.Count(); i++ )
{
Msg(" %d: %s\n", i, m_Providers[i]->GetDebugName() );
}
#endif
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::RemoveProvider( CBaseEntity *pProvider )
{
m_Providers.FindAndRemove( pProvider );
ClearCache();
/*
#ifdef CLIENT_DLL
Msg("CLIENT PROVIDER UPDATE: %s now has %d providers:\n", STRING(GetOuter()->GetDebugName()), m_Providers.Count() );
for ( int i = 0; i < m_Providers.Count(); i++ )
{
Msg(" %d: %s\n", i, STRING(m_Providers[i]->GetDebugName()) );
}
#else
Msg("SERVER PROVIDER UPDATE: %s now has %d providers:\n", GetOuter()->GetDebugName(), m_Providers.Count() );
for ( int i = 0; i < m_Providers.Count(); i++ )
{
Msg(" %d: %s\n", i, m_Providers[i]->GetDebugName() );
}
#endif
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeManager::ClearCache( void )
{
if ( m_bPreventLoopback )
return;
m_CachedResults.Purge();
m_bPreventLoopback = true;
// Tell all providers relying on me that they need to wipe their cache too
int iCount = m_Providers.Count();
for ( int iHook = 0; iHook < iCount; iHook++ )
{
IHasAttributes *pAttribInterface = dynamic_cast<IHasAttributes *>(m_Providers[iHook].Get());
if ( pAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pAttribInterface->GetAttributeManager() )
pAttrMgrForUse->ClearCache();
}
}
// Tell our owner that he needs to clear his too, in case he has attributes affecting him
IHasAttributes *pMyAttribInterface = dynamic_cast<IHasAttributes *>( m_hOuter.Get().Get() );
if ( pMyAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pMyAttribInterface->GetAttributeManager() )
pAttrMgrForUse->ClearCache();
}
m_bPreventLoopback = false;
#ifndef CLIENT_DLL
// Force out client to clear their cache as well
m_iReapplyProvisionParity = (m_iReapplyProvisionParity + 1) & PROVIDER_PARITY_MASK;
NetworkStateChanged();
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseEntity *CAttributeManager::GetProvider( int iIndex )
{
Assert( iIndex >= 0 && iIndex < m_Providers.Count() );
return m_Providers[iIndex];
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this entity is providing attributes to the specified entity
//-----------------------------------------------------------------------------
bool CAttributeManager::IsProvidingTo( CBaseEntity *pEntity )
{
IHasAttributes *pAttribInterface = dynamic_cast<IHasAttributes *>(pEntity);
if ( pAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pAttribInterface->GetAttributeManager() )
if ( pAttrMgrForUse->IsBeingProvidedToBy( GetOuter() ) )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this entity is being provided attributes by the specified entity
//-----------------------------------------------------------------------------
bool CAttributeManager::IsBeingProvidedToBy( CBaseEntity *pEntity )
{
return ( m_Providers.Find( pEntity ) != m_Providers.InvalidIndex() );
}
//=====================================================================================================
// ATTRIBUTE HOOKS
//=====================================================================================================
//-----------------------------------------------------------------------------
// Purpose: Wrapper that checks to see if we've already got the result in our cache
//-----------------------------------------------------------------------------
float CAttributeManager::ApplyAttributeFloatWrapper( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList )
{
int iCount = m_CachedResults.Count();
for ( int i = iCount-1; i >= 0; i-- )
{
if ( m_CachedResults[i].iAttribHook == iszAttribHook )
{
if ( m_CachedResults[i].flIn == flValue )
return m_CachedResults[i].flOut;
// We've got a cached result for a different flIn value. Remove the cached result to
// prevent stacking up entries for different requests (i.e. crit chance)
m_CachedResults.Remove(i);
break;
}
}
// Wasn't in cache. Do the work.
float flResult = ApplyAttributeFloat( flValue, pInitiator, iszAttribHook, pItemList );
// Add it to our cache
int iIndex = m_CachedResults.AddToTail();
m_CachedResults[iIndex].flIn = flValue;
m_CachedResults[iIndex].flOut = flResult;
m_CachedResults[iIndex].iAttribHook = iszAttribHook;
return flResult;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CAttributeManager::ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList )
{
if ( m_bPreventLoopback || !GetOuter() )
return flValue;
// We need to prevent loopback between two items both providing to the same entity.
m_bPreventLoopback = true;
// See if we have any providers. If we do, tell them to apply.
int iCount = m_Providers.Count();
for ( int iHook = 0; iHook < iCount; iHook++ )
{
if ( m_Providers[iHook].Get() == pInitiator )
continue;
// Don't allow weapons to provide to other weapons being carried by the same person
IHasAttributes *pAttribInterface = dynamic_cast<IHasAttributes *>(m_Providers[iHook].Get());
if ( pInitiator && pAttribInterface->GetAttributeManager() &&
pAttribInterface->GetAttributeManager()->GetProviderType() == PROVIDER_WEAPON )
{
IHasAttributes *pInitiatorAttribInterface = dynamic_cast<IHasAttributes *>(pInitiator);
if ( pInitiatorAttribInterface->GetAttributeManager() &&
pInitiatorAttribInterface->GetAttributeManager()->GetProviderType() == PROVIDER_WEAPON )
continue;
}
if ( CAttributeManager *pAttrMgrForUse = pAttribInterface->GetAttributeManager() )
flValue = pAttrMgrForUse->ApplyAttributeFloat( flValue, pInitiator, iszAttribHook, pItemList );
}
// Then see if our owner has any attributes he wants to apply as well.
// i.e. An aura is providing attributes to this weapon's carrier.
IHasAttributes *pMyAttribInterface = dynamic_cast<IHasAttributes *>( m_hOuter.Get().Get() );
if ( pMyAttribInterface->GetAttributeOwner() )
{
IHasAttributes *pOwnerAttribInterface = dynamic_cast<IHasAttributes *>( pMyAttribInterface->GetAttributeOwner() );
if ( pOwnerAttribInterface )
{
if ( CAttributeManager * pAttrMgrForUse = pOwnerAttribInterface->GetAttributeManager() )
flValue = pAttrMgrForUse->ApplyAttributeFloat( flValue, pInitiator, iszAttribHook, pItemList );
}
}
m_bPreventLoopback = false;
return flValue;
}
//=====================================================================================================
// ATTRIBUTE CONTAINER
//=====================================================================================================
//-----------------------------------------------------------------------------
// Purpose: Call this inside your entity's Spawn()
//-----------------------------------------------------------------------------
void CAttributeContainer::InitializeAttributes( CBaseEntity *pEntity )
{
BaseClass::InitializeAttributes( pEntity );
#ifndef CLIENT_DLL
/*
if ( !m_Item.IsValid() )
{
Warning("Item '%s' not setup correctly. Attempting to create attributes on an unitialized item.\n", m_hOuter.Get()->GetDebugName() );
}
*/
#endif
m_Item.GetAttributeList()->SetManager( this );
ClearCache();
}
static void ApplyAttribute( const CEconItemAttributeDefinition *pAttributeDef, float& flValue, const float flValueModifier )
{
Assert( pAttributeDef );
Assert( pAttributeDef->GetAttributeType() );
AssertMsg1( pAttributeDef->GetAttributeType()->BSupportsGameplayModificationAndNetworking(), "Attempt to hook the value of attribute '%s' which doesn't support hooking! Pull the value of the attribute directly using FindAttribute()!", pAttributeDef->GetDefinitionName() );
const int iAttrDescFormat = pAttributeDef->GetDescriptionFormat();
switch ( iAttrDescFormat )
{
case ATTDESCFORM_VALUE_IS_PERCENTAGE:
case ATTDESCFORM_VALUE_IS_INVERTED_PERCENTAGE:
{
flValue *= flValueModifier;
}
break;
case ATTDESCFORM_VALUE_IS_COLOR:
case ATTDESCFORM_VALUE_IS_ADDITIVE:
case ATTDESCFORM_VALUE_IS_ADDITIVE_PERCENTAGE:
case ATTDESCFORM_VALUE_IS_PARTICLE_INDEX:
{
flValue += flValueModifier;
}
break;
case ATTDESCFORM_VALUE_IS_REPLACE:
{
flValue = flValueModifier;
}
break;
case ATTDESCFORM_VALUE_IS_OR:
{
int iTmp = flValue;
iTmp |= (int)flValueModifier;
flValue = iTmp;
}
break;
case ATTDESCFORM_VALUE_IS_GAME_TIME:
case ATTDESCFORM_VALUE_IS_DATE:
Assert( !"Attempt to apply date attribute in ApplyAttribute()." ); // No-one should be hooking date descriptions
break;
default:
// Unknown value format.
AssertMsg1( false, "Unknown attribute value type %i in ApplyAttribute().", iAttrDescFormat );
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Given two attributes, return a collated value.
//-----------------------------------------------------------------------------
float CollateAttributeValues( const CEconItemAttribute *pAttrib1, const CEconItemAttribute *pAttrib2 )
{
// We can only collate attributes of matching definitions
Assert( !Q_stricmp( pAttrib1->GetStaticData()->GetAttributeClass(), pAttrib2->GetStaticData()->GetAttributeClass() ) );
const CEconItemAttributeDefinition *pDef = pAttrib1->GetStaticData();
const int iAttrDescFormat = pDef->GetDescriptionFormat();
float flValue = 0;
switch ( iAttrDescFormat )
{
case ATTDESCFORM_VALUE_IS_PERCENTAGE:
case ATTDESCFORM_VALUE_IS_INVERTED_PERCENTAGE:
{
flValue = 1.0;
}
break;
case ATTDESCFORM_VALUE_IS_COLOR:
case ATTDESCFORM_VALUE_IS_ADDITIVE:
case ATTDESCFORM_VALUE_IS_ADDITIVE_PERCENTAGE:
case ATTDESCFORM_VALUE_IS_OR:
case ATTDESCFORM_VALUE_IS_REPLACE:
{
flValue = 0;
}
break;
case ATTDESCFORM_VALUE_IS_DATE:
Assert( !"Attempt to apply date attribute in ApplyAttribute()." ); // No-one should be hooking date descriptions
break;
default:
// Unknown value format.
AssertMsg1( false, "Unknown attribute value type %i in ApplyAttribute().", iAttrDescFormat );
break;
}
ApplyAttribute( pDef, flValue, pAttrib1->GetValue() );
ApplyAttribute( pDef, flValue, pAttrib2->GetValue() );
return flValue;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CEconItemAttributeIterator_ApplyAttributeFloat : public IEconItemAttributeIterator
{
public:
CEconItemAttributeIterator_ApplyAttributeFloat( CBaseEntity *pOuter, float flInitialValue, string_t iszAttribHook, CUtlVector<CBaseEntity *> *pItemList )
: m_pOuter( pOuter )
, m_flValue( flInitialValue )
, m_iszAttribHook( iszAttribHook )
, m_pItemList( pItemList )
{
Assert( pOuter );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value )
{
COMPILE_TIME_ASSERT( sizeof( value ) == sizeof( float ) );
Assert( pAttrDef );
if ( pAttrDef->GetCachedClass() != m_iszAttribHook )
return true;
if ( m_pItemList && !m_pItemList->HasElement( m_pOuter ) )
{
m_pItemList->AddToTail( m_pOuter );
}
ApplyAttribute( pAttrDef, m_flValue, *reinterpret_cast<float *>( &value ) );
// We assume that each attribute can only be in the attribute list for a single item once, but we're
// iterating over attribute *classes* here, not unique attribute types, so we carry on looking.
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value )
{
Assert( pAttrDef );
if ( pAttrDef->GetCachedClass() != m_iszAttribHook )
return true;
if ( m_pItemList && !m_pItemList->HasElement( m_pOuter ) )
{
m_pItemList->AddToTail( m_pOuter );
}
ApplyAttribute( pAttrDef, m_flValue, value );
// We assume that each attribute can only be in the attribute list for a single item once, but we're
// iterating over attribute *classes* here, not unique attribute types, so we carry on looking.
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value )
{
// We can't possibly process an attribute of this type!
Assert( pAttrDef );
Assert( pAttrDef->GetCachedClass() != m_iszAttribHook );
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value )
{
// We can't possibly process an attribute of this type!
Assert( pAttrDef );
Assert( pAttrDef->GetCachedClass() != m_iszAttribHook );
return true;
}
float GetResultValue() const
{
return m_flValue;
}
private:
CBaseEntity *m_pOuter;
float m_flValue;
string_t m_iszAttribHook;
CUtlVector<CBaseEntity *> *m_pItemList;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CAttributeContainer::ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList )
{
if ( m_bPreventLoopback || !GetOuter() )
return flValue;
// We need to prevent loopback between two items both providing to the same entity.
m_bPreventLoopback = true;
// ...
CEconItemAttributeIterator_ApplyAttributeFloat it( GetOuter(), flValue, iszAttribHook, pItemList );
m_Item.IterateAttributes( &it );
m_bPreventLoopback = false;
return BaseClass::ApplyAttributeFloat( it.GetResultValue(), pInitiator, iszAttribHook, pItemList );
}
#if defined( TF_DLL ) || defined( CSTRIKE_DLL )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAttributeContainerPlayer::InitializeAttributes( CBaseEntity *pEntity )
{
BaseClass::InitializeAttributes( pEntity );
ClearCache();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CAttributeContainerPlayer::ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook, CUtlVector<CBaseEntity*> *pItemList )
{
if ( m_bPreventLoopback || !GetOuter() )
return flValue;
m_bPreventLoopback = true;
#ifdef DEBUG
int iFoundAttributeCount = 0;
#endif // DEBUG
CEconItemAttributeIterator_ApplyAttributeFloat it( GetOuter(), flValue, iszAttribHook, pItemList );
#if defined( USE_PLAYER_ATTRIBUTE_MANAGER )
CBasePlayer *pPlayer = GetPlayer();
if ( pPlayer )
{
pPlayer->m_AttributeList.IterateAttributes( &it );
// Apply all the attributes within this manager
int iAttributes = pPlayer->m_AttributeList.GetNumAttributes();
for ( int i = 0; i < iAttributes; i++ )
{
CEconItemAttribute *pAttribute = pPlayer->m_AttributeList.GetAttribute(i);
CEconItemAttributeDefinition *pData = pAttribute->GetStaticData();
// The first time we try to compare to an attribute, we alloc this for faster future lookup
if ( pData->GetCachedClass() == iszAttribHook )
{
// If we are keep track (ie. pItemList != NULL), then put the item in the list.
if ( pItemList )
{
if ( pItemList->Find( GetOuter() ) == -1 )
{
pItemList->AddToTail( GetOuter() );
}
}
ApplyAttribute( pData, flValue, pAttribute->GetValue() );
#ifdef DEBUG
iFoundAttributeCount++;
#endif // DEBUG
}
}
}
#endif //#if defined( USE_PLAYER_ATTRIBUTE_MANAGER )
#ifdef DEBUG
// If we didn't find any attributes on this object, loop through all the attributes in our schema to find
// out whether this attribute even exists so we can spew a warning if it doesn't.
if ( iFoundAttributeCount == 0 )
{
const CEconItemSchema::EconAttrDefsContainer_t & mapAttrDefs = ItemSystem()->GetItemSchema()->GetAttributeDefinitionContainer();
FOR_EACH_VEC( mapAttrDefs, i )
{
if ( mapAttrDefs[i] && ( mapAttrDefs[i]->GetCachedClass() == iszAttribHook ) )
{
iFoundAttributeCount++;
break;
}
}
}
AssertMsg1( iFoundAttributeCount != 0, "Attempt to apply unknown attribute '%s'.", STRING( iszAttribHook ) );
#endif // DEBUG
m_bPreventLoopback = false;
return BaseClass::ApplyAttributeFloat( it.GetResultValue(), pInitiator, iszAttribHook, pItemList );
}
#endif

View File

@@ -0,0 +1,220 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose: Attributable entities contain one of these, which handles game specific handling:
// - Save / Restore
// - Networking
// - Attribute providers
// - Application of attribute effects
//
//=============================================================================
#ifndef ATTRIBUTE_MANAGER_H
#define ATTRIBUTE_MANAGER_H
#ifdef _WIN32
#pragma once
#endif
#include "econ_item_view.h"
#include "ihasattributes.h"
// Provider types
enum attributeprovidertypes_t
{
PROVIDER_GENERIC,
PROVIDER_WEAPON,
};
float CollateAttributeValues( const CEconItemAttribute *pAttrib1, const CEconItemAttribute *pAttrib2 );
//-----------------------------------------------------------------------------
// Macros for hooking the application of attributes
#define CALL_ATTRIB_HOOK( vartype, retval, hookName, who, itemlist ) \
retval = CAttributeManager::AttribHookValue<vartype>( retval, #hookName, static_cast<const CBaseEntity*>( who ), itemlist, true );
#define CALL_ATTRIB_HOOK_INT( retval, hookName ) CALL_ATTRIB_HOOK( int, retval, hookName, this, NULL )
#define CALL_ATTRIB_HOOK_FLOAT( retval, hookName ) CALL_ATTRIB_HOOK( float, retval, hookName, this, NULL )
#define CALL_ATTRIB_HOOK_INT_ON_OTHER( other, retval, hookName ) CALL_ATTRIB_HOOK( int, retval, hookName, other, NULL )
#define CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( other, retval, hookName ) CALL_ATTRIB_HOOK( float, retval, hookName, other, NULL )
#define CALL_ATTRIB_HOOK_BOOL( hookName ) ( 0 != CAttributeManager::AttribHookValue<int>( 0, #hookName, static_cast<const CBaseEntity*>( this ), NULL, true ) )
#define CALL_ATTRIB_HOOK_BOOL_ON_OTHER( other, hookName ) ( 0 != CAttributeManager::AttribHookValue<int>( 0, #hookName, static_cast<const CBaseEntity*>( other ), NULL, true ) )
template< class T > T AttributeConvertFromFloat( float flValue );
template<> float AttributeConvertFromFloat<float>( float flValue );
template<> int AttributeConvertFromFloat<int>( float flValue );
//-----------------------------------------------------------------------------
// Purpose: Base Attribute manager.
// This class knows how to apply attribute effects that have been
// provided to its owner by other entities, but doesn't contain attributes itself.
//-----------------------------------------------------------------------------
class CAttributeManager
{
DECLARE_CLASS_NOBASE( CAttributeManager );
public:
DECLARE_DATADESC();
DECLARE_EMBEDDED_NETWORKVAR();
virtual ~CAttributeManager() {}
// Call this inside your entity's Spawn()
virtual void InitializeAttributes( CBaseEntity *pEntity );
CBaseEntity *GetOuter( void ) { return m_hOuter.Get(); }
//--------------------------------------------------------
// Attribute providers.
// Other entities that are providing attributes to this entity (i.e. weapons being carried by a player)
void ProvideTo( CBaseEntity *pProvider );
void StopProvidingTo( CBaseEntity *pProvider );
protected:
// Not to be called directly. Use ProvideTo() or StopProvidingTo() above.
void AddProvider( CBaseEntity *pProvider );
void RemoveProvider( CBaseEntity *pProvider );
public:
int GetNumProviders( void ) { return m_Providers.Count(); }
CBaseEntity *GetProvider( int iIndex );
// Return true if this entity is providing attributes to the specified entity
bool IsProvidingTo( CBaseEntity *pEntity );
// Return true if this entity is being provided attributes by the specified entity
bool IsBeingProvidedToBy( CBaseEntity *pEntity );
// Provider types are used to prevent specified providers supplying to certain initiators
void SetProviderType( attributeprovidertypes_t tType ) { m_ProviderType = tType; }
attributeprovidertypes_t GetProviderType( void ) { return m_ProviderType; }
//--------------------------------------------------------
// Attribute hook. Use the CALL_ATTRIB_HOOK macros above.
template <class T> static T AttribHookValue( T TValue, const char *pszAttribHook, const CBaseEntity *pEntity, CUtlVector<CBaseEntity*> *pItemList = NULL, bool bIsGlobalConstString = false )
{
// Do we have a hook?
if ( pszAttribHook == NULL || pszAttribHook[0] == '\0' )
return TValue;
// Verify that we have an entity, at least as "this"
if ( pEntity == NULL )
return TValue;
IHasAttributes *pAttribInterface = dynamic_cast<IHasAttributes*>( (CBaseEntity*) pEntity );
Assert(pAttribInterface); // If you hit this, you've probably got a hook incorrectly setup, because the entity it's hooking on doesn't know about attributes.
if ( pAttribInterface && pAttribInterface->GetAttributeManager() )
{
string_t iszAttribHook = bIsGlobalConstString ? AllocPooledStringConstant(pszAttribHook) : AllocPooledString(pszAttribHook);
float flValue = pAttribInterface->GetAttributeManager()->ApplyAttributeFloatWrapper( static_cast<float>( TValue ), (CBaseEntity*) pEntity, iszAttribHook, pItemList );
TValue = AttributeConvertFromFloat<T>( flValue );
}
return TValue;
}
virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL );
//--------------------------------------------------------
// Networking
#ifdef CLIENT_DLL
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
#endif
//--------------------------------------------------------
// memory handling
void *operator new( size_t stAllocateBlock );
void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
protected:
CUtlVector<EHANDLE> m_Providers;
CNetworkVarForDerived( int, m_iReapplyProvisionParity );
CNetworkVarForDerived( EHANDLE, m_hOuter );
bool m_bPreventLoopback;
CNetworkVarForDerived( attributeprovidertypes_t, m_ProviderType );
public:
void ClearCache( void );
private:
virtual float ApplyAttributeFloatWrapper( float flValue, CBaseEntity *pInitiator, string_t pszAttribHook, CUtlVector<CBaseEntity*> *pItemList = NULL );
private:
// Cached attribute results
// We cache off requests for data, and wipe the cache whenever our providers change.
struct cached_attribute_float_t
{
float flIn;
string_t iAttribHook;
float flOut;
};
CUtlVector<cached_attribute_float_t> m_CachedResults;
#ifdef CLIENT_DLL
public:
// Data received from the server
int m_iOldReapplyProvisionParity;
#endif
};
//-----------------------------------------------------------------------------
// Purpose: This is an attribute manager that also knows how to contain attributes.
//-----------------------------------------------------------------------------
class CAttributeContainer : public CAttributeManager
{
public:
DECLARE_DATADESC();
DECLARE_CLASS( CAttributeContainer, CAttributeManager );
DECLARE_EMBEDDED_NETWORKVAR();
virtual void InitializeAttributes( CBaseEntity *pEntity );
//--------------------------------------------------------
// Attribute hook. Use the CALL_ATTRIB_HOOK macros above.
virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
CEconItemView *GetItem( void ) { return m_Item.Get(); }
const CEconItemView *GetItem( void ) const { return m_Item.Get(); }
void SetItem( CEconItemView *pItem )
{
m_Item.CopyFrom( *pItem );
}
private:
CNetworkVarEmbedded( CEconItemView, m_Item );
};
//-----------------------------------------------------------------------------
// Purpose: An attribute manager that uses a player's shared attributes.
//-----------------------------------------------------------------------------
#if defined( TF_DLL ) || defined( CSTRIKE_DLL )
class CAttributeContainerPlayer : public CAttributeManager
{
public:
DECLARE_DATADESC();
DECLARE_CLASS( CAttributeContainerPlayer, CAttributeManager );
DECLARE_EMBEDDED_NETWORKVAR();
virtual void InitializeAttributes( CBaseEntity *pEntity );
virtual float ApplyAttributeFloat( float flValue, CBaseEntity *pInitiator, string_t iszAttribHook = NULL_STRING, CUtlVector<CBaseEntity*> *pItemList = NULL ) OVERRIDE;
CBasePlayer* GetPlayer( void ) { return m_hPlayer; }
void SetPlayer( CBasePlayer *pPlayer ) { m_hPlayer = pPlayer; }
private:
CNetworkHandle( CBasePlayer, m_hPlayer );
};
#endif
#ifdef CLIENT_DLL
EXTERN_RECV_TABLE( DT_AttributeManager );
EXTERN_RECV_TABLE( DT_AttributeContainer );
#else
EXTERN_SEND_TABLE( DT_AttributeManager );
EXTERN_SEND_TABLE( DT_AttributeContainer );
#endif
#endif // ATTRIBUTE_MANAGER_H

View File

@@ -0,0 +1,64 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Code for the CTFMapContribution object
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "econ_contribution.h"
using namespace GCSDK;
#ifdef GC
IMPLEMENT_CLASS_MEMPOOL( CTFMapContribution, 10 * 1000, UTLMEMORYPOOL_GROW_SLOW );
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
bool CTFMapContribution::BYieldingAddInsertToTransaction( GCSDK::CSQLAccess & sqlAccess )
{
CSchMapContribution schMapContribution;
WriteToRecord( &schMapContribution );
return CSchemaSharedObjectHelper::BYieldingAddInsertToTransaction( sqlAccess, &schMapContribution );
}
bool CTFMapContribution::BYieldingAddWriteToTransaction( GCSDK::CSQLAccess & sqlAccess, const CUtlVector< int > &fields )
{
CSchMapContribution schMapContribution;
WriteToRecord( &schMapContribution );
CColumnSet csDatabaseDirty( schMapContribution.GetPSchema()->GetRecordInfo() );
csDatabaseDirty.MakeEmpty();
if ( fields.HasElement( CSOTFMapContribution::kContributionLevelFieldNumber ) )
{
csDatabaseDirty.BAddColumn( CSchMapContribution::k_iField_unContributionLevel );
}
return CSchemaSharedObjectHelper::BYieldingAddWriteToTransaction( sqlAccess, &schMapContribution, csDatabaseDirty );
}
bool CTFMapContribution::BYieldingAddRemoveToTransaction( GCSDK::CSQLAccess & sqlAccess )
{
CSchMapContribution schMapContribution;
WriteToRecord( &schMapContribution );
return CSchemaSharedObjectHelper::BYieldingAddRemoveToTransaction( sqlAccess, &schMapContribution );
}
void CTFMapContribution::WriteToRecord( CSchMapContribution *pMapContribution ) const
{
pMapContribution->m_unAccountID = Obj().account_id();
pMapContribution->m_unDefIndex = Obj().def_index();
pMapContribution->m_unContributionLevel = Obj().contribution_level();
}
void CTFMapContribution::ReadFromRecord( const CSchMapContribution & mapContribution )
{
Obj().set_account_id( mapContribution.m_unAccountID );
Obj().set_def_index( mapContribution.m_unDefIndex );
Obj().set_contribution_level( mapContribution.m_unContributionLevel );
}
#endif

View File

@@ -0,0 +1,45 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds the CTFMapContribution object
//
// $NoKeywords: $
//=============================================================================//
#ifndef TFMAPCONTRIBUTION_H
#define TFMAPCONTRIBUTION_H
#ifdef _WIN32
#pragma once
#endif
#include "gcsdk/protobufsharedobject.h"
#include "tf_gcmessages.h"
namespace GCSDK
{
class CSQLAccess;
};
//---------------------------------------------------------------------------------
// Purpose: All the account-level information that the GC tracks for TF
//---------------------------------------------------------------------------------
class CTFMapContribution : public GCSDK::CProtoBufSharedObject< CSOTFMapContribution, k_EEconTypeMapContribution >
{
#ifdef GC
DECLARE_CLASS_MEMPOOL( CTFMapContribution );
#endif
public:
CTFMapContribution() {}
#ifdef GC
virtual bool BYieldingAddInsertToTransaction( GCSDK::CSQLAccess & sqlAccess );
virtual bool BYieldingAddWriteToTransaction( GCSDK::CSQLAccess & sqlAccess, const CUtlVector< int > &fields );
virtual bool BYieldingAddRemoveToTransaction( GCSDK::CSQLAccess & sqlAccess );
void WriteToRecord( CSchMapContribution *pMapContribution ) const;
void ReadFromRecord( const CSchMapContribution & mapContribution );
#endif
};
#endif // TFMAPCONTRIBUTION_H

View File

@@ -0,0 +1,12 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: CEconCoupon - Limited time offers to purchase an econ item
//
//=============================================================================//
#include "cbase.h"
#include "econ_coupons.h"
using namespace GCSDK;

View File

@@ -0,0 +1,34 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: CEconCoupons - Limited time offers to purchase an econ item
//
//=============================================================================//
#pragma once
#include "gcsdk/protobufsharedobject.h"
#include "cstrike15_gcmessages.pb.h"
class CEconCoupon : public GCSDK::CProtoBufSharedObject< CSOEconCoupon, k_EEconTypeCoupon >
{
#ifdef GC_DLL
DECLARE_CLASS_MEMPOOL_MT( CEconCoupon );
enum { k_MaxNumCoupons = 4 }; // Must match SCH declaration
#endif
public:
const static int k_nTypeID = k_EEconTypeCoupon;
virtual int GetTypeID() const
{
return k_nTypeID;
}
#ifdef GC
// virtual bool BYieldingAddWriteToTransaction( GCSDK::CSQLAccess &sqlAccess, const CUtlVector< int > &fields );
// virtual bool BYieldingAddInsertToTransaction( GCSDK::CSQLAccess & sqlAccess );
// virtual bool BYieldingAddRemoveToTransaction( GCSDK::CSQLAccess &sqlAccess );
// void WriteToRecord( CSchCoupons *pSchRecord );
// void ReadFromRecord( const CSchCoupons &rSchRecord );
#endif
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
//========= Copyright <20> 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef ECON_ENTITY_H
#define ECON_ENTITY_H
#ifdef _WIN32
#pragma once
#endif
#include <utlsortvector.h>
#include <utlhashtable.h>
#include "ihasattributes.h"
#include "ihasowner.h"
#include "attribute_manager.h"
#ifdef DOTA_DLL
#include "dota_econ_item_string_table.h"
#endif
#if defined( CLIENT_DLL )
#define CEconEntity C_EconEntity
#define CBaseAttributableItem C_BaseAttributableItem
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CEconEntity : public CBaseFlex, public IHasAttributes
{
DECLARE_CLASS( CEconEntity, CBaseFlex );
public:
DECLARE_NETWORKCLASS();
DECLARE_DATADESC();
CEconEntity();
~CEconEntity();
void InitializeAttributes( void );
void DebugDescribe( void );
Activity TranslateViewmodelHandActivity( Activity actBase );
virtual void UpdateOnRemove( void );
virtual CStudioHdr * OnNewModel();
bool HasCustomParticleSystems( void );
#if !defined( CLIENT_DLL )
virtual void GiveTo( CBaseEntity *pOther ) {}
void OnOwnerClassChange( void );
void UpdateModelToClass( void );
void PlayAnimForPlaybackEvent( wearableanimplayback_t iPlayback );
virtual int CalculateVisibleClassFor( CBaseCombatCharacter *pPlayer );
virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo );
#else
virtual void SetDormant( bool bDormant );
virtual void OnPreDataChanged( DataUpdateType_t type );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool ShouldShowToolTip( void ) { return true; }
virtual bool InitializeAsClientEntity( const char *pszModelName, bool bRenderWithViewModels );
virtual int InternalDrawModel( int flags, const RenderableInstance_t &instance );
virtual bool OnInternalDrawModel( ClientModelRenderInfo_t *pInfo );
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options );
bool InternalFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
// Custom flex controllers
virtual bool UsesFlexDelayedWeights( void );
virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights );
float m_flFlexDelayTime;
float * m_flFlexDelayedWeight;
// Custom particle attachments
void UpdateParticleSystems( void );
virtual bool ShouldDrawParticleSystems( void );
void SetParticleSystemsVisible( bool bVisible );
void UpdateSingleParticleSystem( bool bVisible, attachedparticlesystem_t *pSystem, const char *pszAttachmentName = NULL );
virtual void UpdateAttachmentModels( void );
virtual bool AttachmentModelsShouldBeVisible( void ) { return true; }
// Viewmodel overriding
virtual bool ViewModel_IsTransparent( void );
virtual bool ViewModel_IsUsingFBTexture( void );
virtual bool IsOverridingViewmodel( void );
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags );
// Attachments
bool WantsToOverrideViewmodelAttachments( void ) { return (m_hViewmodelAttachment != nullptr); }
virtual int LookupAttachment( const char *pAttachmentName );
virtual bool GetAttachment( const char *szName, Vector &absOrigin ) { return BaseClass::GetAttachment(szName,absOrigin); }
virtual bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles ) { return BaseClass::GetAttachment(szName,absOrigin,absAngles); }
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
virtual bool GetAttachment( int number, Vector &origin );
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
C_BaseAnimating *GetViewmodelAttachment( void ) { return m_hViewmodelAttachment.Get(); }
virtual void ViewModelAttachmentBlending( CStudioHdr *hdr, Vector pos[], Quaternion q[], float currentTime, int boneMask ) {}
void SetWaitingToLoad( bool bWaiting );
virtual bool ValidateEntityAttachedToPlayer( bool &bShouldRetry );
virtual void SetMaterialOverride( const char *pszMaterial );
virtual void SetMaterialOverride( CMaterialReference &ref );
bool m_bAttributesInitialized;
#endif
public:
// IHasAttributes
CAttributeManager *GetAttributeManager( void ) { return m_AttributeManager.Get(); }
CAttributeContainer *GetAttributeContainer( void ) { return m_AttributeManager.Get(); }
const CAttributeContainer *GetAttributeContainer( void ) const { return m_AttributeManager.Get(); }
CBaseEntity *GetAttributeOwner( void ) { return GetOwnerEntity(); }
CAttributeList *GetAttributeList( void ) { return m_AttributeManager.GetItem()->GetAttributeList(); }
loadout_positions_t GetLoadoutPosition( int iTeam = 0 ) const;
const CEconItemView* GetEconItemView( void ) const;
virtual void SetOriginalOwnerXuid( uint32 nLow, uint32 nHigh ) { m_OriginalOwnerXuidLow = nLow; m_OriginalOwnerXuidHigh = nHigh; }
virtual uint64 GetOriginalOwnerXuid( void ) const;
// Obsolete, but used for demo backward compat
virtual int GetFallbackPaintKit( void ) const { return m_nFallbackPaintKit; }
virtual int GetFallbackSeed( void ) const { return m_nFallbackSeed; }
virtual int GetFallbackWear( void ) const { return m_flFallbackWear; }
virtual int GetFallbackStatTrak( void ) const { return m_nFallbackStatTrak; }
virtual void ReapplyProvision( void );
virtual bool UpdateBodygroups( CBaseCombatCharacter* pOwner, int iState );
protected:
virtual Activity TranslateViewmodelHandActivityInternal( Activity actBase ) { return actBase; }
protected:
CNetworkVarEmbedded( CAttributeContainer, m_AttributeManager );
CNetworkVar( uint32, m_OriginalOwnerXuidLow );
CNetworkVar( uint32, m_OriginalOwnerXuidHigh );
// Obsolete, but used for demo backward compat
CNetworkVar( int, m_nFallbackPaintKit );
CNetworkVar( int, m_nFallbackSeed );
CNetworkVar( float, m_flFallbackWear );
CNetworkVar( int, m_nFallbackStatTrak );
#ifdef CLIENT_DLL
bool m_bClientside;
bool m_bParticleSystemsCreated;
CUtlVector<int> m_vecAttachedParticles;
CMaterialReference m_MaterialOverrides;
CHandle<C_BaseAnimating> m_hViewmodelAttachment;
int m_iOldTeam;
bool m_bAttachmentDirty;
int m_nUnloadedModelIndex;
int m_iNumOwnerValidationRetries;
#endif
EHANDLE m_hOldProvidee;
#ifdef GAME_DLL
int m_iOldOwnerClass; // Used to detect class changes on items that have per-class models
#endif
protected:
#ifdef CLIENT_DLL
public:
// Additional attachments.
struct AttachedModelData_t
{
const model_t *m_pModel;
int m_iModelDisplayFlags;
};
CUtlVector<AttachedModelData_t> m_vecAttachedModels;
#endif // CLIENT_DLL
};
#define ITEM_PICKUP_BOX_BLOAT 24
#define VIEWMODEL_CLASS_RESTRICTION_DEFAULT_NONE -1
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CBaseAttributableItem : public CEconEntity
{
DECLARE_CLASS( CBaseAttributableItem, CBaseAnimating );
public:
DECLARE_NETWORKCLASS();
DECLARE_DATADESC();
CBaseAttributableItem();
};
#endif // ECON_ENTITY_H

View File

@@ -0,0 +1,196 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "econ_entity_creation.h"
#include "utldict.h"
#include "filesystem.h"
#include "keyvalues.h"
#include "attribute_manager.h"
#include "vgui/ILocalize.h"
#include "tier3/tier3.h"
#include "util_shared.h"
#include "props_shared.h"
//==================================================================================
// GENERATION SYSTEM
//==================================================================================
CItemGeneration g_ItemGenerationSystem;
CItemGeneration *ItemGeneration( void )
{
return &g_ItemGenerationSystem;
}
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CItemGeneration::CItemGeneration( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Generate a random item matching the specified criteria
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::GenerateRandomItem( CItemSelectionCriteria *pCriteria, const Vector &vecOrigin, const QAngle &vecAngles )
{
entityquality_t iQuality;
int iChosenItem = ItemSystem()->GenerateRandomItem( pCriteria, &iQuality );
if ( iChosenItem == INVALID_ITEM_INDEX )
return NULL;
return SpawnItem( iChosenItem, vecOrigin, vecAngles, pCriteria->GetItemLevel(), iQuality, NULL );
}
//-----------------------------------------------------------------------------
// Purpose: Generate a random item matching the specified definition index
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::GenerateItemFromDefIndex( int iDefIndex, const Vector &vecOrigin, const QAngle &vecAngles )
{
return SpawnItem( iDefIndex, vecOrigin, vecAngles, 1, AE_UNIQUE, NULL );
}
//-----------------------------------------------------------------------------
// Purpose: Generate an item from the specified item data
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::GenerateItemFromScriptData( CEconItemView *pData, const Vector &vecOrigin, const QAngle &vecAngles, const char *pszOverrideClassName )
{
return SpawnItem( pData, vecOrigin, vecAngles, pszOverrideClassName );
}
//-----------------------------------------------------------------------------
// Purpose: Generate the base item for a class's loadout slot
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::GenerateBaseItem( struct baseitemcriteria_t *pCriteria )
{
int iChosenItem = ItemSystem()->GenerateBaseItem( pCriteria );
if ( iChosenItem == INVALID_ITEM_INDEX )
return NULL;
return SpawnItem( iChosenItem, vec3_origin, vec3_angle, 1, AE_NORMAL, NULL );
}
//-----------------------------------------------------------------------------
// Purpose: Create a new instance of the chosen item
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::SpawnItem( int iChosenItem, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles, int iItemLevel, entityquality_t entityQuality, const char *pszOverrideClassName )
{
const CEconItemDefinition *pData = ItemSystem()->GetStaticDataForItemByDefIndex( iChosenItem );
if ( !pData )
return NULL;
if ( !pszOverrideClassName )
{
pszOverrideClassName = pData->GetItemClass();
}
CBaseEntity *pItem = CreateEntityByName( pszOverrideClassName );
if ( !pItem )
return NULL;
// Set the item level & quality
IHasAttributes *pItemInterface = dynamic_cast<IHasAttributes *>(pItem);
Assert( pItemInterface );
if ( pItemInterface )
{
// Setup the script item. Don't generate attributes here, because it'll be done during entity spawn.
CEconItemView *pScriptItem = pItemInterface->GetAttributeContainer()->GetItem();
pScriptItem->Init( iChosenItem, entityQuality, iItemLevel, false );
}
return PostSpawnItem( pItem, pItemInterface, vecAbsOrigin, vecAbsAngles );
}
//-----------------------------------------------------------------------------
// Purpose: Create a base entity for the specified item data
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::SpawnItem( CEconItemView *pData, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles, const char *pszOverrideClassName )
{
if ( !pData->GetStaticData() )
return NULL;
if ( !pszOverrideClassName )
{
pszOverrideClassName = pData->GetStaticData()->GetItemClass();
}
CBaseEntity *pItem = CreateEntityByName( pszOverrideClassName );
if ( !pItem )
return NULL;
// Set the item level & quality
IHasAttributes *pItemInterface = dynamic_cast<IHasAttributes *>(pItem);
Assert( pItemInterface );
if ( pItemInterface )
{
pItemInterface->GetAttributeContainer()->SetItem( pData );
}
return PostSpawnItem( pItem, pItemInterface, vecAbsOrigin, vecAbsAngles );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseEntity *CItemGeneration::PostSpawnItem( CBaseEntity *pItem, IHasAttributes *pItemInterface, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles )
{
const char *pszPlayerModel = NULL;
CEconItemView *pScriptItem = NULL;
if ( pItemInterface )
{
pScriptItem = pItemInterface->GetAttributeContainer()->GetItem();
pszPlayerModel = pScriptItem->GetPlayerDisplayModel();
}
#ifndef CSTRIKE15
if ( pScriptItem )
{
// For now, allow precaches until we have dynamic loading.
bool allowPrecache = CBaseEntity::IsPrecacheAllowed();
CBaseEntity::SetAllowPrecache( true );
CUtlVector<const char *> vecPrecacheModelStrings;
pScriptItem->GetStaticData()->GeneratePrecacheModelStrings( false, &vecPrecacheModelStrings );
// Precache the models and the gibs for everything the definition requested.
FOR_EACH_VEC( vecPrecacheModelStrings, i )
{
// Ignore any objects which requested an empty precache string for whatever reason.
if ( vecPrecacheModelStrings[i] && vecPrecacheModelStrings[i][0] )
{
int iModelIndex = CBaseEntity::PrecacheModel( vecPrecacheModelStrings[i] );
PrecacheGibsForModel( iModelIndex );
}
}
// Precache any replacement sounds for this item.
CUtlVector<const char *> vecPrecacheSoundStrings;
pScriptItem->GetStaticData()->GeneratePrecacheSoundStrings( &vecPrecacheSoundStrings );
FOR_EACH_VEC( vecPrecacheSoundStrings, i )
{
CBaseEntity::PrecacheScriptSound( vecPrecacheSoundStrings[i] );
}
// Precache any effects for this item
CUtlVector<const char *> vecPrecacheEffectStrings;
pScriptItem->GetStaticData()->GeneratePrecacheEffectStrings( &vecPrecacheEffectStrings );
FOR_EACH_VEC( vecPrecacheEffectStrings, i )
{
PrecacheEffect( vecPrecacheEffectStrings[i] );
}
CBaseEntity::SetAllowPrecache( allowPrecache );
}
#endif
#ifdef CLIENT_DLL
// If we create a clientside item, we need to force it to initialize attributes
if ( pItem->InitializeAsClientEntity( pszPlayerModel, false ) == false )
return NULL;
#endif
pItem->SetAbsOrigin( vecAbsOrigin );
pItem->SetAbsAngles( vecAbsAngles );
pItem->Spawn();
pItem->Activate();
return pItem;
}

View File

@@ -0,0 +1,50 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef ITEM_CREATION_H
#define ITEM_CREATION_H
#ifdef _WIN32
#pragma once
#endif
#include "igamesystem.h"
#include "econ_item_system.h"
#include "econ_entity.h"
#if defined(TF_CLIENT_DLL) || defined(TF_DLL)
#include "tf_shareddefs.h"
#endif
//-----------------------------------------------------------------------------
// Purpose: Game system that handles initializing the item system, and generating items as full game entities
//-----------------------------------------------------------------------------
class CItemGeneration : public CAutoGameSystem
{
public:
CItemGeneration( void );
// Generate a random item matching the specified criteria
CBaseEntity *GenerateRandomItem( CItemSelectionCriteria *pCriteria, const Vector &vecOrigin, const QAngle &vecAngles );
// Generate a random item matching the specified definition index
CBaseEntity *GenerateItemFromDefIndex( int iDefIndex, const Vector &vecOrigin, const QAngle &vecAngles );
// Generate an item from the specified item data
CBaseEntity *GenerateItemFromScriptData( CEconItemView *pData, const Vector &vecOrigin, const QAngle &vecAngles, const char *pszOverrideClassName );
// Generate the base item for a class's loadout slot
CBaseEntity *GenerateBaseItem( struct baseitemcriteria_t *pCriteria );
private:
// Create a new instance of the chosen item
CBaseEntity *SpawnItem( int iChosenItem, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles, int iItemLevel, entityquality_t entityQuality, const char *pszOverrideClassName );
CBaseEntity *SpawnItem( CEconItemView *pData, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles, const char *pszOverrideClassName );
CBaseEntity *PostSpawnItem( CBaseEntity *pItem, IHasAttributes *pItemInterface, const Vector &vecAbsOrigin, const QAngle &vecAbsAngles );
};
extern CItemGeneration *ItemGeneration( void );
#endif // ITEM_CREATION_H

View File

@@ -0,0 +1,17 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Code for the CEconGameAccount object
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
using namespace GCSDK;
#ifdef GC_DLL
IMPLEMENT_CLASS_MEMPOOL( CEconGameAccount, 10 * 1000, CUtlMemoryPool::GROW_SLOW );
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

View File

@@ -0,0 +1,49 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds the CEconGameAccount object
//
// $NoKeywords: $
//=============================================================================//
#ifndef ECON_GAME_ACCOUNT_H
#define ECON_GAME_ACCOUNT_H
#ifdef _WIN32
#pragma once
#endif
#include "gcsdk/schemasharedobject.h"
#include "rtime.h"
enum
{
kGameAccountFlags_ConvertedUniques = 1 << 0,
kGameAccountFlags_MadeFirstPurchase = 1 << 1,
kGameAccountFlags_ConvertItemFlagsToOrigin = 1 << 2,
kGameAccountFlags_ConvertPackageItemGrants = 1 << 3,
kGameAccountFlags_RemoveCafeOrSchoolItems = 1 << 4,
kGameAccountFlags_CleanupItemNames = 1 << 5,
kGameAccountFlags_NeedToChooseMostHelpfulFriend = 1 << 6,
kGameAccountFlags_DONT_USE_THIS_BUI_LIES = 1 << 7, // some accounts might have this set! it used to be the "needs to thank a friend" bit
kGameAccountFlags_OwnedGameServersDisabled = 1 << 8,
kGameAccountFlags_UpdatedEquippedSlots = 1 << 9,
kGameAccountFlags_MadeFirstWebPurchase = 1 << 10,
};
//---------------------------------------------------------------------------------
// Purpose: All the account-level information that the GC tracks
//---------------------------------------------------------------------------------
class CEconGameAccount : public GCSDK::CSchemaSharedObject< CSchGameAccount, k_EEconTypeGameAccount >
{
#ifdef GC_DLL
DECLARE_CLASS_MEMPOOL( CEconGameAccount );
#endif
public:
CEconGameAccount() {}
CEconGameAccount( uint32 unAccountID )
{
Obj().m_unAccountID = unAccountID;
}
};
#endif //ECON_GAME_ACCOUNT_H

View File

@@ -0,0 +1,21 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Code for the CEconGameAccountClient object
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "econ_game_account_client.h"
#if defined( CLIENT_DLL )
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
uint32 CEconGameAccountClient::ComputeXpBonusFlagsNow() const
{
/** Removed for partner depot **/
return 0;
}

View File

@@ -0,0 +1,44 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds the CEconGameAccountClient object
//
// $NoKeywords: $
//=============================================================================//
#ifndef ECON_GAME_ACCOUNT_CLIENT_H
#define ECON_GAME_ACCOUNT_CLIENT_H
#ifdef _WIN32
#pragma once
#endif
#include "gcsdk/protobufsharedobject.h"
#include "base_gcmessages.pb.h"
#include "cstrike15_gcmessages.pb.h"
enum EGameAccountElevatedState_t
{
k_EGameAccountElevatedState_None, // account has no verified phone on file
k_EGameAccountElevatedState_NotIdentifying, // account has phone, but it's not identifying
k_EGameAccountElevatedState_AwaitingCooldown, // account has identifying phone, but it cannot be used to become elevated yet (cooldown on changes)
k_EGameAccountElevatedState_Eligible, // account is apriori eligible to become premium, just needs to ask!
k_EGameAccountElevatedState_EligibleWithTakeover, // account is completely eligible, just need to confirm the phone takeover
k_EGameAccountElevatedState_Elevated, // account is fully elevated to premium
k_EGameAccountElevatedState_AccountCooldown, // account has identifying phone, but it is a different phone than recently used for upgrading (so account has a cooldown)
};
//---------------------------------------------------------------------------------
// Purpose: All the account-level information that the GC tracks
//---------------------------------------------------------------------------------
class CEconGameAccountClient : public GCSDK::CProtoBufSharedObject< CSOEconGameAccountClient, k_EEconTypeGameAccountClient >
{
public:
uint32 ComputeXpBonusFlagsNow() const;
};
// Persona data shared to the game server
class CEconPersonaDataPublic : public GCSDK::CProtoBufSharedObject < CSOPersonaDataPublic, k_EEconTypePersonaDataPublic >
{
public:
};
#endif //ECON_GAME_ACCOUNT_CLIENT_H

View File

@@ -0,0 +1,33 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Code for the CEconGameAccount object
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "econ_game_account_server.h"
using namespace GCSDK;
#ifdef GC_DLL
IMPLEMENT_CLASS_MEMPOOL( CEconGameServerAccount, 100, UTLMEMORYPOOL_GROW_SLOW );
void GameServerAccount_GenerateIdentityToken( char* pIdentityToken, uint32 unMaxChars )
{
static const char s_ValidChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./+!$%^-_+?<>()&~:";
const int nLastValidIndex = ARRAYSIZE(s_ValidChars) - 2; // last = size - 1, minus another one for null terminator
// create a randomized token
for ( uint32 i = 0; i < unMaxChars - 1; ++i )
{
pIdentityToken[i] = s_ValidChars[ RandomInt( 0, nLastValidIndex ) ];
}
pIdentityToken[unMaxChars - 1] = 0;
}
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

View File

@@ -0,0 +1,98 @@
//========= Copyright (c), Valve Corporation, All rights reserved. ============//
//
// Purpose: Holds the CEconGameServerAccount object
//
// $NoKeywords: $
//=============================================================================//
#ifndef ECON_GAME_SERVER_ACCOUNT_H
#define ECON_GAME_SERVER_ACCOUNT_H
#ifdef _WIN32
#pragma once
#endif
enum eGameServerOrigin
{
kGSAOrigin_Player = 0,
kGSAOrigin_Support = 1,
kGSAOrigin_AutoRegister = 2, // for valve-owned servers
};
enum eGameServerScoreStanding
{
kGSStanding_Good,
kGSStanding_Bad,
};
enum eGameServerScoreStandingTrend
{
kGSStandingTrend_Up,
kGSStandingTrend_SteadyUp,
kGSStandingTrend_Steady,
kGSStandingTrend_SteadyDown,
kGSStandingTrend_Down,
};
#ifdef GC
#include "gcsdk/schemasharedobject.h"
//---------------------------------------------------------------------------------
// Purpose:
//---------------------------------------------------------------------------------
class CEconGameServerAccount : public GCSDK::CSchemaSharedObject< CSchGameServerAccount, k_EEconTypeGameServerAccount >
{
#ifdef GC_DLL
DECLARE_CLASS_MEMPOOL( CEconGameServerAccount );
#endif
public:
CEconGameServerAccount() {}
CEconGameServerAccount( uint32 unAccountID )
{
Obj().m_unAccountID = unAccountID;
}
};
void GameServerAccount_GenerateIdentityToken( char* pIdentityToken, uint32 unMaxChars );
#endif // GC
inline const char *GameServerAccount_GetStandingString( eGameServerScoreStanding standing )
{
const char *pStanding = "Good";
switch ( standing )
{
case kGSStanding_Good:
pStanding = "Good";
break;
case kGSStanding_Bad:
pStanding = "Bad";
break;
} // switch
return pStanding;
}
inline const char *GameServerAccount_GetStandingTrendString( eGameServerScoreStandingTrend trend )
{
const char *pStandingTrend = "Steady";
switch ( trend )
{
case kGSStandingTrend_Up:
pStandingTrend = "Upward Fast";
break;
case kGSStandingTrend_SteadyUp:
pStandingTrend = "Slightly Upward";
break;
case kGSStandingTrend_Steady:
pStandingTrend = "Steady";
break;
case kGSStandingTrend_SteadyDown:
pStandingTrend = "Slightly Downward";
break;
case kGSStandingTrend_Down:
pStandingTrend = "Downward Fast";
break;
} // switch
return pStandingTrend;
}
#endif //ECON_GAME_SERVER_ACCOUNT_H

View File

@@ -0,0 +1,530 @@
//====== Copyright (C), Valve Corporation, All rights reserved. =======
//
// Purpose: This file defines all of our over-the-wire net protocols for the
// Game Coordinator for the item system. Note that we never use types
// with undefined length (like int). Always use an explicit type
// (like int32).
//
//=============================================================================
#ifndef ITEM_GCMESSAGES_H
#define ITEM_GCMESSAGES_H
#ifdef _WIN32
#pragma once
#endif
#pragma pack( push, 1 )
// generic zero-length message struct
struct MsgGCEmpty_t
{
};
// k_EMsgGCSetItemPosition
struct MsgGCSetItemPosition_t
{
uint64 m_unItemID;
uint32 m_unNewPosition;
};
// k_EMsgGCCraft
struct MsgGCCraft_t
{
int16 m_nRecipeDefIndex;
uint16 m_nItemCount;
// list of m_nItemCount uint64 item IDs
};
// k_EMsgGCDelete
struct MsgGCDelete_t
{
uint64 m_unItemID;
bool m_bRecycle;
};
// k_EMsgGCCraftResponse
struct MsgGCStandardResponse_t
{
int16 m_nResponseIndex;
uint32 m_eResponse;
};
// k_EMsgGCVerifyCacheSubscription
struct MsgGCVerifyCacheSubscription_t
{
uint64 m_ulSteamID;
};
// k_EMsgGCNameItem
struct MsgGCNameItem_t
{
uint64 m_unToolItemID; // the Nametag item
uint64 m_unSubjectItemID; // the item to be renamed
bool m_bDescription;
// Varchar: Item name
};
// k_EMsgGCNameBaseItem
struct MsgGCNameBaseItem_t
{
uint64 m_unToolItemID; // the Nametag item
uint32 m_unBaseItemDefinitionID; // the base item definition to be renamed
bool m_bDescription;
// Varchar: Item name
};
// k_EMsgGCUnlockCrate
struct MsgGCUnlockCrate_t
{
uint64 m_unToolItemID; // the crate key
uint64 m_unSubjectItemID; // the crate to be decoded
};
// k_EMsgGCPaintItem
struct MsgGCPaintItem_t
{
uint64 m_unToolItemID; // the Paint Can item
uint64 m_unSubjectItemID; // the item to be painted
bool m_bUnusualPaint; // the paint event is unusual paint
};
// k_EMsgGCPaintKitItem
struct MsgGCPaintKitItem_t
{
uint64 m_unToolItemID; // the Paint Kit item
uint64 m_unSubjectItemID; // the item to be painted
bool m_bUnusualPaint; // the paint event is unusual paint
};
// k_EMsgGCPaintKitBaseItem
struct MsgGCPaintKitBaseItem_t
{
uint64 m_unToolItemID; // the Paint Kit item
uint32 m_unBaseItemDefinitionID; // the base item definition to be painted
};
// k_EMsgGCPaintKitBaseItem
struct MsgGCDev_PaintKitItemDrop_t
{
uint32 m_unPaintID; // the Paint Kit ID
uint32 m_unBaseItemDefinitionID; // the base item definition to be painted
int m_nStrangeType;
};
// k_EMsgGCGiftWrapItem
struct MsgGCGiftWrapItem_t
{
uint64 m_unToolItemID; // the Gift Wrap item
uint64 m_unSubjectItemID; // the item to be wrapped
};
// k_EMsgGCDeliverGift
struct MsgGCDeliverGift_t
{
uint64 m_unGiftID;
uint64 m_ulGiverSteamID;
uint64 m_ulTargetSteamID;
};
// k_EMsgGCUnwrapGiftRequest
struct MsgGCUnwrapGiftRequest_t
{
uint64 m_unItemID;
};
// k_EMsgGCMOTDRequest
struct MsgGCMOTDRequest_t
{
RTime32 m_nLastMOTDRequest; // Time at which the client last asked for MOTDs. GC will send back all MOTDs posted since.
int16 m_eLanguage;
};
// k_EMsgGCMOTDRequestResponse
struct MsgGCMOTDRequestResponse_t
{
int16 m_nEntries;
};
// k_EMsgGCCustomizeItemTexture
struct MsgGCCustomizeItemTexture_t
{
uint64 m_unToolItemID; // the tool
uint64 m_unSubjectItemID; // the item wants the texture
uint64 m_unImageUGCHandle; // cloud ID of image file (UGCHandle_t)
};
// k_EMsgGCSetItemStyle
struct MsgGCSetItemStyle_t
{
uint64 m_unItemID;
uint8 m_iStyle;
};
// k_EMsgGCUnlockItemStyle
struct MsgGCUnlockItemStyle_t
{
uint64 m_unItemID;
uint8 m_iStyle;
};
// k_EMsgGCUnlockItemStyleResponse
struct MsgGCUnlockItemStyleResponse_t
{
uint64 m_unItemID;
uint8 m_iStyle;
uint8 m_iStylePreReq;
uint8 m_iResult;
};
// k_EMsgGCItemPreviewCheckStatus
struct MsgGCCheckItemPreviewStatus_t
{
uint32 m_unItemDefIndex;
};
// k_EMsgGCItemPreviewCheckStatusResponse
struct MsgGCItemPreviewCheckStatusResponse_t
{
uint32 m_unItemDefIndex;
uint32 m_eResponse;
RTime32 m_timePreviewTime;
};
// k_EMsgGCItemPreviewRequest
struct MsgGCItemPreviewRequest_t
{
uint32 m_unItemDefIndex;
};
// k_EMsgGCItemPreviewRequestResponse
struct MsgGCItemPreviewRequestResponse_t
{
uint32 m_unItemDefIndex;
uint32 m_eResponse;
};
// k_EMsgGCItemPreviewExpireNotification
struct MsgGCItemPreviewExpireNotification_t
{
uint32 m_unItemDefIndex;
};
// k_EMsgGCItemPreviewItemBoughtNotification
struct MsgGCItemPreviewItemBoughtNotification_t
{
uint32 m_unItemDefIndex;
};
//-----------------------------------------------------------------------------
// k_EMsgGCUseItemResponse
enum EGCMsgUseItemResponse
{
k_EGCMsgUseItemResponse_ItemUsed = 0,
k_EGCMsgUseItemResponse_GiftNoOtherPlayers = 1,
k_EGCMsgUseItemResponse_ServerError = 2,
k_EGCMsgUseItemResponse_MiniGameAlreadyStarted = 3,
k_EGCMsgUseItemResponse_ItemUsed_ItemsGranted = 4,
k_EGCMsgUseItemResponse_DropRateBonusAlreadyGranted = 5,
k_EGCMsgUseItemResponse_NotInLowPriorityPool = 6,
k_EGCMsgUseItemResponse_ForceSizeInt = 0x7FFFFFFF
};
// k_EMsgGCUseItemResponse
struct MsgGCUseItemResponse_t
{
uint32 m_eResponse;
uint32 m_unDefIndex;
};
// DEPRECATED : k_EMsgGCGiftedItems_DEPRECATED
// struct MsgGCGiftedItems_t
// {
// uint64 m_ulGifterSteamID;
// bool m_bRandomPerson;
// uint8 m_unNumGiftRecipients;
// // other data dynamically added:
// // steam ids of all the recipients
// };
// k_EMsgGCRemoveItemName
struct MsgGCRemoveItemName_t
{
uint64 m_unItemID;
bool m_bDescription;
};
// k_EMsgGCRemoveItemPaint
struct MsgGCRemoveItemPaint_t
{
uint64 m_unItemID;
};
// MsgGCRemoveItemCustomTexture_t
struct MsgGCRemoveItemCustomTexture_t
{
uint64 m_unItemID;
};
// MsgGCRemoveItemMakersMark_t
struct MsgGCRemoveItemMakersMark_t
{
uint64 m_unItemID;
};
// MsgGCRemoveItemUniqueCraftIndex_t
struct MsgGCRemoveItemUniqueCraftIndex_t
{
uint64 m_unItemID;
};
// k_EMsgGCApplyConsumableEffects
struct MsgGCApplyConsumableEffects_t
{
uint64 m_ulInitiatorSteamID;
uint32 m_unItemDefinitionID;
};
//-----------------------------------------------------------------------------
// Trading
// k_EMsgGCTrading_InitiateTradeRequest
struct MsgGCTrading_InitiateTradeRequest_t
{
uint32 m_unTradeRequestID;
uint64 m_ulOtherSteamID;
// @note player A's name as string when sent to party B
};
enum EGCMsgInitiateTradeResponse
{
k_EGCMsgInitiateTradeResponse_Accepted = 0,
k_EGCMsgInitiateTradeResponse_Declined = 1,
k_EGCMsgInitiateTradeResponse_VAC_Banned_Initiator = 2,
k_EGCMsgInitiateTradeResponse_VAC_Banned_Target = 3,
k_EGCMsgInitiateTradeResponse_Target_Already_Trading = 4,
k_EGCMsgInitiateTradeResponse_Disabled = 5,
k_EGCMsgInitiateTradeResponse_NotLoggedIn = 6,
k_EGCMsgInitiateTradeResponse_Cancel = 7,
k_EGCMsgInitiateTradeResponse_TooSoon = 8,
k_EGCMsgInitiateTradeResponse_TooSoonPenalty = 9,
k_EGCMsgInitiateTradeResponse_Trade_Banned_Initiator = 10,
k_EGCMsgInitiateTradeResponse_Trade_Banned_Target = 11,
k_EGCMsgInitiateTradeResponse_Free_Account_Initiator_DEPRECATED = 12, // free accounts can initiate trades now
k_EGCMsgInitiateTradeResponse_Shared_Account_Initiator= 13,
k_EGCMsgInitiateTradeResponse_Service_Unavailable = 14,
k_EGCMsgInitiateTradeResponse_Count,
k_EGCMsgInitiateTradeResponse_ForceSizeInt = 0x7FFFFFFF
};
// k_EMsgGCTrading_InitiateTradeResponse
struct MsgGCTrading_InitiateTradeResponse_t
{
uint32 m_eResponse;
uint32 m_unTradeRequestID;
};
// k_EMsgGCTrading_StartSession
struct MsgGCTrading_StartSession_t
{
uint32 m_unSessionVersion;
uint64 m_ulSteamIDPartyA;
uint64 m_ulSteamIDPartyB;
// @note strings from player names will be added to the message
};
// k_EMsgGCTrading_SetItem
struct MsgGCTrading_SetItem_t
{
bool m_bShowcase;
uint64 m_unItemID;
uint8 m_unPosition;
};
// k_EMsgGCTrading_RemoveItem
struct MsgGCTrading_RemoveItem_t
{
uint64 m_unItemID;
};
// k_EMsgGCTrading_UpdateTradeInfo
struct MsgGCTrading_UpdateTradeInfo_t
{
uint32 m_unSessionVersion;
uint8 m_unNumItemsPartyA;
uint8 m_unNumItemsPartyB;
uint8 m_unNumShowcaseItemsPartyA;
uint8 m_unNumShowcaseItemsPartyB;
// @note 4 lists of item ids in the order above
};
// k_EMsgGCTrading_SetReadiness
struct MsgGCTrading_SetReadiness_t
{
uint32 m_unSessionVersion;
bool m_bReady;
};
// k_EMsgGCTrading_ConfirmOffer
struct MsgGCTrading_ConfirmOffer_t
{
uint32 m_unConfirmedSessionVersion;
};
// k_EMsgGCTrading_ReadinessResponse
struct MsgGCTrading_ReadinessResponse_t
{
uint32 m_unSessionVersion;
bool m_bIsReadyPartyA;
bool m_bIsReadyPartyB;
bool m_bConfirmedByPartyA;
bool m_bConfirmedByPartyB;
};
enum EGCMsgSessionClosed
{
k_EGCMsgSessionClosed_ItemsTraded = 0,
k_EGCMsgSessionClosed_Canceled = 1,
k_EGCMsgSessionClosed_Error = 2,
k_EGCMsgSessionClosed_DoesNotOwnItems = 3,
k_EGCMsgSessionClosed_UntradableItems = 4,
k_EGCMsgSessionClosed_NoItems = 5,
k_EGCMsgSessionClosed_Disabled = 6,
k_EGCMsgSessionClosed_ForceSizeInt = 0x7FFFFFFF
};
// k_EMsgGCTrading_SessionClosed
struct MsgGCTrading_SessionClosed_t
{
uint32 m_eReason;
};
// k_EMsgGCTrading_CancelSession
struct MsgGCTrading_CancelSession_t
{
};
// k_EMsgGCTrading_TradeChatMsg
struct MsgGCTrading_TradeChatMsg_t
{
// char* variable length chat message, up to 128 characters
};
// k_EMsgGCTrading_TradeTypingChatMsg
struct MsgGCTrading_TradeTypingChatMsg_t
{
// empty
};
// k_EMsgGCUsedClaimCodeItem
struct MsgGCUsedClaimCodeItem_t
{
// string of URL
};
//-----------------------------------------------------------------------------
// ServerBrowser messages
enum EGCMsgServerBrowser
{
k_EGCMsgServerBrowser_FromServerBrowser = 0,
k_EGCMsgServerBrowser_FromAutoAskDialog = 1,
};
// k_EMsgGCServerBrowser_FavoriteServer
// k_EMsgGCServerBrowser_BlacklistServer
struct MsgGCServerBrowser_Server_t
{
uint32 m_unIP;
int m_usPort;
uint8 m_ubSource; // 0=serverbrowser, 1=auto-ask dialog
};
//-----------------------------------------------------------------------------
// Public facing loot lists.
// k_EMsgGC_RevolvingLootList
struct MsgGC_RevolvingLootList_t
{
uint8 m_usListID; // Id of this list.
// Var Data:
// Serialized Lootlist KV
};
//-----------------------------------------------------------------------------
// Microtransactions
// k_EMsgGCStorePurchaseFinalize
struct MsgGCStorePurchaseFinalize_t
{
uint64 m_ulTxnID; // Transaction ID for the the transaction
};
//k_EMsgGCStorePurchaseFinalizeResponse
struct MsgGCStorePurchaseFinalizeResponse_t
{
int16 m_eResult; // Result of the operation
uint32 m_cItemIDs; // Number of items contained in the purchase
// Var Data:
// If successful, list of m_cItemIDs uint64's
// that represent the purchased items
};
//k_EMsgGCStorePurchaseCancel
struct MsgGCStorePurchaseCancel_t
{
uint64 m_ulTxnID; // Transaction ID for the the transaction
};
//k_EMsgGCStorePurchaseCancelResponse
struct MsgGCStorePurchaseCancelResponse_t
{
int16 m_eResult; // Result of the operation
};
//k_EMsgGCStorePurchaseQueryTxn
struct MsgGCStorePurchaseQueryTxn_t
{
uint64 m_ulTxnID; // Transaction ID for the the transaction
};
//k_EMsgGCStorePurchaseQueryTxnResponse
struct MsgGCStorePurchaseQueryTxnResponse_t
{
int16 m_eResult; // Result of the operation
int16 m_ePurchaseState; // State of the queried transaction
uint32 m_cItemIDs; // Number of items contained in the purchase
// Var Data:
// If the order is final, list of m_cItemIDs uint64's
// that represent the items purchased by this order
};
// k_EMsgGCLookupAccount
struct MsgGCLookupAccount_t
{
uint16 m_uiFindType;
// Var Data
// string containing Persona / URL / etc
};
// k_EMsgGCLookupAccountResponse
// k_EMsgGCLookupAccountName
struct MsgGCLookupAccountName_t
{
uint32 m_unAccountID;
};
// k_EMsgGCLookupAccountNameResponse
struct MsgGCLookupAccountNameResponse_t
{
uint32 m_unAccountID;
// string containing persona name
};
#pragma pack( pop )
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,588 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: CEconItem, a shared object for econ items
//
//=============================================================================
#ifndef ECONITEM_H
#define ECONITEM_H
#ifdef _WIN32
#pragma once
#endif
#include "gcsdk/gcclientsdk.h"
#include "base_gcmessages.pb.h"
#include "econ_item_constants.h"
#include "econ_item_interface.h"
#include "econ_item_schema.h"
#include <typeinfo> // needed for typeid()
#define ENABLE_TYPED_ATTRIBUTE_PARANOIA 1
namespace GCSDK
{
class CColumnSet;
};
class CEconItem;
class CSOEconItem;
class CEconItemCustomData;
class CEconSessionItemAudit;
//-----------------------------------------------------------------------------
// Stats tracking for the attributes attached to CEconItem instances.
//-----------------------------------------------------------------------------
struct schema_attribute_stat_bucket_t
{
const schema_attribute_stat_bucket_t *m_pNext;
const char *m_pszDesc;
uint64 m_unLiveInlineCount;
uint64 m_unLifetimeInlineCount;
uint64 m_unLiveHeapCount;
uint64 m_unLifetimeHeapCount;
void OnAllocateInlineInstance() { m_unLiveInlineCount++; m_unLifetimeInlineCount++; }
void OnFreeInlineInstance() { /* temporarily disabling to avoid spew until the rest of the minor attribute changelists are brought from TF to Dota: -> Assert( m_unLiveInlineCount > 0 ); */ m_unLiveInlineCount--; }
void OnAllocateHeapInstance() { m_unLiveHeapCount++; m_unLifetimeHeapCount++; }
void OnFreeHeapInstance() { Assert( m_unLiveHeapCount ); m_unLiveHeapCount--; }
};
class CSchemaAttributeStats
{
public:
template < typename TAttribStatsStorageClass, typename TAttribInMemoryType >
static void RegisterAttributeType()
{
TAttribStatsStorageClass::s_InstanceStats.m_pszDesc = typeid( TAttribInMemoryType ).name();
TAttribStatsStorageClass::s_InstanceStats.m_pNext = m_pHead;
m_pHead = &TAttribStatsStorageClass::s_InstanceStats;
}
static const schema_attribute_stat_bucket_t *GetFirstStatBucket()
{
return m_pHead;
}
private:
static const schema_attribute_stat_bucket_t *m_pHead;
};
//-----------------------------------------------------------------------------
// Base class interface for attributes of a certain in-memory type.
//-----------------------------------------------------------------------------
template < typename T >
unsigned int GetAttributeTypeUniqueIdentifier();
template < typename TAttribInMemoryType >
class ISchemaAttributeTypeBase : public ISchemaAttributeType
{
friend class CSchemaAttributeStats;
public:
ISchemaAttributeTypeBase()
{
CSchemaAttributeStats::RegisterAttributeType< ISchemaAttributeTypeBase<TAttribInMemoryType>, TAttribInMemoryType >();
}
virtual void LoadEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const union attribute_data_union_t& value ) const OVERRIDE;
// Returns a unique identifier per run based on the type of <TAttribInMemoryType>.
virtual unsigned int GetTypeUniqueIdentifier() const OVERRIDE
{
return GetAttributeTypeUniqueIdentifier<TAttribInMemoryType>();
}
// ...
void ConvertTypedValueToEconAttributeValue( const TAttribInMemoryType& typedValue, attribute_data_union_t *out_pValue ) const
{
// If our type is smaller than an int, we don't know how to copy the memory into our flat structure. We could write
// this code but we have no use case for it now so this is set up to fail so if someone does come up with a use case
// they know where to fix.
COMPILE_TIME_ASSERT( sizeof( TAttribInMemoryType ) >= sizeof( uint32 ) );
// Do we fit in the bottom 32-bits?
if ( sizeof( TAttribInMemoryType ) <= sizeof( uint32 ) )
{
*reinterpret_cast<TAttribInMemoryType *>( &out_pValue->asUint32 ) = typedValue;
}
// What about in the full 64-bits (if we're running a 64-bit build)?
else if ( sizeof( TAttribInMemoryType ) <= sizeof( void * ) )
{
*reinterpret_cast<TAttribInMemoryType *>( &out_pValue->asBlobPointer ) = typedValue;
}
// We're too big for our flat structure. We need to allocate space somewhere outside our attribute instance and point
// to that.
else
{
if ( !out_pValue->asBlobPointer )
{
InitializeNewEconAttributeValue( out_pValue );
}
*reinterpret_cast<TAttribInMemoryType *>( out_pValue->asBlobPointer ) = typedValue;
}
}
// Guaranteed to return a valid reference (or assert/crash if calling code is behaving inappropriately and calling
// this before an attribute value is allocated/set).
const TAttribInMemoryType& GetTypedValueContentsFromEconAttributeValue( const attribute_data_union_t& value ) const
{
COMPILE_TIME_ASSERT( sizeof( TAttribInMemoryType ) >= sizeof( uint32 ) );
// Do we fit in the bottom 32-bits?
if ( sizeof( TAttribInMemoryType ) <= sizeof( uint32 ) )
return *reinterpret_cast<const TAttribInMemoryType *>( &value.asUint32 );
// What about in the full 64-bits (if we're running a 64-bit build)?
if ( sizeof( TAttribInMemoryType ) <= sizeof( void * ) )
return *reinterpret_cast<const TAttribInMemoryType *>( &value.asBlobPointer );
// We don't expect to get to a "read value" call without having written a value, which would
// have allocated this memory.
Assert( value.asBlobPointer );
return *reinterpret_cast<const TAttribInMemoryType *>( value.asBlobPointer );
}
void ConvertEconAttributeValueToTypedValue( const attribute_data_union_t& value, TAttribInMemoryType *out_pTypedValue ) const
{
Assert( out_pTypedValue );
*out_pTypedValue = GetTypedValueContentsFromEconAttributeValue( value );
}
void InitializeNewEconAttributeValue( attribute_data_union_t *out_pValue ) const OVERRIDE
{
if ( sizeof( TAttribInMemoryType ) <= sizeof( uint32 ) )
{
new( &out_pValue->asUint32 ) TAttribInMemoryType;
s_InstanceStats.OnAllocateInlineInstance();
}
else if ( sizeof( TAttribInMemoryType ) <= sizeof( void * ) )
{
new( &out_pValue->asBlobPointer ) TAttribInMemoryType;
s_InstanceStats.OnAllocateInlineInstance();
}
else
{
out_pValue->asBlobPointer = reinterpret_cast<byte *>( new TAttribInMemoryType );
s_InstanceStats.OnAllocateHeapInstance();
}
}
virtual void UnloadEconAttributeValue( attribute_data_union_t *out_pValue ) const OVERRIDE
{
COMPILE_TIME_ASSERT( sizeof( TAttribInMemoryType ) >= sizeof( uint32 ) );
// For smaller types, anything that fits inside the bits of a void pointer, we store the contents
// inline and only have to worry about calling the correct destructor. We check against the small-/
// size/medium-size values separately to not worry about which bits we're storing the uint32 in.
if ( sizeof( TAttribInMemoryType ) <= sizeof( uint32 ) )
{
(reinterpret_cast<TAttribInMemoryType *>( &out_pValue->asUint32 ))->~TAttribInMemoryType();
s_InstanceStats.OnFreeInlineInstance();
}
else if ( sizeof( TAttribInMemoryType ) <= sizeof( void * ) )
{
(reinterpret_cast<TAttribInMemoryType *>( &out_pValue->asBlobPointer ))->~TAttribInMemoryType();
s_InstanceStats.OnFreeInlineInstance();
}
// For larger types, we have the memory stored on the heap somewhere. We don't have to manually
// destruct, but we do have to manually free.
else
{
if ( !out_pValue->asBlobPointer )
return;
delete reinterpret_cast<TAttribInMemoryType *>( out_pValue->asBlobPointer );
s_InstanceStats.OnFreeHeapInstance();
}
}
virtual bool OnIterateAttributeValue( IEconItemAttributeIterator *pIterator, const CEconItemAttributeDefinition *pAttrDef, const attribute_data_union_t& value ) const OVERRIDE
{
Assert( pIterator );
Assert( pAttrDef );
// Call the appropriate virtual function on our iterator based on whatever type we represent.
return pIterator->OnIterateAttributeValue( pAttrDef, GetTypedValueContentsFromEconAttributeValue( value ) );
}
virtual void LoadByteStreamToEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const std::string& sBytes ) const OVERRIDE;
virtual void ConvertEconAttributeValueToByteStream( const attribute_data_union_t& value, ::std::string *out_psBytes ) const;
virtual void ConvertTypedValueToByteStream( const TAttribInMemoryType& typedValue, ::std::string *out_psBytes ) const = 0;
virtual void ConvertByteStreamToTypedValue( const ::std::string& sBytes, TAttribInMemoryType *out_pTypedValue ) const = 0;
private:
static schema_attribute_stat_bucket_t s_InstanceStats;
};
template < typename TAttribInMemoryType >
schema_attribute_stat_bucket_t ISchemaAttributeTypeBase<TAttribInMemoryType>::s_InstanceStats;
class CEconItem : public GCSDK::CSharedObject, public IEconItemInterface
{
public:
typedef GCSDK::CSharedObject BaseClass;
struct attribute_t
{
attrib_definition_index_t m_unDefinitionIndex; // stored as ints here for memory efficiency on the GC
attribute_data_union_t m_value;
private:
void operator=( const attribute_t& rhs );
};
struct EquippedInstance_t
{
EquippedInstance_t() : m_unEquippedClass( 0 ), m_unEquippedSlot( INVALID_EQUIPPED_SLOT ) {}
EquippedInstance_t( equipped_class_t unClass, equipped_slot_t unSlot ) : m_unEquippedClass( unClass ), m_unEquippedSlot( unSlot ) {}
equipped_class_t m_unEquippedClass;
equipped_slot_t m_unEquippedSlot;
};
struct CustomDataOptimizedObject_t
{
// This is preceding the attributes block, attributes tightly packed and follow immediately
// 25% of CS:GO items have no attributes and don't allocate anything here
// one attribute case = [uint16] + [uint16+uint32] = 8 bytes (SBH bucket 8)
// 2 attributes case = [uint16]+2x[uint16+uint32] = 14 bytes (SBH bucket 16)
// 3 attributes case = [uint16]+3x[uint16+uint32] = 20 bytes (SBH bucket 24) (60% of CS:GO items)
// 4 attributes case = [uint16]+4x[uint16+uint32] = 26 bytes (SBH bucket 32)
// 5 attributes case = [uint16]+4x[uint16+uint32] = 26 bytes (SBH bucket 32)
uint16 m_equipInstanceSlot1 : 6; // Equip Instance Slot #6 // if equipped
uint16 m_equipInstanceClass1 : 3; // Equip Instance Class #9
uint16 m_equipInstanceClass2Bit : 1; // Whether the item is equipped for complementary class #10
uint16 m_numAttributes : 6; // Length of following attributes #16
// 32-bit GC size = 2 bytes!
inline attribute_t * GetAttribute( uint32 j ) { return ( reinterpret_cast< attribute_t * >( this + 1 ) ) + j ; }
inline const attribute_t * GetAttribute( uint32 j ) const { return ( reinterpret_cast< const attribute_t * >( this + 1 ) ) + j ; }
private: // forbid all operations including constructor/destructor
CustomDataOptimizedObject_t();
CustomDataOptimizedObject_t( const CustomDataOptimizedObject_t & );
~CustomDataOptimizedObject_t();
CustomDataOptimizedObject_t & operator=( const CustomDataOptimizedObject_t & );
public:
static CustomDataOptimizedObject_t *Alloc( uint32 numAttributes ); // allocates enough memory to include attributes
static attribute_t * AddAttribute( CustomDataOptimizedObject_t * &rptr ); // reallocs the ptr
void RemoveAndFreeAttrMemory( uint32 idxAttributeInArray ); // keeps the memory allocated
void FreeObjectAndAttrMemory();
};
// Set only the top 16 bits for field ID types! These will be or'd into the index of
// the field itself and then pulled apart later.
enum
{
kUpdateFieldIDType_FieldID = 0x00000000, // this must stay as 0 for legacy code
kUpdateFieldIDType_AttributeID = 0x00010000, // this will modify existing attribute in the database
};
const static int k_nTypeID = k_EEconTypeItem;
virtual int GetTypeID() const { return k_nTypeID; }
CEconItem();
virtual ~CEconItem();
private:
CEconItem( const CEconItem &copy ); // no impl - don't want to allow accidental pass-by-value
public:
CEconItem &operator=( const CEconItem& rhs );
// IEconItemInterface interface.
const GameItemDefinition_t *GetItemDefinition() const;
public:
#ifndef GC_DLL
virtual void SetSOUpdateFrame( int nNewValue ) const { m_bSOUpdateFrame = nNewValue; }
virtual int GetSOUpdateFrame( void ) const { return m_bSOUpdateFrame; }
#endif
virtual void IterateAttributes( class IEconItemAttributeIterator *pIterator ) const;
// Accessors/Settors
virtual itemid_t GetItemID() const { return m_ulID; }
void SetItemID( uint64 ulID );
itemid_t GetOriginalID() const;
void SetOriginalID( uint64 ulOriginalID );
uint32 GetAccountID() const { return m_unAccountID; }
void SetAccountID( uint32 unAccountID ) { m_unAccountID = unAccountID; }
item_definition_index_t GetDefinitionIndex() const { return m_unDefIndex; }
void SetDefinitionIndex( uint32 unDefinitionIndex ) { m_unDefIndex = unDefinitionIndex; }
uint32 GetItemLevel() const { return m_unLevel; }
void SetItemLevel( uint32 unItemLevel ) { m_unLevel = unItemLevel; }
int32 GetQuality() const { return m_nQuality; }
void SetQuality( int32 nQuality ) { m_nQuality = nQuality; }
int32 GetRarity() const;
void SetRarity( int32 nRarity ) { m_nRarity = nRarity; }
uint32 GetInventoryToken() const { return m_unInventory; }
void SetInventoryToken( uint32 unToken ) { m_unInventory = unToken; }
uint16 GetQuantity() const;
void SetQuantity( uint16 unQuantity );
uint8 GetFlags() const { return m_unFlags; }
void SetFlags( uint8 unFlags ) { m_unFlags = unFlags; }
void SetFlag( uint8 unFlag ) { m_unFlags |= unFlag; }
void ClearFlag( uint8 unFlag ) { m_unFlags &= ~unFlag; }
bool CheckFlags( uint8 unFlags ) const { return ( m_unFlags & unFlags ) != 0; }
eEconItemOrigin GetOrigin() const { return (eEconItemOrigin)m_unOrigin; }
void SetOrigin( eEconItemOrigin unOrigin ) { m_unOrigin = unOrigin; Assert( m_unOrigin == unOrigin ); }
bool IsForeign() const { return m_unOrigin == kEconItemOrigin_Foreign; }
const char *GetCustomName() const;
void SetCustomName( const char *pName );
const char *GetCustomDesc() const;
void SetCustomDesc( const char *pDesc );
virtual int GetItemSetIndex() const;
void InitAttributesDroppedFromListEntry( item_list_entry_t const *pEntryInfo );
bool IsEquipped() const;
bool IsEquippedForClass( equipped_class_t unClass ) const;
equipped_slot_t GetEquippedPositionForClass( equipped_class_t unClass ) const;
void UpdateEquippedState( equipped_class_t unClass, equipped_slot_t unSlot ) { UpdateEquippedState( EquippedInstance_t( unClass, unSlot ) ); }
void UpdateEquippedState( EquippedInstance_t equipInstance );
virtual bool GetInUse() const;
void SetInUse( bool bInUse );
bool IsTradable() const;
bool IsMarketable() const;
bool IsUsableInCrafting() const;
// --------------------------------------------------------------------------------------------
// Typed attributes. These are methods for accessing and setting values of attributes with
// some semblance of type information and type safety.
// --------------------------------------------------------------------------------------------
// Assign the value of the attribute [pAttrDef] to [value]. Passing in a type for [value] that
// doesn't match the storage type specified by the attribute definition will fail asserts a bunch
// of asserts all the way down the stack and may or may not crash -- it would be nice to make this
// fail asserts at compile time.
//
// This function has undefined results (besides asserting) if called to add a dynamic version of
// an attrib that's already specified statically.
template < typename T >
void SetDynamicAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const T& value )
{
Assert( pAttrDef );
const ISchemaAttributeTypeBase<T> *pAttrType = GetTypedAttributeType<T>( pAttrDef );
Assert( pAttrType );
if ( !pAttrType )
return;
// Fail right off the bat if we're trying to write a dynamic attribute value for an item that already
// has this as a static value.
/*
AssertMsg( !::FindAttribute( GetItemDefinition(), pAttrDef ),
"Item id %llu (%s) attempting to set dynamic attribute value for '%s' (%d) when static attribute exists!",
GetItemID(), GetItemDefinition()->GetDefinitionName(), pAttrDef->GetDefinitionName(), pAttrDef->GetDefinitionIndex() );
*/
// Alright, we have a data type match so we can safely store data. Some types may need to initialize
// their data to a current state if it's the first time we're writing to this value (as opposed to
// updating an existing value).
attribute_t *pEconAttrib = FindDynamicAttributeInternal( pAttrDef );
if ( !pEconAttrib )
{
pEconAttrib = &(AddDynamicAttributeInternal());
pEconAttrib->m_unDefinitionIndex = pAttrDef->GetDefinitionIndex();
pAttrType->InitializeNewEconAttributeValue( &pEconAttrib->m_value );
}
pAttrType->ConvertTypedValueToEconAttributeValue( value, &pEconAttrib->m_value );
#if ENABLE_TYPED_ATTRIBUTE_PARANOIA
// Paranoia!: make sure that our read/write functions are mirrored correctly, and that if we attempt
// to read back a value we get something identical to what we just wrote. We do this via converting
// to strings and then comparing those because there may or not be equality comparisons for our type
// T that make sense (ie., protobufs).
{
T readValue;
DbgVerify( FindAttribute( pAttrDef, &readValue ) );
std::string sBytes, sReadBytes;
pAttrType->ConvertTypedValueToByteStream( value, &sBytes );
pAttrType->ConvertTypedValueToByteStream( readValue, &sReadBytes );
AssertMsg1( sBytes == sReadBytes, "SetDynamicAttributeValue(): read/write mismatch for attribute '%s'.", pAttrDef->GetDefinitionName() );
}
#endif // ENABLE_TYPED_ATTRIBUTE_PARANOIA
}
// Remove an instance of an attribute from this item. This will also free any dynamic memory associated
// with that instance if any was allocated.
void RemoveDynamicAttribute( const CEconItemAttributeDefinition *pAttrDef );
// Copy all attributes and values in a type-safe way from [source] to ourself. Attributes that we have
// that don't exist on [source] will maintain their current values. All other attributes will get their
// values set to whatever [source] specifies.
void CopyAttributesFrom( const CEconItem& source );
// Copy everything about the item without the attributes
void CopyWithoutAttributesFrom( const CEconItem& source );
private:
template < typename T >
static const ISchemaAttributeTypeBase<T> *GetTypedAttributeType( const CEconItemAttributeDefinition *pAttrDef )
{
// Make sure the type of data we're passing in matches the type of data we're claiming that we can
// store in the attribute definition.
const ISchemaAttributeType *pIAttr = pAttrDef->GetAttributeType();
Assert( pIAttr );
Assert( pIAttr->GetTypeUniqueIdentifier() == GetAttributeTypeUniqueIdentifier<T>() );
#if ENABLE_TYPED_ATTRIBUTE_PARANOIA
return dynamic_cast<const ISchemaAttributeTypeBase<T> *>( pIAttr );
#else
return static_cast<const ISchemaAttributeTypeBase<T> *>( pIAttr );
#endif
}
public:
void AddCustomAttribute( uint16 usDefinitionIndex, float flValue );
void AddOrSetCustomAttribute( uint16 usDefinitionIndex, float flValue );
bool BDeserializeFromKV( KeyValues *pKVItem, const CEconItemSchema &pschema, CUtlVector<CUtlString> *pVecErrors = NULL );
virtual bool BParseFromMessage( const CUtlBuffer &buffer ) OVERRIDE;
virtual bool BParseFromMessage( const std::string &buffer ) OVERRIDE;
virtual bool BUpdateFromNetwork( const CSharedObject & objUpdate ) OVERRIDE;
virtual bool BAddToMessage( std::string *pBuffer ) const OVERRIDE; // short cut to remove an extra copy
virtual bool BAddDestroyToMessage( std::string *pBuffer ) const OVERRIDE;
virtual bool BIsKeyLess( const CSharedObject & soRHS ) const ;
virtual void Copy( const CSharedObject & soRHS );
virtual void Dump() const;
void SerializeToProtoBufItem( CSOEconItem &msgItem ) const;
void DeserializeFromProtoBufItem( const CSOEconItem &msgItem );
typedef CUtlVectorFixed< CEconItem::EquippedInstance_t, 2 > EquippedInstanceArray_t;
int GetEquippedInstanceArray( EquippedInstanceArray_t &equips ) const;
protected:
// CSharedObject
// adapted from CSchemaSharedObject
void GetDirtyColumnSet( const CUtlVector< int > &fields, GCSDK::CColumnSet &cs ) const;
void OnTransferredOwnership();
// Internal attribute interface.
friend class CWebAPIStringExporterAttributeIterator;
attribute_t& AddDynamicAttributeInternal(); // add another chunk of data to our internal storage to store a new attribute -- initialization is the responsibility of the caller
attribute_t *FindDynamicAttributeInternal( const CEconItemAttributeDefinition *pAttrDef ); // search for an instance of a dynamic attribute with this definition -- ignores static properties, etc. and will return NULL if not found
int GetDynamicAttributeCountInternal() const; // how many attributes are there attached to this instance?
const attribute_t & GetDynamicAttributeInternal( int iAttrIndexIntoArray ) const;
public:
//
// GC object data breakdown (32-bit build)
//
// already starting with TWO VTBLS due to multiple inheritance :(
// 8 bytes spent on VTBLS
//
// data that is most commonly changed
uint64 m_ulID; // Item ID
uint64 m_ulOriginalID; // Original ID is often different from item ID itself
// optional data (custom name, additional attributes, etc.)
CustomDataOptimizedObject_t *m_pCustomDataOptimizedObject;
uint32 m_unAccountID; // Item Owner
uint32 m_unInventory; // App managed int representing inventory placement
// === + 7*4 = 36 bytes here already, uint16 packing below ===
item_definition_index_t m_unDefIndex; // Item definition index +16
uint16 m_unOrigin : 5; // Origin (eEconItemOrigin) (0-31) #5
uint16 m_nQuality : 4; // Item quality (0-14) #9
uint16 m_unLevel:2; // Item Level (0-1-2-3) #11
uint16 m_nRarity:4; // Item rarity (0-14) #15
uint16 m_dirtybitInUse:1; // In Use #16
protected:
mutable int16 m_iItemSet; // packs it tightly with defindex field
mutable int m_bSOUpdateFrame;
public:
uint8 m_unFlags; // Flags
// + 6 bytes = 42 bytes total (in 32-bit build)
static void FreeAttributeMemory( CEconItem::attribute_t *pAttrib );
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
template < typename TAttribInMemoryType >
/*virtual*/ void ISchemaAttributeTypeBase<TAttribInMemoryType>::LoadByteStreamToEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const std::string& sBytes ) const
{
Assert( pTargetItem );
Assert( pAttrDef );
TAttribInMemoryType typedValue;
ConvertByteStreamToTypedValue( sBytes, &typedValue );
pTargetItem->SetDynamicAttributeValue( pAttrDef, typedValue );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
template < typename TAttribInMemoryType >
/*virtual*/ void ISchemaAttributeTypeBase<TAttribInMemoryType>::ConvertEconAttributeValueToByteStream( const attribute_data_union_t& value, ::std::string *out_psBytes ) const
{
ConvertTypedValueToByteStream( GetTypedValueContentsFromEconAttributeValue( value ), out_psBytes );
}
bool ItemsMatch( CEconItemView *pCurItem, CEconItemView *pNewItem );
class CEconDefaultEquippedDefinitionInstanceClient : public GCSDK::CProtoBufSharedObject< CSOEconDefaultEquippedDefinitionInstanceClient, k_EEconTypeDefaultEquippedDefinitionInstanceClient >
{
public:
const static int k_nTypeID = k_EEconTypeDefaultEquippedDefinitionInstanceClient;
virtual int GetTypeID() const { return k_nTypeID; }
};
void YieldingAddAuditRecord( GCSDK::CSQLAccess *sqlAccess, const CEconItem *pItem, uint32 unOwnerID, EItemAction eAction, uint32 unData, CEconSessionItemAudit* pItemAudit = NULL );
void YieldingAddAuditRecord( GCSDK::CSQLAccess *sqlAccess, uint64 ulItemID, uint32 unOwnerID, EItemAction eAction, uint32 unData, CEconSessionItemAudit* pItemAudit = NULL );
void YieldingAddAttributeChangeAuditRecord( GCSDK::CSQLAccess *sqlAccess, uint64 ulItemID, uint32 unOwnerID, uint16 unAttributeDefIndex, uint32 uiOriginalValue, EItemAction eAction, uint32 unData );
bool YieldingAddItemToDatabase( CEconItem *pItem, const CSteamID & steamID, EItemAction eAction, uint32 unData, CEconSessionItemAudit* pItemAudit = NULL );
template < typename TAttribInMemoryType >
void ISchemaAttributeTypeBase<TAttribInMemoryType>::LoadEconAttributeValue( CEconItem *pTargetItem, const CEconItemAttributeDefinition *pAttrDef, const union attribute_data_union_t& value ) const
{
pTargetItem->SetDynamicAttributeValue( pAttrDef, GetTypedValueContentsFromEconAttributeValue( value ) );
}
#endif // ECONITEM_H

View File

@@ -0,0 +1,469 @@
//====== Copyright (c), Valve Corporation, All rights reserved. =======
//
// Purpose: Holds constants for the econ item system
//
//=============================================================================
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *g_szQualityStrings[] =
{
"normal",
"genuine",
"vintage",
"unusual",
"unique",
"community",
"developer",
"selfmade",
"customized",
"strange",
"completed",
"haunted",
"tournament",
"favored"
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityStrings ) == AE_MAX_TYPES );
const char *EconQuality_GetQualityString( EEconItemQuality eQuality )
{
// This is a runtime check and not an assert because we could theoretically bounce the GC with new
// qualities while the client is running.
if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
return g_szQualityStrings[ eQuality ];
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *g_szQualityColorStrings[] =
{
"QualityColorNormal",
"QualityColorGenuine",
"QualityColorVintage",
"QualityColorUnusual",
"QualityColorUnique",
"QualityColorCommunity",
"QualityColorDeveloper",
"QualityColorSelfMade",
"QualityColorSelfMadeCustomized",
"QualityColorStrange",
"QualityColorCompleted",
"QualityColorHaunted", // AE_HAUNTED, // same as AE_UNUSUAL
"QualityColorTournament",
"QualityColorFavored",
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityColorStrings ) == AE_MAX_TYPES );
const char *EconQuality_GetColorString( EEconItemQuality eQuality )
{
if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
return g_szQualityColorStrings[ eQuality ];
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *g_szQualityLocalizationStrings[] =
{
"#normal",
"#genuine",
"#vintage",
"#unusual",
"#unique",
"#community",
"#developer",
"#selfmade",
"#customized",
"#strange",
"#completed",
"#haunted",
"#tournament",
"#favored"
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szQualityLocalizationStrings ) == AE_MAX_TYPES );
const char *EconQuality_GetLocalizationString( EEconItemQuality eQuality )
{
if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
return g_szQualityLocalizationStrings[ eQuality ];
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Sort order for rarities
//-----------------------------------------------------------------------------
int g_nRarityScores[] =
{
11, // AE_NORMAL = 0,
9, // AE_GENUINE = 1,
5, // AE_VINTAGE
7, // AE_UNUSUAL,
0, // AE_UNIQUE,
2, // AE_COMMUNITY,
3, // AE_DEVELOPER,
-1, // AE_SELFMADE,
4, // AE_CUSTOMIZED,
10, // AE_STRANGE,
12, // AE_COMPLETED,
1, // AE_HAUNTED, // same as AE_UNIQUE
13, // AE_TOURNAMENT,
14, // AE_FAVORED
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_nRarityScores ) == AE_MAX_TYPES );
int EconQuality_GetRarityScore( EEconItemQuality eQuality )
{
if ( eQuality >= 0 && eQuality < AE_MAX_TYPES )
return g_nRarityScores[ eQuality ];
return 0;
}
int EconRarity_CombinedItemAndPaintRarity( int nItemDefRarity, int nPaintRarity )
{
return clamp( ( nItemDefRarity + nPaintRarity ) - 1, 0, ( nPaintRarity == 7 ) ? 7 : 6 );
}
int EconWear_ToIntCategory( float flWear )
{
if ( flWear < 0.07f )
{
return 0;
}
else if ( flWear < 0.15f )
{
return 1;
}
else if ( flWear < 0.38f )
{
return 2;
}
else if ( flWear < 0.45f )
{
return 3;
}
else
{
return 4;
}
}
float EconWear_FromIntCategory( int nWearCategory )
{
if ( nWearCategory <= 0 )
return 0.05f;
else if ( nWearCategory == 1 )
return 0.14f;
else if ( nWearCategory == 2 )
return 0.37f;
else if ( nWearCategory == 3 )
return 0.44f;
else
return 0.5f;
}
int EconMinutes_ToRoundMinHrsCategory( float flMinutes )
{
int32 iMinutes = int32( flMinutes );
if ( iMinutes <= 120 )
return iMinutes;
iMinutes /= 60;
iMinutes *= 60;
++ iMinutes; // this way we round up all minutes above 2 hours to a whole number of hours + 1 minute
return iMinutes;
}
float EconMinutes_FromRoundMinHrsCategory( int nRoundMinHrsCategory )
{
return nRoundMinHrsCategory;
}
int EconTintID_ToRoundCategory( uint32 unTintID )
{
return unTintID & 0xFF;
}
uint32 EconTintID_FromRoundCategory( int nRoundCategory )
{
return nRoundCategory;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CSchemaColorDefHandle g_AttribColorDefs[] =
{
CSchemaColorDefHandle( "desc_level" ), // ATTRIB_COL_LEVEL
CSchemaColorDefHandle( "desc_attrib_neutral" ), // ATTRIB_COL_NEUTRAL
CSchemaColorDefHandle( "desc_attrib_positive" ), // ATTRIB_COL_POSITIVE
CSchemaColorDefHandle( "desc_attrib_negative" ), // ATTRIB_COL_NEGATIVE
CSchemaColorDefHandle( "desc_itemset_name" ), // ATTRIB_COL_ITEMSET_NAME
CSchemaColorDefHandle( "desc_itemset_equipped" ), // ATTRIB_COL_ITEMSET_EQUIPPED
CSchemaColorDefHandle( "desc_itemset_missing" ), // ATTRIB_COL_ITEMSET_MISSING
CSchemaColorDefHandle( "desc_bundle" ), // ATTRIB_COL_BUNDLE_ITEM
CSchemaColorDefHandle( "desc_limited_use" ), // ATTRIB_COL_LIMITED_USE
CSchemaColorDefHandle( "desc_flags" ), // ATTRIB_COL_ITEM_FLAGS
CSchemaColorDefHandle( "desc_default" ), // ATTRIB_COL_RARITY_DEFAULT
CSchemaColorDefHandle( "desc_common" ), // ATTRIB_COL_RARITY_COMMON
CSchemaColorDefHandle( "desc_uncommon" ), // ATTRIB_COL_RARITY_UNCOMMON
CSchemaColorDefHandle( "desc_rare" ), // ATTRIB_COL_RARITY_RARE
CSchemaColorDefHandle( "desc_mythical" ), // ATTRIB_COL_RARITY_MYTHICAL
CSchemaColorDefHandle( "desc_legendary" ), // ATTRIB_COL_RARITY_LEGENDARY
CSchemaColorDefHandle( "desc_ancient" ), // ATTRIB_COL_RARITY_ANCIENT
CSchemaColorDefHandle( "desc_immortal" ), // ATTRIB_COL_RARITY_IMMORTAL
CSchemaColorDefHandle( "desc_arcana" ), // ATTRIB_COL_RARITY_ARCANA
CSchemaColorDefHandle( "desc_strange" ), // ATTRIB_COL_STRANGE
CSchemaColorDefHandle( "desc_unusual" ), // ATTRIB_COL_UNUSUAL
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_AttribColorDefs ) == NUM_ATTRIB_COLORS );
attrib_colors_t GetAttribColorIndexForName( const char* pszName )
{
for ( int i=0; i<NUM_ATTRIB_COLORS; ++i )
{
if ( !Q_strcmp( g_AttribColorDefs[i].GetName(), pszName ) )
return (attrib_colors_t) i;
}
return (attrib_colors_t) 0;
}
const char *GetColorNameForAttribColor( attrib_colors_t unAttribColor )
{
Assert( unAttribColor >= 0 );
Assert( unAttribColor < NUM_ATTRIB_COLORS );
return g_AttribColorDefs[unAttribColor]
? g_AttribColorDefs[unAttribColor]->GetColorName()
: "ItemAttribNeutral";
}
const char *GetHexColorForAttribColor( attrib_colors_t unAttribColor )
{
Assert( unAttribColor >= 0 );
Assert( unAttribColor < NUM_ATTRIB_COLORS );
return g_AttribColorDefs[unAttribColor]
? g_AttribColorDefs[unAttribColor]->GetHexColor()
: "#ebe2ca";
}
entityquality_t GetItemQualityFromString( const char *sQuality )
{
for ( int i = 0; i < AE_MAX_TYPES; i++ )
{
if ( !Q_strnicmp( sQuality, g_szQualityStrings[i], 16 ) )
return (entityquality_t)i;
}
return AE_NORMAL;
}
const char *g_szRecipeCategoryStrings[] =
{
"crafting", // RECIPE_CATEGORY_CRAFTINGITEMS = 0,
"commonitem", // RECIPE_CATEGORY_COMMONITEMS,
"rareitem", // RECIPE_CATEGORY_RAREITEMS,
"special", // RECIPE_CATEGORY_SPECIAL,
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_szRecipeCategoryStrings ) == NUM_RECIPE_CATEGORIES );
//-----------------------------------------------------------------------------
// Item acquisition.
//-----------------------------------------------------------------------------
// Strings shown to the local player in the pickup dialog
const char *g_pszItemPickupMethodStrings[] =
{
"#NewItemMethod_Dropped", // UNACK_ITEM_DROPPED = 1,
"#NewItemMethod_Crafted", // UNACK_ITEM_CRAFTED,
"#NewItemMethod_Traded", // UNACK_ITEM_TRADED,
"#NewItemMethod_Purchased", // UNACK_ITEM_PURCHASED,
"#NewItemMethod_FoundInCrate", // UNACK_ITEM_FOUND_IN_CRATE,
"#NewItemMethod_Gifted", // UNACK_ITEM_GIFTED,
"#NewItemMethod_Support", // UNACK_ITEM_SUPPORT,
"#NewItemMethod_Promotion", // UNACK_ITEM_PROMOTION,
"#NewItemMethod_Earned", // UNACK_ITEM_EARNED,
"#NewItemMethod_Refunded", // UNACK_ITEM_REFUNDED,
"#NewItemMethod_GiftWrapped", // UNACK_ITEM_GIFT_WRAPPED,
"#NewItemMethod_Foreign", // UNACK_ITEM_FOREIGN,
"#NewItemMethod_CollectionReward", // UNACK_ITEM_COLLECTION_REWARD
"#NewItemMethod_PreviewItem", // UNACK_ITEM_PREVIEW_ITEM
"#NewItemMethod_PreviewItemPurchased", // UNACK_ITEM_PREVIEW_ITEM_PURCHASED
"#NewItemMethod_PeriodicScoreReward",// UNACK_ITEM_PERIODIC_SCORE_REWARD
"#NewItemMethod_Recycling", // UNACK_ITEM_RECYCLING
"#NewItemMethod_TournamentDrop", // UNACK_ITEM_TOURNAMENT_DROP
"#NewItemMethod_QuestReward", // UNACK_ITEM_QUEST_REWARD
"#NewItemMethod_LevelUpReward", // UNACK_ITEM_LEVEL_UP_REWARD
#ifdef ENABLE_STORE_RENTAL_BACKEND
"#NewItemMethod_RentalPurchase", // UNACK_ITEM_RENTAL_PURCHASE
#endif
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszItemPickupMethodStrings ) == UNACK_NUM_METHODS );
const char *g_pszItemPickupMethodStringsUnloc[] =
{
"dropped", // UNACK_ITEM_DROPPED = 1,
"crafted", // UNACK_ITEM_CRAFTED,
"traded", // UNACK_ITEM_TRADED,
"purchased", // UNACK_ITEM_PURCHASED,
"found_in_crate", // UNACK_ITEM_FOUND_IN_CRATE,
"gifted", // UNACK_ITEM_GIFTED,
"support", // UNACK_ITEM_SUPPORT,
"promotion", // UNACK_ITEM_PROMOTION,
"earned", // UNACK_ITEM_EARNED,
"refunded", // UNACK_ITEM_REFUNDED,
"gift_wrapped", // UNACK_ITEM_GIFT_WRAPPED
"foreign", // UNACK_ITEM_FOREIGN
"collection_reward",// UNACK_ITEM_COLLECTION_REWARD
"preview_item", // UNACK_ITEM_PREVIEW_ITEM
"preview_item_purchased", // UNACK_ITEM_PREVIEW_ITEM_PURCHASED
"periodic_score_reward", // UNACK_ITEM_PERIODIC_SCORE_REWARD
"recycling", // UNACK_ITEM_RECYCLING
"tournament_drop", // UNACK_ITEM_TOURNAMENT_DROP
"quest_reward", // UNACK_ITEM_QUEST_REWARD
"level_up_reward", // UNACK_ITEM_LEVEL_UP_REWARD
#ifdef ENABLE_STORE_RENTAL_BACKEND
"rental_purchase", // UNACK_ITEM_RENTAL_PURCHASE
#endif
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszItemPickupMethodStringsUnloc ) == UNACK_NUM_METHODS );
// Strings shown to other players in the chat dialog
const char *g_pszItemFoundMethodStrings[] =
{
"#Item_Found", // UNACK_ITEM_DROPPED = 1,
"#Item_Crafted", // UNACK_ITEM_CRAFTED,
"#Item_Traded", // UNACK_ITEM_TRADED,
NULL, // UNACK_ITEM_PURCHASED,
"#Item_FoundInCrate", // UNACK_ITEM_FOUND_IN_CRATE,
"#Item_Gifted", // UNACK_ITEM_GIFTED,
NULL, // UNACK_ITEM_SUPPORT,
NULL, // UNACK_ITEM_PROMOTION
"#Item_Earned", // UNACK_ITEM_EARNED
"#Item_Refunded", // UNACK_ITEM_REFUNDED
"#Item_GiftWrapped", // UNACK_ITEM_GIFT_WRAPPED
"#Item_Foreign", // UNACK_ITEM_FOREIGN
"#Item_CollectionReward", // UNACK_ITEM_COLLECTION_REWARD
"#Item_PreviewItem", // UNACK_ITEM_PREVIEW_ITEM
"#Item_PreviewItemPurchased",// UNACK_ITEM_PREVIEW_ITEM_PURCHASED
"#Item_PeriodicScoreReward",// UNACK_ITEM_PERIODIC_SCORE_REWARD
"#Item_Recycling", // UNACK_ITEM_RECYCLING
"#Item_TournamentDrop", // UNACK_ITEM_TOURNAMENT_DROP
"#Item_QuestReward", // UNACK_ITEM_QUEST_REWARD
"#Item_LevelUpReward", // UNACK_ITEM_LEVEL_UP_REWARD
#ifdef ENABLE_STORE_RENTAL_BACKEND
NULL, // UNACK_ITEM_RENTAL_PURCHASE
#endif
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct kill_eater_attr_pair_t
{
kill_eater_attr_pair_t( const char *pScoreAttrName, const char *pTypeAttrName, bool bIsUserCustomizable )
: m_attrScore( pScoreAttrName )
, m_attrType( pTypeAttrName )
, m_bIsUserCustomizable( bIsUserCustomizable )
{
//
}
CSchemaAttributeDefHandle m_attrScore;
CSchemaAttributeDefHandle m_attrType;
bool m_bIsUserCustomizable;
};
kill_eater_attr_pair_t g_KillEaterAttr[] =
{
kill_eater_attr_pair_t( "kill eater", "kill eater score type", false ),
// kill_eater_attr_pair_t( "kill eater 2", "kill eater score type 2", false ),
//
// // assumption: all of the user-customizable attributes will follow all of the schema-specified attributes
// kill_eater_attr_pair_t( "kill eater user 1", "kill eater user score type 1", true ),
// kill_eater_attr_pair_t( "kill eater user 2", "kill eater user score type 2", true ),
// kill_eater_attr_pair_t( "kill eater user 3", "kill eater user score type 3", true ),
};
int GetKillEaterAttrPairCount()
{
return ARRAYSIZE( g_KillEaterAttr );
}
const CEconItemAttributeDefinition *GetKillEaterAttrPair_Score( int i )
{
Assert( i >= 0 );
Assert( i < GetKillEaterAttrPairCount() );
return g_KillEaterAttr[i].m_attrScore;
}
const CEconItemAttributeDefinition *GetKillEaterAttrPair_Type( int i )
{
Assert( i >= 0 );
Assert( i < GetKillEaterAttrPairCount() );
return g_KillEaterAttr[i].m_attrType;
}
bool GetKillEaterAttrPair_IsUserCustomizable( int i )
{
Assert( i >= 0 );
Assert( i < GetKillEaterAttrPairCount() );
return g_KillEaterAttr[i].m_bIsUserCustomizable;
}
bool EventRequiresVictim( kill_eater_event_t ke_event )
{
switch( ke_event )
{
case kKillEaterEvent_MVPs:
return false;
default:
break;
}
return true;
}
// -----------------------------------------------------------------------------
// Purpose: convert the paint color float into rgb string. Char buffer should be at least 7 char long
// -----------------------------------------------------------------------------
void GetHexStringFromPaintColor( float flPaint, char *pszRGB )
{
uint32 unValue = (uint32)flPaint;
Color rgb;
rgb.SetRawColor( unValue );
// it appears to be in bgr instead of rgb, so reverse the values when we read them out here
byte b = rgb.r();
byte g = rgb.g();
byte r = rgb.b();
V_binarytohex( &r, 1, pszRGB, 3 );
V_binarytohex( &g, 1, pszRGB + 2, 3 );
V_binarytohex( &b, 1, pszRGB + 4, 3 );
}

View File

@@ -0,0 +1,710 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef ACTUAL_ECON_ITEM_CONSTANTS_H // ECON_ITEM_CONSTANTS_H is used by src/common/econ_item_view.h
#define ACTUAL_ECON_ITEM_CONSTANTS_H
#ifdef _WIN32
#pragma once
#endif
//=============================================================================
// To avoid #include dependency chains, this file should
// contain only constants that do not depend on other
// header files.
// This file is #included in cbase.h to allow schema compiles
// to use these constants to ensure correlation between
// code data structures and database entries
//=============================================================================
typedef uint32 item_price_t; // this is the type that is used to hold currency values for transactions! don't change this without changing the relevant code/databases/etc.
typedef uint8 item_transaction_quantity_t;
class CLocalizationProvider;
//-----------------------------------------------------------------------------
// Econ Item testing
//-----------------------------------------------------------------------------
#define TESTITEM_DEFINITIONS_BEGIN_AT 32000
#define TESTITEM_DEFINITIONS_COUNT 16
//-----------------------------------------------------------------------------
// Type IDs for economy classes. These are part of the client-GC protocol and
// should not change if it can be helped
// NOTE: if possible fill up the gaps in this enum so that cache objects could
// consume less memory!
//-----------------------------------------------------------------------------
enum EEconTypeID
{
k_EEconTypeItem =1,
k_EEconTypePersonaDataPublic =2,
k_EEconTypeGameAccountClient =7,
k_EEconTypeGameAccount =8,
k_EEconTypeEquipInstance =31,
k_EEconTypeDefaultEquippedDefinitionInstance =42,
k_EEconTypeDefaultEquippedDefinitionInstanceClient =43,
k_EEconTypeCoupon =45,
k_EEconTypeQuest =46,
};
//-----------------------------------------------------------------------------
// Actions for the ItemAudit table
//-----------------------------------------------------------------------------
// WARNING!!! Values stored in DB. Do not renumber!
enum EItemAction
{
k_EItemActionInvalid = -1,
k_EItemActionGSCreate = 0,
k_EItemActionUnpurchase = 1,
k_EItemActionDelete = 2,
k_EItemActionAwardAchievement = 3,
k_EItemActionBanned = 4,
k_EItemActionQuantityChanged = 5,
k_EItemActionRestored = 6,
k_EItemActionAwardTime = 7,
k_EItemActionManualCreate = 8,
k_EItemActionDrop = 9,
k_EItemActionPickUp = 10,
k_EItemActionCraftDestroy = 11,
k_EItemActionCraftCreate = 12,
k_EItemActionLimitExceeded = 13,
k_EItemActionPurchase = 14,
k_EItemActionNameChanged_Add = 15,
k_EItemActionUnlockCrate_Add = 16,
k_EItemActionPaintItem_Add = 17,
k_EItemActionAutoGrantItem = 18,
k_EItemActionCrossGameAchievement = 19,
k_EItemActionAddItemToSocket_Add = 20,
k_EItemActionAddSocketToItem_Add = 21,
k_EItemActionRemoveSocketItem_Add = 22,
k_EItemActionCustomizeItemTexture_Add = 23,
k_EItemActionItemTraded_Add = 24,
k_EItemActionUseItem = 25,
k_EItemActionAwardGift_Receiver = 26,
k_EItemActionNameChanged_Remove = 27,
k_EItemActionUnlockCrate_Remove = 28,
k_EItemActionPaintItem_Remove = 29,
k_EItemActionAddItemToSocket_Remove = 30,
k_EItemActionAddSocketToItem_Remove = 31,
k_EItemActionRemoveSocketItem_Remove = 32,
k_EItemActionCustomizeItemTexture_Remove = 33,
k_EItemActionItemTraded_Remove = 34,
k_EItemActionUnpackItemBundle = 35,
k_EItemActionCreateItemFromBundle = 36,
k_EItemActionAwardStorePromotionItem = 37,
k_EItemActionConvertItem = 38,
k_EItemActionEarnedItem = 39,
k_EItemActionAwardGift_Giver = 40,
k_EItemActionRefundedItem = 41,
k_EItemActionAwardThirdPartyPromo = 42,
k_EItemActionRemoveItemName_Remove = 43,
k_EItemActionRemoveItemName_Add = 44,
k_EItemActionRemoveItemPaint_Remove = 45,
k_EItemActionRemoveItemPaint_Add = 46,
k_EItemActionHalloweenDrop = 47,
k_EItemActionSteamWorkshopContributor = 48,
k_EItemActionSupportDelete = 50,
k_EItemActionSupportCreatedByUndo = 51,
k_EItemActionSupportDeletedByUndo = 52,
k_EItemActionSupportQuantityChangedByUndo = 53,
k_EItemActionSupportRename_Add = 54,
k_EItemActionSupportRename_Remove = 55,
k_EItemActionSupportDescribe_Add = 56,
k_EItemActionSupportDescribe_Remove = 57,
k_EItemActionPeriodicScoreReward_Add = 58,
k_EItemActionPeriodicScoreReward_Remove = 59,
k_EItemActionStrangePartApply_Add = 60,
k_EItemActionStrangePartApply_Remove = 61,
k_EItemActionPennantUpgradeApply_Add = 62,
k_EItemActionPennantUpgradeApply_Remove = 63,
k_EItemActionPaintKitItem_Add = 64,
k_EItemActionPaintKitItem_Remove = 65,
k_EItemActionUpgradeChallengeCoin_Add = 66,
k_EItemActionUpgradeChallengeCoin_Remove = 67,
k_EItemActionStickerApply_Add = 68,
k_EItemActionStickerApply_Remove = 69,
k_EItemActionStickerRemove_Add = 70,
k_EItemActionStickerRemove_Remove = 71,
k_EItemActionGrantQuestReward_Add = 72,
k_EItemActionGrantQuestReward_Remove = 73,
k_EItemActionApplyQuestProgress_Add = 74,
k_EItemActionApplyQuestProgress_Remove = 75,
k_EItemActionPurchaseUnlockCrate_Add = 76,
k_EItemActionPurchaseUnlockCrate_Remove = 77,
k_EItemActionSwapStatTrak_Add = 78,
k_EItemActionSwapStatTrak_Remove = 79,
k_EItemActionPurchaseConsumedAsNonItem = 80,
k_EItemActionDev_ClientLootListRoll = 90,
k_EItemActionGiftWrap_Add = 100,
k_EItemActionGiftWrap_Remove = 101,
k_EItemActionGiftDelivery_Add = 102,
k_EItemActionGiftDelivery_Remove = 103,
k_EItemActionGiftUnwrap_Add = 104,
k_EItemActionGiftUnwrap_Remove = 105,
k_EItemActionPackageItem = 106,
k_EItemActionPackageItem_Revoked = 107,
k_EItemActionHandleMapToken = 108,
k_EItemActionCafeOrSchoolItem_Remove = 109,
k_EItemActionVACBanned_Remove = 110,
k_EItemActionUpgradeThirdPartyPromo = 111,
k_EItemActionExpired = 112,
k_EItemActionTradeRollback_Add = 113,
k_EItemActionTradeRollback_Remove = 114,
k_EItemActionCDKeyGrant = 115,
k_EItemActionCDKeyRevoke = 116,
k_EItemActionWeddingRing_Add = 117,
k_EItemActionWeddingRing_Remove = 118,
k_EItemActionWeddingRing_AddPartner = 119,
k_EItemActionEconSetUnowned = 120,
k_EItemActionEconSetOwned = 121,
k_EItemActionRemoveItemCraftIndex_Remove = 150,
k_EItemActionRemoveItemCraftIndex_Add = 151,
k_EItemActionRemoveItemMakersMark_Remove = 152, // early versions of this will be in the database as 150
k_EItemActionRemoveItemMakersMark_Add = 153, // early versions of this will be in the database as 151 because I am a terrible person
k_EItemActionCollectItem_CollectedItem = 154,
k_EItemActionCollectItem_UpdateCollection = 155,
k_EItemActionCollectItem_RemoveCollection = 156,
k_EItemActionCollectItem_RedeemCollectionReward = 157,
k_EItemActionPreviewItem_BeginPreviewPeriod = 158,
k_EItemActionPreviewItem_EndPreviewPeriodExpired = 159,
k_EItemActionPreviewItem_EndPreviewPeriodItemBought = 160,
k_EItemActionRecycling = 161,
k_EItemActionAwardXP = 162,
k_EItemActionTournamentDrop = 163,
k_EItemDiretideReward = 164,
k_EItemDiretideEggAddOnModify = 165,
k_EItemDiretideEssenceRemove = 166,
k_EItemDiretideEggRemoveOnModify = 167,
k_EItemActionUnpackItems = 168,
k_EItemActionUnlockStyle = 169,
k_EItemActionUnlockStyle_Remove = 170,
k_EItemActionTutorialDrop = 171,
k_EItemActionAutographAdd = 172,
k_EItemActionAutographRemove = 173,
k_EItemActionApplyIntermediateStickerWear = 174,
k_EItemActionTemplateItemGrant = 175,
k_EItemActionCoinCampaignProgress = 176,
k_EItemActionMarket_Add = 177,
k_EItemActionMarket_Remove = 178,
// Let's be consistent with the underscores please.
// k_EItemActionYourNewAction, not k_EItemAction_YourNewAction
// Yes, it matters. See PchLocalizedNameFromEItemAction for why.
};
extern const char *PchNameFromEItemAction( EItemAction eAction );
extern const char *PchNameFromEItemActionUnsafe( EItemAction eAction );
extern bool BIsActionCreative( EItemAction );
extern bool BIsActionDestructive( EItemAction );
enum EItemActionMissingBehavior { kEItemAction_FriendlyNameLookup_ReturnNULLIfMissing, kEItemAction_FriendlyNameLookup_ReturnDummyStringIfMissing };
extern const char *PchFriendlyNameFromEItemAction( EItemAction eAction, EItemActionMissingBehavior eMissingBehavior );
extern const char *PchLocalizedNameFromEItemAction( EItemAction eAction, CLocalizationProvider &localizationProvider );
//-----------------------------------------------------------------------------
// Purpose: Used to pass audit actions to asset servers for SetUnowned and
// SetOwned methods.
//-----------------------------------------------------------------------------
enum EEconOwnershipAction
{
k_EEconOwnershipAction_Invalid = 0,
k_EEconOwnershipAction_TradeBase = 100,
k_EEconOwnershipAction_TradeCommit = 101, // precommit and docommit step of a trade. Reference is trade ID
k_EEconOwnershipAction_TradeRollback = 102, // cancelcommit and rollbackcommit step of a trade. Reference is trade ID
};
// old
enum eEconItemFlags_Deprecated
{
kDeprecated_EconItemFlag_AchievementGrantedItem = 1 << 0,
kDeprecated_EconItemFlag_CannotTrade = 1 << 1,
kDeprecated_EconItemFlag_Purchased = 1 << 2,
kDeprecated_EconItemFlag_CannotBeUsedInCrafting = 1 << 3,
kDeprecated_EconItemFlag_Promotion = 1 << 4,
};
//-----------------------------------------------------------------------------
// Flags for CEconItem
//-----------------------------------------------------------------------------
// WARNING!!! Values stored in DB. DO NOT CHANGE EXISTING VALUES. Add values to the end.
enum eEconItemFlags
{
kEconItemFlag_CannotTrade = 1 << 0,
kEconItemFlag_CannotBeUsedInCrafting = 1 << 1,
kEconItemFlag_CanBeTradedByFreeAccounts = 1 << 2,
kEconItemFlag_NonEconomy = 1 << 3, // used for items that are meant to not interact in the economy -- these can't be traded, gift-wrapped, crafted, etc.
#ifdef CLIENT_DLL
#ifdef TF_CLIENT_DLL
kEconItemFlagClient_ForceBlueTeam = 1 << 5,
#endif // TF_CLIENT_DLL
kEconItemFlagClient_StoreItem = 1 << 6,
kEconItemFlagClient_Preview = 1 << 7, // only set on the client; means "this item is being previewed"
#endif // CLIENT_DLL
// combination of the above flags used in code
kEconItemFlags_CheckFlags_CannotTrade = kEconItemFlag_CannotTrade,
kEconItemFlags_CheckFlags_NotUsableInCrafting = kEconItemFlag_CannotBeUsedInCrafting,
kEconItemFlags_CheckFlags_AllGCFlags = kEconItemFlags_CheckFlags_CannotTrade | kEconItemFlags_CheckFlags_NotUsableInCrafting,
};
//-----------------------------------------------------------------------------
// Origin for an item for CEconItem
//-----------------------------------------------------------------------------
// WARNING!!! Values stored in DB. DO NOT CHANGE EXISTING VALUES. Add values to the end.
enum eEconItemOrigin
{
kEconItemOrigin_Invalid = -1, // should never be stored in the DB! used to indicate "invalid" for in-memory objects only
kEconItemOrigin_Drop = 0,
kEconItemOrigin_Achievement,
kEconItemOrigin_Purchased,
kEconItemOrigin_Traded,
kEconItemOrigin_Crafted,
kEconItemOrigin_StorePromotion,
kEconItemOrigin_Gifted,
kEconItemOrigin_SupportGranted,
kEconItemOrigin_FoundInCrate,
kEconItemOrigin_Earned,
kEconItemOrigin_ThirdPartyPromotion,
kEconItemOrigin_GiftWrapped,
kEconItemOrigin_HalloweenDrop,
kEconItemOrigin_PackageItem,
kEconItemOrigin_Foreign,
kEconItemOrigin_CDKey,
kEconItemOrigin_CollectionReward,
kEconItemOrigin_PreviewItem,
kEconItemOrigin_SteamWorkshopContribution,
kEconItemOrigin_PeriodicScoreReward,
kEconItemOrigin_Recycling,
kEconItemOrigin_TournamentDrop,
kEconItemOrigin_StockItem,
KEconItemOrigin_QuestReward,
KEconItemOrigin_LevelUpReward,
kEconItemOrigin_Max,
};
extern const char *PchNameFromeEconItemOrigin( eEconItemOrigin eOrigin );
// The Steam backend representation of a unique item index
typedef uint64 itemid_t;
typedef uint16 item_definition_index_t;
typedef uint16 attrib_definition_index_t;
typedef uint32 attrib_value_t;
// Misc typedefs for clarity.
typedef uint32 equip_region_mask_t;
typedef uint8 style_index_t;
const uint64 INVALID_ITEM_ID = (itemid_t)-1;
const item_definition_index_t INVALID_ITEM_DEF_INDEX = ((item_definition_index_t)-1);
const attrib_definition_index_t INVALID_ATTRIB_DEF_INDEX= ((attrib_definition_index_t)-1);
//-----------------------------------------------------------------------------
// Standard/default backpack size
#define DEFAULT_NUM_BACKPACK_SLOTS_PER_PAGE 100
#define DEFAULT_NUM_BACKPACK_SLOTS 1000
#define DEFAULT_NUM_BACKPACK_SLOTS_FREE_TRIAL_ACCOUNT 100
#define MAX_NUM_BACKPACK_SLOTS 2000
// Current item level range
#define MIN_ITEM_LEVEL 0
#define MAX_ITEM_LEVEL 100
// Maximum number of attributes allowed on a single item
#define MAX_ATTRIBUTES_PER_ITEM 32
// The maximum length of a single attribute's description
// divide by locchar_t, so we can ensure 192 bytes, whether that's 128 wchars on client or 256 utf-8 bytes on gc
#define MAX_ATTRIBUTE_DESCRIPTION_LENGTH ( 256 / sizeof( locchar_t ) )
// The maximum length of an item's name
#define MAX_ITEM_NAME_LENGTH 128
#define MAX_ITEM_DESC_LENGTH 256
#define MAX_ITEM_LONG_DESC_LENGTH 2048
// The maximum length of an item description. (Extra +1 line is for the base item type line)
// #define MAX_ITEM_DESCRIPTION_LENGTH ((MAX_ATTRIBUTES_PER_ITEM+1) * MAX_ATTRIBUTE_DESCRIPTION_LENGTH)
// For custom user-naming of econ items.
#define MAX_ITEM_CUSTOM_NAME_LENGTH 40
#define MAX_ITEM_CUSTOM_NAME_DATABASE_SIZE ((4 * MAX_ITEM_CUSTOM_NAME_LENGTH) + 1) // Ensures we can store MAX_ITEM_CUSTOM_NAME_LENGTH
// characters worth of obscure unicode characters in UTF8
#define MAX_ITEM_CUSTOM_DESC_LENGTH 80
#define MAX_ITEM_CUSTOM_DESC_DATABASE_SIZE ((4 * MAX_ITEM_CUSTOM_DESC_LENGTH) + 1)
// max length in the DB for claim codes
#define MAX_CLAIM_CODE_LENGTH 128
// The number of items to work on in a job before checking if a yield is necessary
#define MAX_ITEMS_BEFORE_YIELD 50
// TF team-color paints (moved from econ_item_view.h)
#define RGB_INT_RED 12073019
#define RGB_INT_BLUE 5801378
// Custom textures
const int k_nCustomImageSize = 256;
const int k_nMaxCustomImageFileSize = k_nCustomImageSize*k_nCustomImageSize*4 + 4*1024; // Is this about right?
//-----------------------------------------------------------------------------
// Purpose: Quality types of items
//-----------------------------------------------------------------------------
typedef int32 entityquality_t;
enum EEconItemQuality
{
AE_UNDEFINED = -1,
AE_NORMAL = 0,
AE_GENUINE = 1,
AE_VINTAGE,
AE_UNUSUAL,
AE_UNIQUE,
AE_COMMUNITY,
AE_DEVELOPER,
AE_SELFMADE,
AE_CUSTOMIZED,
AE_STRANGE,
AE_COMPLETED,
AE_HAUNTED,
AE_TOURNAMENT,
AE_FAVORED,
AE_MAX_TYPES,
};
//-----------------------------------------------------------------------------
// Purpose: colors used in the display of attributes
//-----------------------------------------------------------------------------
enum attrib_colors_t
{
ATTRIB_COL_LEVEL = 0,
ATTRIB_COL_NEUTRAL,
ATTRIB_COL_POSITIVE,
ATTRIB_COL_NEGATIVE,
ATTRIB_COL_ITEMSET_NAME,
ATTRIB_COL_ITEMSET_EQUIPPED,
ATTRIB_COL_ITEMSET_MISSING,
ATTRIB_COL_BUNDLE_ITEM,
ATTRIB_COL_LIMITED_USE,
ATTRIB_COL_ITEM_FLAGS,
ATTRIB_COL_RARITY_DEFAULT,
ATTRIB_COL_RARITY_COMMON,
ATTRIB_COL_RARITY_UNCOMMON,
ATTRIB_COL_RARITY_RARE,
ATTRIB_COL_RARITY_MYTHICAL,
ATTRIB_COL_RARITY_LEGENDARY,
ATTRIB_COL_RARITY_ANCIENT,
ATTRIB_COL_RARITY_IMMORTAL,
ATTRIB_COL_RARITY_ARCANA,
ATTRIB_COL_STRANGE,
ATTRIB_COL_UNUSUAL,
NUM_ATTRIB_COLORS,
};
#define AE_USE_SCRIPT_VALUE 9999 // Can't be -1, due to unsigned ints used on the backend
const char *EconQuality_GetQualityString( EEconItemQuality eQuality );
const char *EconQuality_GetColorString( EEconItemQuality eQuality );
const char *EconQuality_GetLocalizationString( EEconItemQuality eQuality );
// Sort order for rarities
int EconQuality_GetRarityScore( EEconItemQuality eQuality );
int EconRarity_CombinedItemAndPaintRarity( int nItemDefRarity, int nPaintRarity );
int EconWear_ToIntCategory( float flWear );
float EconWear_FromIntCategory( int nWearCategory );
int EconMinutes_ToRoundMinHrsCategory( float flMinutes );
float EconMinutes_FromRoundMinHrsCategory( int nRoundMinHrsCategory );
int EconTintID_ToRoundCategory( uint32 unTintID );
uint32 EconTintID_FromRoundCategory( int nRoundCategory );
extern attrib_colors_t GetAttribColorIndexForName( const char* pszName );
extern const char *GetColorNameForAttribColor( attrib_colors_t unAttribColor );
extern const char *GetHexColorForAttribColor( attrib_colors_t unAttribColor );
// Utility function that'll get you an item quality from a string
entityquality_t GetItemQualityFromString( const char *sQuality );
enum recipecategories_t
{
RECIPE_CATEGORY_CRAFTINGITEMS = 0,
RECIPE_CATEGORY_COMMONITEMS,
RECIPE_CATEGORY_RAREITEMS,
RECIPE_CATEGORY_SPECIAL,
NUM_RECIPE_CATEGORIES
};
extern const char *g_szRecipeCategoryStrings[NUM_RECIPE_CATEGORIES];
//-----------------------------------------------------------------------------
// Kill eater support.
//-----------------------------------------------------------------------------
enum kill_eater_event_t
{
kKillEaterEvent_PlayerKill = 0,
kKillEaterEvent_MVPs,
// kKillEaterEvent_KillAssists, // not yet implemented
// kKillEaterEvent_Wins,
// kKillEaterEvent_Treants_Created,
// kKillEaterEvent_Omnislash_Jumps,
// kKillEaterEvent_Blade_Fury_Damage,
// kKillEaterEvent_Blade_Dance_Crits,
// kKillEaterEvent_Wards_Placed,
// kKillEaterEvent_Killing_Sprees, // not yet implemented
// kKillEaterEvent_Trees_Created,
// kKillEaterEvent_Carries_Killed, // not yet implemented
// kKillEaterEvent_First_Blood,
// kKillEaterEvent_Godlike,
// kKillEaterEvent_Gold_Earned,
// kKillEaterEvent_Gold_Spent,
// kKillEaterEvent_Towers_Destroyed,
// kKillEaterEventType_Bounty_TrackedKills,
// kKillEaterEventType_Bounty_TrackedInvisKills,
// kKillEaterEventType_Bounty_InvisJinadaHits,
// kKillEaterEventType_Bounty_TrackGold,
// kKillEaterEventType_Tide_GoodRavages,
// kKillEaterEventType_Windrunner_DoubleShackles,
// kKillEaterEventType_Windrunner_GoodPowershots,
// kKillEaterEventType_Invoker_SunstrikeKills,
// kKillEaterEventType_Couriers_Purchased,
// kKillEaterEventType_Wards_Purchased,
// kKillEaterEventType_Tide_EnemiesGushed,
// kKillEaterEventType_Axe_Culls,
// kKillEaterEventType_Axe_BattleHungerKills,
// kKillEaterEventType_Axe_LowHealthKills,
// kKillEaterEventType_Axe_CalledDamageDone,
// kKillEaterEventType_Axe_CalledDamageTaken,
// kKillEaterEventType_Invoker_TornadoKills,
// kKillEaterEventType_Games_Viewed,
// kKillEaterEventType_Sven_DoubleStuns,
// kKillEaterEventType_Sven_WarcryAssists,
// kKillEaterEventType_Sven_CleaveDoubleKills,
// kKillEaterEventType_Sven_TeleportInterrupts,
// kKillEaterEventType_Faceless_MultiChrono,
// kKillEaterEventType_Faceless_ChronoKills,
// kKillEaterEventType_Ursa_MultiShocks,
// kKillEaterEventType_RoshanKills,
// NEW ENTRIES MUST BE ADDED AT THE BOTTOM
};
// Make sure to update this when you add a new type.
bool EventRequiresVictim( kill_eater_event_t ke_event );
// Ugh -- these are shared between the GC and the client. Maybe #define is slightly better than
// magic string literals?
#define KILL_EATER_RANK_LEVEL_BLOCK_NAME "KillEaterRank"
int GetKillEaterAttrPairCount();
const class CEconItemAttributeDefinition *GetKillEaterAttrPair_Score( int i );
const class CEconItemAttributeDefinition *GetKillEaterAttrPair_Type( int i );
bool GetKillEaterAttrPair_IsUserCustomizable( int i );
//===============================================================================================================
// POSITION HANDLING
//===============================================================================================================
// TF Inventory Position cracking
// REALLY OLD FORMAT (??):
// We store a bag index in the highbits of the inventory position.
// The lowbit stores the position of the item within the bag.
//
// LESS OLD FORMAT (up through July, 2011):
// If Bit 31 is 0:
// Bits 1-16 are the backpack position.
// Bits 17-26 are a bool for whether the item is equipped in the matching class.
// Otherwise, if Bit 31 is 1:
// Item hasn't been acknowledged by the player yet.
// Bits 1-16 are the method by the player found the item (see unacknowledged_item_inventory_positions_t)
// Bit 32 is 1, to note the new format.
//
// CURRENT FORMAT:
// If Bit 31 is 0:
// Bits 1-16 are the backpack position.
// Otherwise, if Bit 31 is 1:
// Item hasn't been acknowledged by the player yet.
// Bits 1-16 are the method by the player found the item (see unacknowledged_item_inventory_positions_t)
// Equipped state is stored elsewhere.
// This is the only format that should exist on clients.
enum unacknowledged_item_inventory_positions_t
{
UNACK_ITEM_DROPPED = 1,
UNACK_ITEM_CRAFTED,
UNACK_ITEM_TRADED,
UNACK_ITEM_PURCHASED,
UNACK_ITEM_FOUND_IN_CRATE,
UNACK_ITEM_GIFTED,
UNACK_ITEM_SUPPORT,
UNACK_ITEM_PROMOTION,
UNACK_ITEM_EARNED,
UNACK_ITEM_REFUNDED,
UNACK_ITEM_GIFT_WRAPPED,
UNACK_ITEM_FOREIGN,
UNACK_ITEM_COLLECTION_REWARD,
UNACK_ITEM_PREVIEW_ITEM,
UNACK_ITEM_PREVIEW_ITEM_PURCHASED,
UNACK_ITEM_PERIODIC_SCORE_REWARD,
UNACK_ITEM_RECYCLING,
UNACK_ITEM_TOURNAMENT_DROP,
UNACK_ITEM_QUEST_REWARD,
UNACK_ITEM_LEVEL_UP_REWARD,
#ifdef ENABLE_STORE_RENTAL_BACKEND
UNACK_ITEM_RENTAL_PURCHASE,
#endif
UNACK_NUM_METHODS,
};
extern const char *g_pszItemPickupMethodStrings[UNACK_NUM_METHODS];
extern const char *g_pszItemPickupMethodStringsUnloc[UNACK_NUM_METHODS];
extern const char *g_pszItemFoundMethodStrings[UNACK_NUM_METHODS];
enum
{
kGCItemSort_NoSort = 0, // this won't do anything, but can be used as a safe "header" value
kGCItemSort_SortByName = 1,
kGCItemSort_SortByDefIndex = 2,
kGCItemSort_SortByRarity = 3,
kGCItemSort_SortByType = 4,
kGCItemSort_SortByQuality = 5,
kGCItemSort_GameSpecificBase = 100,
};
// FIXME: these should be moved... somewhere; where?
enum
{
kTFGCItemSort_SortByClass = kGCItemSort_GameSpecificBase + 1,
kTFGCItemSort_SortBySlot = kGCItemSort_GameSpecificBase + 2,
kDOTAGCItemSort_SortByHero = kGCItemSort_GameSpecificBase + 3,
};
enum
{
kBackendPosition_Unacked = 1 << 30,
kBackendPosition_Reserved = 1 << 31,
kBackendPositionMask_Position = 0x0000ffff,
kBackendPositionMask_FormatFlags = (kBackendPosition_Unacked | kBackendPosition_Reserved),
};
inline void SetBackpackPosition( uint32 *pPosition, uint32 iPackPosition )
{
(*pPosition) = iPackPosition;
// Remove the unack'd flag
(*pPosition) &= ~kBackendPosition_Unacked;
}
inline bool IsUnacknowledged( uint32 iBackendPosition )
{
// For backwards compatibility, we consider position 0 as unacknowledged too
return ( iBackendPosition == 0 || (iBackendPosition & kBackendPosition_Unacked) != 0 );
}
inline int ExtractBackpackPositionFromBackend( uint32 iBackendPosition )
{
if ( IsUnacknowledged( iBackendPosition) )
return 0;
return iBackendPosition & kBackendPositionMask_Position;
}
inline unacknowledged_item_inventory_positions_t GetUnacknowledgedReason( uint32 iBackendPosition )
{
return (unacknowledged_item_inventory_positions_t)( iBackendPosition &= ~kBackendPositionMask_FormatFlags );
}
inline uint32 GetUnacknowledgedPositionFor( unacknowledged_item_inventory_positions_t iMethod )
{
return ( iMethod | kBackendPosition_Unacked | kBackendPosition_Reserved );
}
//-----------------------------------------------------------------------------
// Item Preview event IDs for logging.
//-----------------------------------------------------------------------------
enum EEconItemPreviewEventIDs
{
k_EEconItemPreview_Start =1,
k_EEconItemPreview_Expired =2,
k_EEconItemPreview_ItemPurchased =3,
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
enum EHoliday
{
kHoliday_None = 0, // must stay at zero for backwards compatability
kHoliday_Halloween,
kHoliday_Christmas,
kHoliday_FullMoon,
kHoliday_HalloweenOrFullMoon,
kHoliday_Easter,
kHolidayCount,
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
enum ECartItemType
{
kCartItem_Purchase, // a normal lifetime purchase (needs to stay as entry 0!)
kCartItem_TryOutUpgrade, // an upgrade from "try-it-out"
kCartItem_Rental_1Day,
kCartItem_Rental_3Day,
kCartItem_Rental_7Day,
};
void GetHexStringFromPaintColor( float flPaint, char *pszRGB );
inline bool IsRentalCartItemType( ECartItemType eCartType )
{
return eCartType == kCartItem_Rental_1Day
|| eCartType == kCartItem_Rental_3Day
|| eCartType == kCartItem_Rental_7Day;
}
#endif // ACTUAL_ECON_ITEM_CONSTANTS_H

View File

@@ -0,0 +1,74 @@
#include "cbase.h"
#include "econ_item_description.h"
#include "econ_item_interface.h"
//#include "econ_holidays.h"
#include "vgui/ILocalize.h"
#include "localization_provider.h"
#if defined( DOTA_DLL ) || defined( DOTA_GC_DLL )
#include "dota_sharedfuncs.h"
#endif
#ifndef EXTERNALTESTS_DLL
#include "econ_item_inventory.h"
#endif
#ifdef PROJECT_TF
#include "tf_duel_summary.h"
#include "econ_contribution.h"
#include "tf_player_info.h"
#endif
#ifdef VPROF_ENABLED
static const char *g_pszEconDescriptionVprofGroup = _T("Econ Description");
#endif
char *(g_pchWearAmountStrings[]) =
{
"#SFUI_InvTooltip_Wear_Amount_0",
"#SFUI_InvTooltip_Wear_Amount_1",
"#SFUI_InvTooltip_Wear_Amount_2",
"#SFUI_InvTooltip_Wear_Amount_3",
"#SFUI_InvTooltip_Wear_Amount_4"
};
char *( g_pchQuestOperationalPoints[] ) =
{
"", // 1-based
"#Quest_OperationalPoints_1",
"#Quest_OperationalPoints_2",
"#Quest_OperationalPoints_3",
};
ConVar cl_show_quest_info( "cl_show_quest_info", "0", FCVAR_DEVELOPMENTONLY );
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
void IEconItemDescription::YieldingFillOutEconItemDescription( IEconItemDescription *out_pDescription, CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem )
{
VPROF_BUDGET( "IEconItemDescription::YieldingFillOutEconItemDescription()", g_pszEconDescriptionVprofGroup );
Assert( out_pDescription );
Assert( pLocalizationProvider );
Assert( pEconItem );
out_pDescription->YieldingCacheDescriptionData( pLocalizationProvider, pEconItem );
out_pDescription->GenerateDescriptionLines( pLocalizationProvider, pEconItem );
}
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
const econ_item_description_line_t *IEconItemDescription::GetFirstLineWithMetaType( uint32 unMetaTypeSearchFlags ) const
{
for ( unsigned int i = 0; i < GetLineCount(); i++ )
{
const econ_item_description_line_t& pLine = GetLine(i);
if ( (pLine.unMetaType & unMetaTypeSearchFlags) == unMetaTypeSearchFlags )
return &pLine;
}
return NULL;
}

View File

@@ -0,0 +1,133 @@
#ifndef ECONITEMDESCRIPTION_H
#define ECONITEMDESCRIPTION_H
#ifdef _WIN32
#pragma once
#endif
#include "localization_provider.h" // needed for locchar_t type
class IEconItemInterface;
namespace GCSDK
{
class CSharedObjectTypeCache;
}
//-----------------------------------------------------------------------------
// Purpose: Generate a description block for an IEconItemInterface. What the
// client does with the description is anyone's guess, but this will
// generate a block of UTF16 lines of text with meta/color data that
// can be used for whatever.
//-----------------------------------------------------------------------------
enum EDescriptionLineMetaFlags
{
kDescLineFlag_Name = 0x0001, // the item name (can be renamed by user)
kDescLineFlag_Type = 0x0002, // the item type (ie., "Level 5 Rocket Launcher")
kDescLineFlag_Desc = 0x0004, // base item description (description from the item definition, level, etc.)
kDescLineFlag_Attribute = 0x0008, // some sort of gameplay-affecting attribute
kDescLineFlag_Misc = 0x0010, // not an attribute, not name/level
kDescLineFlag_Empty = 0x0020, // line with no content that needs to be displayed; meant for spacing
kDescLineFlag_Set = 0x0040, // this line is associated with item sets somehow
kDescLineFlag_LimitedUse = 0x0080, // this is a limited use item
kDescLineFlag_SetName = 0x0100, // this line is the title for an item set
kDescLineFlag_Scorecard = 0x0200,
kDescLineFlag_LootList = 0x0400, // this line belongs to a lootlist block
kDescLineFlag_OwnerOnly = 0x0800, // this line must be only shown for owner of the item
kDescLineFlag_DetailedInfo = 0x1000, // this line is detailed info like mission xp
kDescLineFlag_NameUncustomized = 0x2000, // the item name (not customized)
kDescLineFlagSet_DisplayInAttributeBlock = ~(kDescLineFlag_Name | kDescLineFlag_Type),
};
struct econ_item_description_line_t
{
attrib_colors_t eColor; // desired color type for this line -- will likely be looked up either in VGUI or in the schema
uint32 unMetaType; // type information for this line -- "item name"? "item level"?; etc.; can be game-specific
CUtlConstStringBase<locchar_t> sText; // actual text for this, post-localization
itemid_t un64FauxItemId; // defindex and paint encoded as an itemid.
bool bOwned; // a way to keep track of set/collection item presence
};
class IEconItemDescription
{
public:
// This may yield on the GC and should never yield on the client.
static void YieldingFillOutEconItemDescription( IEconItemDescription *out_pDescription, CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem );
public:
IEconItemDescription() { }
virtual ~IEconItemDescription() { }
uint32 GetLineCount() const { return m_vecDescLines.Count(); }
const econ_item_description_line_t& GetLine( int i ) const { return m_vecDescLines[i]; }
// Finds and returns the first line with *all* of the passed in search flags. Will return NULL if a line
// will all of the flags cannot be found.
const econ_item_description_line_t *GetFirstLineWithMetaType( uint32 unMetaTypeSearchFlags ) const;
private:
// When generating an item description, this is guaranteed to be called once and only once before GenerateDescription()
// is called. Any data that may yield but will be needed somewhere deep inside GenerateDescription() should be determined
// and cached off here.
virtual void YieldingCacheDescriptionData( CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ) { }
// Take the properties off our pEconItem, and anything that we calculated in YieldingCacheDescriptionData() above and
// fill out all of our description lines.
virtual void GenerateDescriptionLines( CLocalizationProvider *pLocalizationProvider, const IEconItemInterface *pEconItem ) = 0;
protected:
CUtlVector<econ_item_description_line_t> m_vecDescLines;
};
#if defined( TF_DLL ) || defined( TF_CLIENT_DLL ) || defined( TF_GC_DLL )
#define PROJECT_TF
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CSteamAccountIDAttributeCollector : public IEconItemAttributeIterator
{
public:
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE
{
if ( pAttrDef->GetDescriptionFormat() == ATTDESCFORM_VALUE_IS_ACCOUNT_ID )
{
m_vecSteamAccountIDs.AddToTail( value );
}
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) OVERRIDE
{
// Intentionally ignore.
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) OVERRIDE
{
// Intentionally ignore.
return true;
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) OVERRIDE
{
// Intentionally ignore.
return true;
}
// Data access.
const CUtlVector<uint32>& GetAccountIDs()
{
return m_vecSteamAccountIDs;
}
private:
CUtlVector<uint32> m_vecSteamAccountIDs;
};
#endif // ECONITEMDESCRIPTION_H

View File

@@ -0,0 +1,377 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: EconItemFactory: Manages rolling for items requested by the game server
//
//=============================================================================
#include "cbase.h"
#include "econ_item_view_helpers.h"
#include "playerdecals_signature.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace GCSDK;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CEconItemFactory::CEconItemFactory( )
: m_ulNextObjID( 0 )
, m_bIsInitialized( false )
{
}
//-----------------------------------------------------------------------------
itemid_t CEconItemFactory::GetNextID()
{
if( !m_bIsInitialized || !GGCBase()->IsGCRunningType( GC_TYPE_MASTER ) )
{
AssertMsg( m_bIsInitialized, "Critical Error: Attempting to get a new item ID without loading in the starting ID first!!!" );
AssertMsg( GGCBase()->IsGCRunningType( GC_TYPE_MASTER ), "Critical Error: Attempting to get an item ID on the non-master GC, this will get out of sync" );
return INVALID_ITEM_ID;
}
return m_ulNextObjID++;
}
//-----------------------------------------------------------------------------
// Purpose: Initializes the item factory and schema. Return false if init failed
//-----------------------------------------------------------------------------
bool CEconItemFactory::BYieldingInit()
{
CUtlVector< CUtlString > vecErrors;
bool bRet = m_schema.BInit( "scripts/items/unencrypted/items_master.txt", "GAME", &vecErrors );
FOR_EACH_VEC( vecErrors, nError )
{
EmitError( SPEW_GC, "%s\n", vecErrors[nError].Get() );
}
static const char *pchMaxIDQuery = "SELECT MAX( ID ) FROM "
"( select Max(ID) AS ID FROM Item UNION SELECT MAX(ID) AS ID FROM ForeignItem ) as tbl";
CSQLAccess sqlAccess;
if( !sqlAccess.BYieldingExecuteSingleResult<uint64, uint64>( NULL, pchMaxIDQuery, k_EGCSQLType_int64, &m_ulNextObjID, NULL ) )
{
EmitError( SPEW_GC, "Failed to read max item ID" );
return false;
}
m_ulNextObjID++; // our next ID is one past the current max ID
m_bIsInitialized = bRet;
return bRet;
}
static const CEconItemQualityDefinition *GetQualityDefinitionForItemCreation( const CItemSelectionCriteria *pOptionalCriteria, const CEconItemDefinition *pItemDef )
{
Assert( pItemDef );
// Do we have a quality specified? If so, is it a valid quality? If not, we fall back to the
// quality specified by the item definition, the schema, etc.
uint8 unQuality = k_unItemQuality_Any;
// Quality specified in generation request via criteria?
if ( pOptionalCriteria && pOptionalCriteria->BQualitySet() )
{
unQuality = pOptionalCriteria->GetQuality();
}
// If not: quality specified in item definition?
if ( unQuality == k_unItemQuality_Any )
{
unQuality = pItemDef->GetQuality();
}
// Final fallback: default quality in schema.
if ( unQuality == k_unItemQuality_Any )
{
unQuality = GetItemSchema()->GetDefaultQuality();
}
AssertMsg( unQuality != k_unItemQuality_Any, "Unable to locate valid quality!" );
return GetItemSchema()->GetQualityDefinition( unQuality );
}
static const CEconItemRarityDefinition *GetRarityDefinitionForItemCreation( const CItemSelectionCriteria *pOptionalCriteria, const CEconItemDefinition *pItemDef )
{
Assert( pItemDef );
// Do we have a quality specified? If so, is it a valid quality? If not, we fall back to the
// quality specified by the item definition, the schema, etc.
uint8 unRarity = k_unItemRarity_Any;
// Quality specified in generation request via criteria?
if ( pOptionalCriteria && pOptionalCriteria->BRaritySet() )
{
unRarity = pOptionalCriteria->GetRarity();
}
// If not: quality specified in item definition?
if ( unRarity == k_unItemRarity_Any )
{
unRarity = pItemDef->GetRarity();
}
// Final fallback: default quality in schema.
if ( unRarity == k_unItemRarity_Any )
{
unRarity = 1;
}
AssertMsg( unRarity != k_unItemRarity_Any, "Unable to locate valid rarity!" );
return GetItemSchema()->GetRarityDefinition( unRarity );
}
//-----------------------------------------------------------------------------
// Purpose: Creates an item matching the incoming item selection criteria
// Input: pItem - Pointer to the item to fill in
// criteria - The criteria that the generated item must match
// Output: True if a matching item could be generated, false otherwise
//-----------------------------------------------------------------------------
CEconItem *CEconItemFactory::CreateRandomItem( const CEconGameAccount *pGameAccount, const CItemSelectionCriteria &criteria )
{
// Find a matching item definition.
const CEconItemDefinition *pItemDef = RollItemDefinition( criteria );
if ( NULL == pItemDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateRandomItem(): Item creation request with no matching definition\n" );
return NULL;
}
const CEconItemQualityDefinition *pQualityDef = GetQualityDefinitionForItemCreation( &criteria, pItemDef );
if ( NULL == pQualityDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateRandomItem(): Item creation request with unknown quality\n" );
return NULL;
}
const CEconItemRarityDefinition *pRarityDef = GetRarityDefinitionForItemCreation( &criteria, pItemDef );
if ( NULL == pRarityDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateRandomItem(): Item creation request with unknown rarity\n" );
return NULL;
}
// At this point we have everything that can fail will already have failed, so we can safely
// create an item and just move properties over to it.
CEconItem *pItem = new CEconItem();
pItem->SetItemID( GetNextID() );
pItem->SetDefinitionIndex( pItemDef->GetDefinitionIndex() );
pItem->SetItemLevel( criteria.BItemLevelSet() ? criteria.GetItemLevel() : pItemDef->RollItemLevel() );
pItem->SetQuality( pQualityDef->GetDBValue() );
pItem->SetRarity( pRarityDef->GetDBValue() );
pItem->SetInventoryToken( criteria.GetInitialInventory() );
pItem->SetQuantity( criteria.GetInitialQuantity() );
// don't set account ID
// Add any custom attributes we need
AddGCGeneratedAttributesToItem( pGameAccount, pItem );
// Set any painkit data specified
const char *pchPaintKit = criteria.GetValueForFirstConditionOfFieldName( "*paintkit" );
if ( pchPaintKit )
{
const char *pchWear = criteria.GetValueForFirstConditionOfFieldName( "*wear" );
item_list_entry_t itemInit;
itemInit.m_nItemDef = pItemDef->GetDefinitionIndex();
itemInit.m_nPaintKit = atoi( pchPaintKit );
itemInit.m_nPaintKitSeed = 0;
itemInit.m_flPaintKitWear = pchWear ? atof( pchWear ) : 0.001;
pItem->InitAttributesDroppedFromListEntry( &itemInit );
}
return pItem;
}
//-----------------------------------------------------------------------------
// Purpose: Creates an item based on a specific item definition index
// Input: pItem - Pointer to the item to fill in
// unDefinitionIndex - The definition index of the item to create
// Output: True if a matching item could be generated, false otherwise
//-----------------------------------------------------------------------------
CEconItem *CEconItemFactory::CreateSpecificItem( const CEconGameAccount *pGameAccount, item_definition_index_t unDefinitionIndex, ECreateItemPolicy_t eCreateItemPolicy )
{
if ( !pGameAccount )
return NULL;
// Find the matching index
const CEconItemDefinition *pItemDef = m_schema.GetItemDefinition( unDefinitionIndex );
if ( NULL == pItemDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateSpecificItem(): Item creation request with no matching definition (def index %u)\n", unDefinitionIndex );
return NULL;
}
const CEconItemQualityDefinition *pQualityDef = GetQualityDefinitionForItemCreation( NULL, pItemDef );
if ( NULL == pQualityDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateSpecificItem(): Item creation request with unknown quality\n" );
return NULL;
}
const CEconItemRarityDefinition *pRarityDef = GetRarityDefinitionForItemCreation( NULL, pItemDef );
if ( NULL == pRarityDef )
{
EmitWarning( SPEW_GC, 2, "CEconItemFactory::CreateSpecificItem(): Item creation request with unknown rarity\n" );
return NULL;
}
CEconItem *pItem = new CEconItem();
if ( eCreateItemPolicy & k_ECreateItemPolicy_NoSqlItemID )
pItem->SetItemID( 0ull );
else
pItem->SetItemID( GetNextID() );
pItem->SetDefinitionIndex( unDefinitionIndex );
pItem->SetItemLevel( pItemDef->RollItemLevel() );
pItem->SetQuality( pQualityDef->GetDBValue() );
pItem->SetRarity( pRarityDef->GetDBValue() );
// don't set inventory token
pItem->SetQuantity( MAX( 1, pItemDef->GetDefaultDropQuantity() ) );
pItem->SetAccountID( pGameAccount->Obj().m_unAccountID );
// Add any custom attributes we need
AddGCGeneratedAttributesToItem( pGameAccount, pItem );
return pItem;
}
//-----------------------------------------------------------------------------
// Purpose: Randomly chooses an item definition that matches the criteria
// Input: sCriteria - The criteria that the generated item must match
// Output: The chosen item definition, or NULL if no item could be selected
//-----------------------------------------------------------------------------
const CEconItemDefinition *CEconItemFactory::RollItemDefinition( const CItemSelectionCriteria &criteria ) const
{
// Determine which item templates match the criteria
CUtlVector<int> vecMatches;
const CEconItemSchema::ItemDefinitionMap_t &mapDefs = m_schema.GetItemDefinitionMap();
FOR_EACH_MAP_FAST( mapDefs, i )
{
if ( criteria.BEvaluate( mapDefs[i], m_schema ) )
{
vecMatches.AddToTail( mapDefs.Key( i ) );
}
}
if ( 0 == vecMatches.Count() )
return NULL;
// Choose a random match
int iIndex = RandomInt( 0, vecMatches.Count() - 1 );
return m_schema.GetItemDefinition( vecMatches[iIndex] );
}
//-----------------------------------------------------------------------------
// Purpose: Generates attributes that the item definition insists it always has, but must be generated by the GC
// Input:
//-----------------------------------------------------------------------------
void CEconItemFactory::AddGCGeneratedAttributesToItem( const CEconGameAccount *pGameAccount, CEconItem *pItem ) const
{
const CEconItemDefinition *pDef = m_schema.GetItemDefinition( pItem->GetDefinitionIndex() );
if ( !pDef )
return;
const CUtlVector<static_attrib_t> &vecStaticAttribs = pDef->GetStaticAttributes();
// Only generate attributes that force the GC to generate them (so they vary per item created)
FOR_EACH_VEC( vecStaticAttribs, i )
{
if ( vecStaticAttribs[i].m_bForceGCToGenerate )
{
ApplyStaticAttributeToItem( pItem, vecStaticAttribs[i], pGameAccount );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEconItemFactory::ApplyStaticAttributeToItem( CEconItem *pItem, const static_attrib_t& staticAttrib, const CEconGameAccount *pGameAccount, const CCopyableUtlVector< uint32 > *vecValues, float flRangeMin, float flRangeMax ) const
{
static CSchemaAttributeDefHandle pAttr_ElevateQuality( "elevate quality" );
static CSchemaAttributeDefHandle pAttr_SetItemTextureWear( "set item texture wear" );
static CSchemaAttributeDefHandle pAttr_SprayTintID( "spray tint id" );
static CSchemaAttributeDefHandle pAttr_SpraysRemaining( "sprays remaining" );
const CEconItemAttributeDefinition *pAttrDef = GetItemSchema()->GetAttributeDefinition( staticAttrib.iDefIndex );
Assert( pAttrDef );
// Special-case the elevate-quality attribute.
if ( pAttrDef->GetDefinitionIndex() == pAttr_ElevateQuality->GetDefinitionIndex() )
{
//AssertMsg( CEconItem::GetTypedAttributeType<CSchemaAttributeType_Default>( pAttrDef ), "Elevate quality attribute doesn't have the right type!" );
pItem->SetQuality( staticAttrib.m_value.asFloat );
return;
}
static CSchemaItemDefHandle hItemSpray( "spray" );
static CSchemaItemDefHandle hItemSprayPaint( "spraypaint" );
// Special-case the sprays remaining to mean unsealing the spray into spray paint
if ( pAttr_SpraysRemaining && hItemSpray && hItemSprayPaint && pItem->GetDefinitionIndex() == hItemSpray->GetDefinitionIndex() &&
pAttrDef->GetDefinitionIndex() == pAttr_SpraysRemaining->GetDefinitionIndex() )
{
pItem->SetDefinitionIndex( hItemSprayPaint->GetDefinitionIndex() );
pItem->SetFlag( kEconItemFlag_NonEconomy );
pItem->SetDynamicAttributeValue( pAttr_SpraysRemaining, uint32( PLAYERDECALS_NUMCHARGES ) );
return;
}
attribute_data_union_t attrValue = staticAttrib.m_value;
// pick from 'values' if they exist. Otherwise use min/max ranges specified.
if ( vecValues && ( *vecValues ).Count() != 0 )
{
uint32 uiRandIndex = CEconItemSchema::GetRandomStream().RandomInt( 0, ( *vecValues ).Count() - 1 );
if ( pAttrDef->IsStoredAsFloat() )
{
attrValue.asFloat = ( *vecValues ).Element( uiRandIndex );
}
else
{
attrValue.asUint32 = ( *vecValues ).Element( uiRandIndex );
}
}
else if ( flRangeMin != 0.0f || flRangeMax != 0.0 )
{
if ( pAttrDef->IsStoredAsFloat() )
{
attrValue.asFloat = CEconItemSchema::GetRandomStream().RandomFloat( flRangeMin, flRangeMax );
}
else
{
attrValue.asUint32 = CEconItemSchema::GetRandomStream().RandomInt( flRangeMin, flRangeMax );
}
}
if ( pAttr_SetItemTextureWear && staticAttrib.iDefIndex == pAttr_SetItemTextureWear->GetDefinitionIndex() )
{
const CPaintKit *pPaintKit = GetItemSchema()->GetPaintKitDefinition( pItem->GetCustomPaintKitIndex() );
if ( pPaintKit )
{
attrValue.asFloat = RemapValClamped( attrValue.asFloat, 0.0f, 1.0f, pPaintKit->flWearRemapMin, pPaintKit->flWearRemapMax );
}
}
#if ECON_SPRAY_TINT_IDS_FLOAT_COLORSPACE
if ( pAttr_SprayTintID && staticAttrib.iDefIndex == pAttr_SprayTintID->GetDefinitionIndex()
&& pAttr_SprayTintID->IsStoredAsInteger()
&& ( attrValue.asUint32 & 0xFF ) )
{ // Generation of random HSV space tints
attrValue.asUint32 = CombinedTintIDMakeFromIDHSVu( attrValue.asUint32,
CEconItemSchema::GetRandomStream().RandomInt( 0x00, 0x7F ),
CEconItemSchema::GetRandomStream().RandomInt( 0x00, 0x7F ),
CEconItemSchema::GetRandomStream().RandomInt( 0x00, 0x7F ) );
}
#endif
// Custom attribute initialization code?
pAttrDef->GetAttributeType()->LoadOrGenerateEconAttributeValue( pItem, pAttrDef, staticAttrib.m_pszCustomLogic, attrValue, pGameAccount );
}

View File

@@ -0,0 +1,74 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: EconItemFactory: Manages rolling for items requested by the game server
//
//=============================================================================
#ifndef ECONITEMFACTORY_H
#define ECONITEMFACTORY_H
#ifdef _WIN32
#pragma once
#endif
class CEconItem;
class CEconGameAccount;
namespace GCSDK
{
class CGCSharedObjectCache;
}
#include "game_item_schema.h"
//-----------------------------------------------------------------------------
// CEconItemFactory
// Factory responsible for rolling random items
//-----------------------------------------------------------------------------
class CEconItemFactory
{
public:
CEconItemFactory( );
enum ECreateItemPolicy_t
{
k_ECreateItemPolicy_Default = 0, // Default creating item policy
k_ECreateItemPolicy_NoSqlItemID = ( 1 << 0 ), // Item will have no ItemID generated
};
// Gets a pointer to the underlying item schema the factory is using
GameItemSchema_t &GetSchema() { return m_schema; }
// Create a random item based on the incoming item selection criteria
CEconItem *CreateRandomItem( const CEconGameAccount *pGameAccount, const CItemSelectionCriteria &criteria );
// Create an item from a specific definition index
CEconItem *CreateSpecificItem( const CEconGameAccount *pGameAccount, item_definition_index_t unDefinitionIndex, ECreateItemPolicy_t eCreateItemPolicy = k_ECreateItemPolicy_Default );
CEconItem *CreateSpecificItem( GCSDK::CGCSharedObjectCache *pUserSOCache, item_definition_index_t unDefinitionIndex )
{
return CreateSpecificItem( pUserSOCache->GetSingleton<CEconGameAccount>(), unDefinitionIndex );
}
itemid_t GetNextID();
bool BYieldingInit();
bool BIsInitialized() { return m_bIsInitialized; }
void ApplyStaticAttributeToItem( CEconItem *pItem, const static_attrib_t& staticAttrib, const CEconGameAccount *pGameAccount, const CCopyableUtlVector< uint32 > *m_vecValues = NULL, float flRangeMin = 0.0f, float flRangeMax = 0.0f ) const;
private:
// Functions to create random items
const CEconItemDefinition *RollItemDefinition( const CItemSelectionCriteria &criteria ) const;
void AddGCGeneratedAttributesToItem( const CEconGameAccount *pGameAccount, CEconItem *pItem ) const;
private:
// The schema this factory uses to create items
GameItemSchema_t m_schema;
// the next item ID to give out
itemid_t m_ulNextObjID;
bool m_bIsInitialized;
};
#endif //ECONITEMFACTORY_H

View File

@@ -0,0 +1,310 @@
#include "cbase.h"
#include "econ_item_interface.h"
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
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( "tradable after date" );
Assert( pAttrib );
if ( !pAttrib )
return 0;
RTime32 rtTimestamp;
if ( !FindAttribute( pAttrib, &rtTimestamp ) )
return 0;
return rtTimestamp;
}
RTime32 IEconItemInterface::GetUseAfterDateTime() const
{
static CSchemaAttributeDefHandle pAttrib( "use after date" );
Assert( pAttrib );
if ( !pAttrib )
return 0;
RTime32 rtTimestamp;
if ( !FindAttribute( pAttrib, &rtTimestamp ) )
return 0;
return rtTimestamp;
}
RTime32 IEconItemInterface::GetCacheRefreshDateTime() const
{
RTime32 rtExpiration = 0;
/** Removed for partner depot **/
return rtExpiration;
}
int IEconItemInterface::GetCustomPaintKitIndex( void ) const
{
static CSchemaAttributeDefHandle pAttrDef_PaintKit( "set item texture prefab" );
float flPaintKit = 0;
FindAttribute_UnsafeBitwiseCast<attrib_value_t>( this, pAttrDef_PaintKit, &flPaintKit );
return flPaintKit;
}
int IEconItemInterface::GetCustomPaintKitSeed( void ) const
{
static CSchemaAttributeDefHandle pAttrDef_PaintKitSeed( "set item texture seed" );
float flPaintSeed = 0;
FindAttribute_UnsafeBitwiseCast<attrib_value_t>( this, pAttrDef_PaintKitSeed, &flPaintSeed );
return flPaintSeed;
}
float IEconItemInterface::GetCustomPaintKitWear( float flWearDefault /*= 0.0f*/ ) const
{
static CSchemaAttributeDefHandle pAttrDef_PaintKitWear( "set item texture wear" );
float flPaintKitWear = flWearDefault;
FindAttribute_UnsafeBitwiseCast<attrib_value_t>( this, pAttrDef_PaintKitWear, &flPaintKitWear );
return flPaintKitWear;
}
float IEconItemInterface::GetStickerAttributeBySlotIndexFloat( int nSlotIndex, EStickerAttributeType type, float flDefault ) const
{
const CSchemaAttributeDefHandle &attrDef = GetStickerAttributeDefHandle( nSlotIndex, type );
if ( attrDef )
{
if ( attrDef->IsStoredAsFloat() )
{
float flOutput = 0.0f;
if ( FindAttribute_UnsafeBitwiseCast< attrib_value_t >( this, attrDef, &flOutput ) )
{
return flOutput;
}
}
else
{
Assert( false );
}
}
return flDefault;
}
uint32 IEconItemInterface::GetStickerAttributeBySlotIndexInt( int nSlotIndex, EStickerAttributeType type, uint32 uiDefault ) const
{
const CSchemaAttributeDefHandle &attrDef = GetStickerAttributeDefHandle( nSlotIndex, type );
if ( attrDef )
{
if ( attrDef->IsStoredAsFloat() )
{
Assert( false );
}
else
{
uint32 unOutput;
if ( FindAttribute( attrDef, &unOutput ) )
{
return unOutput;
}
}
}
return uiDefault;
}
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
bool IEconItemInterface::IsTradable() const
{
/** Removed for partner depot **/
return false;
}
bool IEconItemInterface::IsPotentiallyTradable() const
{
if ( GetItemDefinition() == NULL )
return false;
// check attributes
static CSchemaAttributeDefHandle pAttrDef_AlwaysTradableAndUsableInCrafting( "always tradable" );
static CSchemaAttributeDefHandle pAttrib_CannotTrade( "cannot trade" );
Assert( pAttrDef_AlwaysTradableAndUsableInCrafting != NULL );
Assert( pAttrib_CannotTrade != NULL );
if ( pAttrDef_AlwaysTradableAndUsableInCrafting == NULL || pAttrib_CannotTrade == NULL )
return false;
// NOTE: we are not checking the time delay on trade restriction here - the item is considered potentially tradable in future = true
// if ( GetTradableAfterDateTime() > CRTime::RTime32TimeCur() )
// return false;
// Explicit rules by item quality to validate trading eligibility
switch ( GetQuality() )
{
case AE_UNIQUE:
break;
case AE_STRANGE:
return ( GetOrigin() == kEconItemOrigin_FoundInCrate || GetOrigin() == kEconItemOrigin_Crafted || GetOrigin() == kEconItemOrigin_Purchased );
case AE_UNUSUAL:
case AE_TOURNAMENT:
return ( GetOrigin() == kEconItemOrigin_FoundInCrate );
default:
// all other qualities are untradable
return false;
}
if ( FindAttribute( pAttrDef_AlwaysTradableAndUsableInCrafting ) )
return true;
if ( FindAttribute( pAttrib_CannotTrade ) )
return false;
// 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:
case kEconItemOrigin_StockItem:
return false;
}
// certain quality levels are not tradable
if ( GetQuality() >= AE_COMMUNITY && GetQuality() <= AE_SELFMADE )
return false;
// explicitly marked cannot trade?
if ( ( kEconItemFlags_CheckFlags_CannotTrade & GetFlags() ) != 0 )
return false;
// tagged to not be a part of the economy?
if ( ( kEconItemFlag_NonEconomy & GetFlags() ) != 0 )
return false;
// This code catches stock items with name tags (rarity is stock) and prevents them from trading/marketing
// until we have a better solution for extracting value out of reselling these items and avoiding scams
if ( GetRarity() <= 0 )
return false;
return true;
}
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
bool IEconItemInterface::IsMarketable() const
{
/** Removed for partner depot **/
return false;
}
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
bool IEconItemInterface::IsCommodity() const
{
const CEconItemDefinition *pItemDef = GetItemDefinition();
if ( pItemDef == NULL )
return false;
static CSchemaAttributeDefHandle pAttrib_IsCommodity( "is commodity" );
Assert( pAttrib_IsCommodity != NULL );
if ( pAttrib_IsCommodity == NULL )
return false;
attrib_value_t unAttribValue;
if ( FindAttribute( pAttrib_IsCommodity, &unAttribValue ) && unAttribValue )
return true;
return false;
}
bool IEconItemInterface::IsHiddenFromDropList() const
{
const CEconItemDefinition *pItemDef = GetItemDefinition();
if ( pItemDef == NULL )
return false;
static CSchemaAttributeDefHandle pAttrib_HideFromDropList( "hide from drop list" );
Assert( pAttrib_HideFromDropList != NULL );
if ( pAttrib_HideFromDropList == NULL )
return false;
attrib_value_t unAttribValue;
if ( FindAttribute( pAttrib_HideFromDropList, &unAttribValue ) && unAttribValue )
return true;
return false;
}
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
bool IEconItemInterface::IsUsableInCrafting() const
{
if ( GetItemDefinition() == NULL )
return false;
// check attribute
static CSchemaAttributeDefHandle pAttrDef_AlwaysTradableAndUsableInCrafting( "always tradable" );
Assert( pAttrDef_AlwaysTradableAndUsableInCrafting );
if ( FindAttribute( pAttrDef_AlwaysTradableAndUsableInCrafting ) )
return true;
// explicitly marked not usable in crafting?
if ( ( kEconItemFlags_CheckFlags_NotUsableInCrafting & GetFlags() ) != 0 )
return false;
// items gained in this way are not craftable
switch ( GetOrigin() )
{
case kEconItemOrigin_Invalid:
case kEconItemOrigin_Foreign:
case kEconItemOrigin_PreviewItem:
case kEconItemOrigin_Purchased:
case kEconItemOrigin_StorePromotion:
case kEconItemOrigin_SteamWorkshopContribution:
return false;
}
// certain quality levels are not craftable
if ( GetQuality() >= AE_COMMUNITY && GetQuality() <= AE_SELFMADE )
return false;
// tagged to not be a part of the economy?
if ( ( kEconItemFlag_NonEconomy & GetFlags() ) != 0 )
return false;
return true;
}

View File

@@ -0,0 +1,442 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: CEconItem, a shared object for econ items
//
//=============================================================================
#ifndef ECONITEMINTERFACE_H
#define ECONITEMINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "game_item_schema.h" // needed for GameItemDefinition_t
class CAttribute_String;
//-----------------------------------------------------------------------------
// Purpose: Template helper classes for dealing with types.
//-----------------------------------------------------------------------------
// StripConstIfPresent<T> will take an input type T and "return" via ResultType:
//
// - T: T
// - const T: T
//
// This is used to prevent having to have different specializations for "T" versus
// "const T" when checking for equivalent template type arguments, etc.
template < typename T >
struct StripConstIfPresent { typedef T ResultType; };
template < typename T > struct StripConstIfPresent<const T> { typedef T ResultType; };
// AreTypesIdentical<T, U> takes two input types and "returns" via kValue whether the
// types are exactly equal. This is intended for checking type equivalence at compile-time
// in ways that template specializations for functions/classes may not be ideal for.
//
// We use it in the attribute code to guarantee that we're only doing The Old, Scary Path
// when dealing with attributes of The Old, Scary Type.
template < typename T, typename U >
struct AreTypesIdentical { enum { kValue = false }; };
template < typename T > struct AreTypesIdentical<T, T> { enum { kValue = true }; };
// IsValidAttributeValueTypeImpl<T> is a hand-made specialization for what types we want
// to consider valid attribute data types. This is used as a sanity check to make sure we
// don't pass in completely arbitrary types to things like FindAttribute(). (Doing so
// would cause an assert at runtime, but it seems like getting compile-time asserts is
// advantageous, and probably worth paying the small cost of adding to this list whenever
// a new attribute type is added.)
template < typename T>
struct IsValidAttributeValueTypeImpl { enum { kValue = false }; };
template < > struct IsValidAttributeValueTypeImpl<attrib_value_t> { enum { kValue = true }; };
template < > struct IsValidAttributeValueTypeImpl<float> { enum { kValue = true }; };
template < > struct IsValidAttributeValueTypeImpl<CAttribute_String> { enum { kValue = true }; };
template < > struct IsValidAttributeValueTypeImpl<Vector> { enum { kValue = true }; };
template < typename T >
struct IsValidAttributeValueType : public IsValidAttributeValueTypeImpl< typename StripConstIfPresent<T>::ResultType > { };
//-----------------------------------------------------------------------------
// Purpose: Interface for callback functions per-attribute-data-type. When adding
// a new attribute data type that can't be converted to any existing type,
// you'll need to add a new virtual function here or the code will fail
// to compile.
//-----------------------------------------------------------------------------
class IEconItemAttributeIterator
{
public:
virtual ~IEconItemAttributeIterator ( ) { }
// Returns whether to continue iteration after this element.
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) = 0;
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) = 0;
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) = 0;
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Iterator where each callback is default implemented, but the value
// is ignored. Derive from this iterator when you only care about certain
// attribute types.
//
//-----------------------------------------------------------------------------
class CEconItemSpecificAttributeIterator : public IEconItemAttributeIterator
{
// By default, always return true
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) { return true; }
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) { return true; }
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) { return true; }
};
//-----------------------------------------------------------------------------
// Purpose: Interface for a single callback function per-attribute, regardless of
// what type of data it stores and what the value is. This can be used
// to count attributes, display generic information about definitions, etc.
// but can't be used to pull data.
//
// To implement a subclass, override the OnIterateAttributeValueUntyped()
// method.
//-----------------------------------------------------------------------------
class IEconItemUntypedAttributeIterator : public IEconItemAttributeIterator
{
public:
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t ) OVERRIDE
{
return OnIterateAttributeValueUntyped( pAttrDef );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float ) OVERRIDE
{
return OnIterateAttributeValueUntyped( pAttrDef );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& ) OVERRIDE
{
return OnIterateAttributeValueUntyped( pAttrDef );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& ) OVERRIDE
{
return OnIterateAttributeValueUntyped( pAttrDef );
}
private:
virtual bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Simple class to answer the question "does this attribute exist" without
// regards to what value it might have. Intended to be used by FindAttribute()
// but made global because why not.
//-----------------------------------------------------------------------------
class CAttributeIterator_HasAttribute : public IEconItemUntypedAttributeIterator
{
public:
CAttributeIterator_HasAttribute( const CEconItemAttributeDefinition *pAttrDef )
: m_pAttrDef( pAttrDef )
, m_bFound( false )
{
Assert( m_pAttrDef );
}
bool WasFound() const
{
return m_bFound;
}
private:
bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef ) OVERRIDE
{
// We don't assert because we might be reusing the same iterator between calls.
// Assert( !m_bFound );
if ( m_pAttrDef == pAttrDef )
{
m_bFound = true;
}
return !m_bFound;
}
private:
const CEconItemAttributeDefinition *m_pAttrDef;
bool m_bFound;
};
//-----------------------------------------------------------------------------
// Purpose: Helper class to answer the question "does this attribute exist? and if
// so what is its value?". There are some template shenanigans that happen
// to make things as safe as possible, and to catch errors as early as
// possible.
//
// TActualTypeInMemory: the in-memory type of the data we're going to try
// to read out (ie., "attrib_value_t", "CAttribute_String",
// etc.
//
// TTreatAsThisType: if TActualTypeInMemory is "attrib_value_t", then we're
// dealing with the old attribute system and so maybe we
// want to treat these bits as a float, or a bitmask, or
// who knows! Specifying this type for non-attrib_value_t
// in-memory types is invalid and will fail to compile.
//
// This class isn't intended to be used directly but instead called from
// either FindAttribute() or FindAttribute_UnsafeBitwiseCast(). It's
// global because C++ doesn't support template member functions on a
// template class inside a standalone template function. Weird.
//-----------------------------------------------------------------------------
template < typename TActualTypeInMemory, typename TTreatAsThisType = TActualTypeInMemory >
class CAttributeIterator_GetTypedAttributeValue : public IEconItemAttributeIterator
{
public:
CAttributeIterator_GetTypedAttributeValue( const CEconItemAttributeDefinition *pAttrDef, TTreatAsThisType *outpValue )
: m_pAttrDef( pAttrDef )
, m_outpValue( outpValue )
, m_bFound( false )
{
// If this fails, it means that the type TActualTypeInMemory isn't something the attribute
// system is prepared to recognize as a valid attribute storage type. The list of valid types
// are IsValidAttributeValueTypeImpl<> specializations.
//
// If you added a new type and didn't make a specialization for it, this will fail. If you
// *didn't* add a new type, it probably means you're passing a pointer of an incorrect type
// in to FindAttribute().
COMPILE_TIME_ASSERT( IsValidAttributeValueType<TActualTypeInMemory>::kValue );
// The only reason we allow callers to specify a different TTreatAsThisType (versus having
// it always match TActualTypeInMemory) is to deal with the old attribute system, which sometimes
// had attributes have int/float types and sometimes had attribute data values that were 32
// arbitrary bits. We test here to make sure that we're only using the "treat these bits as
// a different type" behavior code when dealing with attributes using the old storage system
// (attrib_value_t) or when we're trying to get the pointer to buffer contents for a string.
COMPILE_TIME_ASSERT( ((AreTypesIdentical<TActualTypeInMemory, attrib_value_t>::kValue && AreTypesIdentical<TTreatAsThisType, float>::kValue) ||
(AreTypesIdentical<TActualTypeInMemory, CAttribute_String>::kValue && AreTypesIdentical<TTreatAsThisType, const char *>::kValue) ||
AreTypesIdentical<TActualTypeInMemory, TTreatAsThisType>::kValue) );
Assert( m_pAttrDef );
Assert( outpValue );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value ) OVERRIDE
{
return OnIterateAttributeValueTyped( pAttrDef, value );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, float value ) OVERRIDE
{
return OnIterateAttributeValueTyped( pAttrDef, value );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_String& value ) OVERRIDE
{
return OnIterateAttributeValueTyped( pAttrDef, value );
}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const Vector& value ) OVERRIDE
{
return OnIterateAttributeValueTyped( pAttrDef, value );
}
bool WasFound() const
{
return m_bFound;
}
private:
// Generic template function for handling any attribute value of any type besides the one that we're looking
// for. For example, if we say "we're looking for attribute 'damage multiplier' and give me back a float", then
// all other attribute value types (strings, structures, etc.) will go through this code, which does nothing
// except look for caller errors.
//
// If you call FindAttribute() and specify the wrong type for an attribute (ie., using the above example, looking
// for "damage multiplier" but feeding in a string), it will get found in this function, which will assert and
// tell you you've got the wrong type. (FindAttribute() in that case will return false because it's impossible
// for us to safely copy the value out.)
template < typename TAnyOtherType >
bool OnIterateAttributeValueTyped( const CEconItemAttributeDefinition *pAttrDef, const TAnyOtherType& value )
{
COMPILE_TIME_ASSERT( IsValidAttributeValueType<TAnyOtherType>::kValue );
// We don't assert because we might be reusing the same iterator between calls.
// Assert( !m_bFound );
AssertMsg( m_pAttrDef != pAttrDef, "Incorrect type found for attribute during iteration." );
return true;
}
// Overload for attributes of the data type we're looking for. ie., if we say "we're looking for attribute
// 'damage multiplier' and give me back a float", this will be the <float> specialization. We assume that
// we're only going to find at most one attribute per definition and stop looking after we've found the first.
//
// Note that this is just a normal member function, but is *not* a template member function, which would compile
// under VC but otherwise be illegal.
bool OnIterateAttributeValueTyped( const CEconItemAttributeDefinition *pAttrDef, const TActualTypeInMemory& value )
{
// We don't assert because we might be reusing the same iterator between calls.
// Assert( !m_bFound );
if ( m_pAttrDef == pAttrDef )
{
m_bFound = true;
CopyAttributeValueToOutput( &value, reinterpret_cast<TTreatAsThisType *>( m_outpValue ) );
}
return !m_bFound;
}
private:
static void CopyAttributeValueToOutput( const TActualTypeInMemory *pValue, TTreatAsThisType *out_pValue )
{
// Even if we are using the old attribute type system, we need to guarantee that the type
// in memory (ie., uint32) and the type we're considering it as (ie., float) are the same size
// because we're going to be doing bitwise casts.
COMPILE_TIME_ASSERT( sizeof( TActualTypeInMemory ) == sizeof( TTreatAsThisType ) );
Assert( pValue );
Assert( out_pValue );
*out_pValue = *reinterpret_cast<const TTreatAsThisType *>( pValue );
}
private:
const CEconItemAttributeDefinition *m_pAttrDef;
TTreatAsThisType *m_outpValue;
bool m_bFound;
};
//-----------------------------------------------------------------------------
// Purpose: Custom code path to support getting the char * result from an
// attribute of type CAttribute_String.
//
// We can't specify the implementation here because we may or may not
// have the definition of CAttribute_String in scope. We also can't
// declare the template specialization here and define it later because
// that would violate the standard, so instead we have the template
// function call a declared-but-not-defined non-template function that
// we can define later.
//-----------------------------------------------------------------------------
void CopyStringAttributeValueToCharPointerOutput( const CAttribute_String *pValue, const char **out_pValue );
template < >
inline void CAttributeIterator_GetTypedAttributeValue<CAttribute_String, const char *>::CopyAttributeValueToOutput( const CAttribute_String *pValue, const char **out_pValue )
{
CopyStringAttributeValueToCharPointerOutput( pValue, out_pValue );
}
//-----------------------------------------------------------------------------
// Purpose: Look for the existence/nonexistence of an attribute with the
// definition [pAttrDef]. Can be called on anything with an IterateAttributes()
// member functions (IEconItemInterface, CEconItemDefinition).
//-----------------------------------------------------------------------------
template < typename TAttributeContainerType >
bool FindAttribute( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef )
{
if ( !pAttrDef )
return false;
CAttributeIterator_HasAttribute it( pAttrDef );
pSomethingThatHasAnIterateAttributesFunction->IterateAttributes( &it );
return it.WasFound();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
template < typename TActualTypeInMemory, typename TTreatAsThisType, typename TAttributeContainerType >
bool FindAttribute_UnsafeBitwiseCast( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef, TTreatAsThisType *out_pValue )
{
if ( !pAttrDef )
return false;
CAttributeIterator_GetTypedAttributeValue<TActualTypeInMemory, TTreatAsThisType> it( pAttrDef, out_pValue );
pSomethingThatHasAnIterateAttributesFunction->IterateAttributes( &it );
return it.WasFound();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
template < typename TAttributeContainerType, typename T >
bool FindAttribute( const TAttributeContainerType *pSomethingThatHasAnIterateAttributesFunction, const CEconItemAttributeDefinition *pAttrDef, T *out_pValue )
{
return FindAttribute_UnsafeBitwiseCast<T, T, TAttributeContainerType>( pSomethingThatHasAnIterateAttributesFunction, pAttrDef, out_pValue );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class IEconItemInterface
{
public:
virtual ~IEconItemInterface() { }
// Is an attribute present? We neither know nor care anything about the attribute
// value stored.
bool FindAttribute( const CEconItemAttributeDefinition *pAttrDef ) const
{
return ::FindAttribute( this, pAttrDef );
}
// If an attribute is present, it will copy the value into out_pValue and return true.
// If the attribute is not present, it will return false and not touch the value in
// out_pValue. If a T is passed in that is not a type the attribute system understands,
// this function will fail to compile.
template < typename T >
bool FindAttribute( const CEconItemAttributeDefinition *pAttrDef, T *out_pValue ) const
{
return ::FindAttribute( this, pAttrDef, out_pValue );
}
virtual int GetCustomPaintKitIndex( void ) const;
virtual int GetCustomPaintKitSeed( void ) const;
virtual float GetCustomPaintKitWear( float flWearDefault = 0.0f ) const;
virtual float GetStickerAttributeBySlotIndexFloat( int nSlotIndex, EStickerAttributeType type, float flDefault ) const;
virtual uint32 GetStickerAttributeBySlotIndexInt( int nSlotIndex, EStickerAttributeType type, uint32 uiDefault ) const;
// IEconItemInterface common implementation.
virtual bool IsTradable() const;
virtual bool IsMarketable() const;
virtual bool IsCommodity() const;
virtual bool IsUsableInCrafting() const;
virtual bool IsHiddenFromDropList() const;
virtual RTime32 GetExpirationDate() const;
// IEconItemInterface interface.
virtual const GameItemDefinition_t *GetItemDefinition() const = 0;
virtual uint32 GetAccountID() const = 0;
virtual uint64 GetItemID() const = 0;
virtual int32 GetQuality() const = 0;
virtual int32 GetRarity() const = 0;
virtual uint8 GetFlags() const = 0;
virtual eEconItemOrigin GetOrigin() const = 0;
virtual uint16 GetQuantity() const = 0;
virtual uint32 GetItemLevel() const = 0;
virtual bool GetInUse() const = 0; // is this item in use somewhere in the backend? (ie., cross-game trading)
virtual const char *GetCustomName() const = 0; // get a user-generated name, if present, otherwise NULL; return value is UTF8
virtual const char *GetCustomDesc() const = 0; // get a user-generated flavor text, if present, otherwise NULL; return value is UTF8
virtual int GetItemSetIndex() const = 0;
// IEconItemInterface attribute iteration interface. This is not meant to be used for
// attribute lookup! This is meant for anything that requires iterating over the full
// attribute list.
virtual void IterateAttributes( IEconItemAttributeIterator *pIterator ) const = 0;
// We can check whether the item is potentially tradable in future if enough time
// passes, and if yes can get the exact date when it becomes tradable
bool IsPotentiallyTradable() const;
RTime32 GetCacheRefreshDateTime() const;
RTime32 GetTradableAfterDateTime() const;
RTime32 GetUseAfterDateTime() const;
};
#endif // ECONITEMINTERFACE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,490 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: Container that allows client & server access to data in player inventories & loadouts
//
//=============================================================================
#ifndef ITEM_INVENTORY_H
#define ITEM_INVENTORY_H
#ifdef _WIN32
#pragma once
#endif
#include "igamesystem.h"
#include "econ_entity.h"
#include "econ_item_view.h"
#include "utlsortvector.h"
#if !defined(NO_STEAM)
#include "steam/steam_api.h"
#include "gcsdk/gcclientsdk.h"
#endif // NO_STEAM
class CPlayerInventory;
class CEconItem;
struct baseitemcriteria_t;
// Inventory Less function.
// Used to sort the inventory items into their positions.
class CInventoryListLess
{
public:
bool Less( CEconItemView* const &src1, CEconItemView *const &src2, void *pCtx );
};
// A class that wants notifications when an inventory is updated
class IInventoryUpdateListener : public GCSDK::ISharedObjectListener
{
public:
virtual void InventoryUpdated( CPlayerInventory *pInventory ) = 0;
virtual void SOCreated( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { InventoryUpdated( NULL ); }
virtual void SOUpdated( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { InventoryUpdated( NULL ); }
virtual void SODestroyed( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { InventoryUpdated( NULL ); }
virtual void SOCacheSubscribed( GCSDK::SOID_t owner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { InventoryUpdated( NULL ); }
virtual void SOCacheUnsubscribed( GCSDK::SOID_t owner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE { InventoryUpdated( NULL ); }
};
//-----------------------------------------------------------------------------
// Purpose: A single 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 CPlayerInventory : public GCSDK::ISharedObjectListener
{
DECLARE_CLASS_NOBASE( CPlayerInventory );
public:
CPlayerInventory();
virtual ~CPlayerInventory();
void Shutdown( void );
// Returns true if this inventory has been filled out by Steam.
bool InventoryRetrievedFromSteamAtLeastOnce( void ) const { return m_bGotItemsFromSteamAtLeastOnce; }
bool InventorySubscribedToSteamCurrently( void ) const { return m_bCurrentlySubscribedToSteam; }
// Inventory access
GCSDK::SOID_t GetOwner( void ) { return m_OwnerID; }
void SetOwner( GCSDK::SOID_t& ownerID ) { m_OwnerID = ownerID; }
int GetItemCount( void ) const { return m_Items.GetItemVector().Count(); }
int GetDefaultEquippedDefinitionItemsCount( void ) const { return m_aDefaultEquippedDefinitionItems.Count(); }
virtual bool CanPurchaseItems( int iItemCount ) const { return GetMaxItemCount() - GetItemCount() >= iItemCount; }
virtual int GetMaxItemCount( void ) const { return DEFAULT_NUM_BACKPACK_SLOTS; }
CEconItemView *GetItem( int i ) { return m_Items.GetItemVector()[i]; }
CEconItemView *GetDefaultEquippedDefinitionItem( int i ) { return m_aDefaultEquippedDefinitionItems[ i ]; }
CEconItemView *FindDefaultEquippedDefinitionItemBySlot( int iClass, int iSlot ) const;
bool GetDefaultEquippedDefinitionItemSlotByDefinitionIndex( item_definition_index_t nDefIndex, int nClass, int &nSlot );
void SetDefaultEquippedDefinitionItemBySlot( int iClass, int iSlot, item_definition_index_t iDefIndex );
void FindItemsByType( EItemType eType, CUtlVector< CEconItemView* >& outVec );
virtual CEconItemView *GetItemInLoadout( int iClass, int iSlot ) const { AssertMsg( 0, "Implement me!" ); return NULL; }
// Get the item object cache data for the specified item
CEconItem *GetSOCDataForItem( itemid_t iItemID );
const CEconItem *GetSOCDataForItem( itemid_t iItemID ) const;
GCSDK::CGCClientSharedObjectCache *GetSOC( void ) { return m_pSOCache; }
// tells the GC systems to forget about this listener
void RemoveListener( GCSDK::ISharedObjectListener *pListener );
// Finds the item in our inventory that matches the specified global index
CEconItemView *GetInventoryItemByItemID( itemid_t iIndex ) const;
// Finds the item in our inventory in the specified position
CEconItemView *GetItemByPosition( int iPosition, int *pIndex = NULL );
// Used to reject items on the backend for inclusion into this inventory.
// Mostly used for division of bags into different in-game inventories.
virtual bool ItemShouldBeIncluded( int iItemPosition ) { return true; }
// Debugging
virtual void DumpInventoryToConsole( bool bRoot );
// 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 ) { return iBackendPosition; }
// Recipe access
int GetRecipeCount( void ) const;
const CEconCraftingRecipeDefinition *GetRecipeDef( int iIndex ) const;
const CEconCraftingRecipeDefinition *GetRecipeDefByDefIndex( uint16 iDefIndex ) const;
int GetMaxCraftIngredientsNeeded( const CUtlVector< itemid_t >& vecCraftEconItems ) const;
void GetMarketCraftCompletionLink( const CUtlVector< itemid_t >& vecCraftItems, char *pchLink, int nNumChars ) const;
int GetPossibleCraftResultsCount( const CUtlVector< itemid_t >& vecCraftItems ) const;
int GetPossibleCraftResultsCount( const CUtlVector< CEconItem* >& vecCraftEconItems ) const;
const CEconCraftingRecipeDefinition *GetPossibleCraftResult( const CUtlVector< itemid_t >& vecCraftItems, int nIndex ) const;
int GetPossibleCraftResultID( const CUtlVector< itemid_t >& vecCraftItems, int nIndex ) const;
const wchar_t* GetPossibleCraftResultName( const CUtlVector< itemid_t >& vecCraftItems, int nIndex ) const;
const wchar_t* GetPossibleCraftResultDescription( const CUtlVector< itemid_t >& vecCraftItems, int nIndex ) const;
bool CanAddToCraftTarget( const CUtlVector< itemid_t >& vecCraftItems, itemid_t nNewItem ) const;
bool IsCraftReady( const CUtlVector< itemid_t >& vecCraftItems, int16 &nRecipe ) const;
void CraftIngredients( const CUtlVector< itemid_t >& vecCraftItems ) const;
void SetTargetCraftRecipe( int nRecipe ) { m_nTargetRecipe = nRecipe; }
int16 GetTargetCraftRecipe( void ) const { return m_nTargetRecipe; }
// Finds the item in our inventory that matches the specified global index
void ClearItemCustomName( itemid_t iIndex );
void WearItemSticker( itemid_t iIndex, int nSlot, float flStickerWearCurrent );
// Item access
uint32 GetItemCount( uint32 unItemDef );
// Item previews
virtual int GetPreviewItemDef( void ) const { return 0; };
// Access helpers
virtual void SOClear();
virtual void NotifyHasNewItems() {}
bool AddEconItem( CEconItem * pItem, bool bUpdateAckFile, bool bWriteAckFile, bool bCheckForNewItems );
enum EInventoryItemEvent
{
k_EInventoryItemCreated,
k_EInventoryItemUpdated,
k_EInventoryItemDestroyed,
};
// Made public for an inventory helper func
int m_nTargetRecipe;
protected:
// Inventory updating, called by the Inventory Manager only. If you want an inventory updated,
// use the SteamRequestX functions in CInventoryManager.
void RequestInventory( GCSDK::SOID_t ID );
void AddListener( GCSDK::ISharedObjectListener *pListener );
virtual void RemoveItem( itemid_t iItemID );
bool AddEconDefaultEquippedDefinition( CEconDefaultEquippedDefinitionInstanceClient *pDefaultEquippedDefinition );
bool FilloutItemFromEconItem( CEconItemView *pScriptItem, CEconItem *pEconItem );
virtual void SendInventoryUpdateEvent();
virtual void OnHasNewItems() {}
virtual void OnItemChangedPosition( CEconItemView *pItem, uint32 iOldPos ) { return; }
virtual void SOCreated( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void SOUpdated( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void SODestroyed( GCSDK::SOID_t owner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void SOCacheSubscribed( GCSDK::SOID_t owner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void SOCacheUnsubscribed( GCSDK::SOID_t owner, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void ValidateInventoryPositions( void );
// Derivable Inventory hooks
virtual void ItemHasBeenUpdated( CEconItemView *pItem, bool bUpdateAckFile, bool bWriteAckFile, EInventoryItemEvent eEventType );
virtual void ItemIsBeingRemoved( CEconItemView *pItem ) { return; }
virtual void DefaultEquippedDefinitionHasBeenUpdated( CEconDefaultEquippedDefinitionInstanceClient *pDefaultEquippedDefinition );
virtual void MarkSetItemDescriptionsDirty( int nItemSetIndex );
// Get the index for the item in our inventory utlvector
int GetIndexForItem( CEconItemView *pItem );
protected:
// The SharedObject Id of the player who owns this inventory
GCSDK::SOID_t m_OwnerID;
CUtlVector< CEconItemView*> m_aDefaultEquippedDefinitionItems;
typedef CUtlMap< itemid_t, CEconItemView*, int, CDefLess< itemid_t > > ItemIdToItemMap_t;
// Wrap different container types so they all stay in sync with inventory state
class CItemContainers
{
public:
void Add( CEconItemView* pItem );
void Remove( itemid_t ullItemID );
void Purge();
bool DbgValidate() const; // Walk all containers and confirm content matches
const CUtlVector< CEconItemView*>& GetItemVector( void ) const { return m_vecInventoryItems; }
const ItemIdToItemMap_t& GetItemMap( void ) const { return m_mapItemIDToItemView; }
private:
// The items the player has in his inventory, received from steam.
CUtlVector< CEconItemView*> m_vecInventoryItems;
// Copies of pointers in vector for faster lookups
ItemIdToItemMap_t m_mapItemIDToItemView;
};
CItemContainers m_Items;
int m_iPendingRequests;
bool m_bGotItemsFromSteamAtLeastOnce, m_bCurrentlySubscribedToSteam;
GCSDK::CGCClientSharedObjectCache *m_pSOCache;
CUtlVector<GCSDK::ISharedObjectListener *> m_vecListeners;
friend class CInventoryManager;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CInventoryManager : public CAutoGameSystem
{
DECLARE_CLASS_GAMEROOT( CInventoryManager, CAutoGameSystem );
public:
CInventoryManager( void );
virtual ~CInventoryManager() {}
// Adds the inventory to the list of inventories that should be maintained.
// This causes the game to load the items for the SteamID into this inventory.
// NOTE: This fires off a request to Steam. The data will not be filled out immediately.
void SteamRequestInventory( CPlayerInventory *pInventory, CSteamID pSteamID, IInventoryUpdateListener *pListener = NULL );
void RegisterPlayerInventory( CPlayerInventory *pInventory, IInventoryUpdateListener *pListener = NULL, CSteamID* pSteamID = NULL );
void PreInitGC();
void PostInitGC();
#ifdef CLIENT_DLL
void DeleteItem( itemid_t iItemID, bool bRecycle=false );
int DeleteUnknowns( CPlayerInventory *pInventory );
#endif
public:
//-----------------------------------------------------------------------
// IAutoServerSystem
//-----------------------------------------------------------------------
virtual bool Init( void );
virtual void PostInit( void );
virtual void Shutdown();
virtual void LevelInitPreEntity( void );
virtual void LevelShutdownPostEntity( void );
#if defined(CSTRIKE15) && defined(CLIENT_DLL)
virtual void InsertMaterialGenerationJob( CEconItemView *pItemView );
virtual void OnDestroyEconItemView( CEconItemView *pItemView );
#endif
void GameServerSteamAPIActivated();
virtual CPlayerInventory *GetInventoryForAccount( uint32 iAccountID );
// 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 ) { return; }
#ifdef CLIENT_DLL
// Must be implemented by derived class
virtual bool EquipItemInLoadout( int iClass, int iSlot, itemid_t iItemID, bool bSwap = false ) = 0;
virtual CPlayerInventory *GeneratePlayerInventoryObject() const { return new CPlayerInventory; }
void DestroyPlayerInventoryObject( CPlayerInventory *pPlayerInventory ) const;
//-----------------------------------------------------------------------
// LOCAL INVENTORY
//
// 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.
// Override GetLocalInventory() in your inventory manager and return your custom local inventory.
//-----------------------------------------------------------------------
virtual void UpdateLocalInventory( void );
virtual CPlayerInventory *GetLocalInventory( void ) { return NULL; }
// The local inventory is used to track discards & responses to. We need to
// make a decision about inventory space right after sending a delete request,
// so we predict the request will work.
void OnItemDeleted( CPlayerInventory *pInventory ) { if ( pInventory == GetLocalInventory() ) m_iPredictedDiscards--; }
static void SendGCConnectedEvent( void );
// Returns the item at the specified backpack position
virtual CEconItemView *GetItemByBackpackPosition( int iBackpackPosition );
// Moves the item to the specified backpack position. If there's another item as that spot, it swaps positions with it.
virtual void MoveItemToBackpackPosition( CEconItemView *pItem, int iBackpackPosition );
// Tries to set the item to the specified backpack position. Passing in 0 will find the first empty position.
// FAILS if the backpack is full, or if that spot isn't clear. Returns false in that case.
virtual bool SetItemBackpackPosition( CEconItemView *pItem, uint32 iPosition = 0, bool bForceUnequip = false, bool bAllowOverflow = false );
// Sort the backpack items by the specified type
virtual void SortBackpackBy( uint32 iSortType );
void SortBackpackFinished( void );
bool IsInBackpackSort( void ) { return m_bInBackpackSort; }
void PredictedBackpackPosFilled( int iBackpackPos );
// Tell the backend to move an item to a specified backend position
virtual void UpdateInventoryPosition( CPlayerInventory *pInventory, uint64 ulItemID, uint32 unNewInventoryPos );
virtual void UpdateInventoryEquippedState( CPlayerInventory *pInventory, uint64 ulItemID, equipped_class_t unClass, equipped_slot_t unSlot, bool bSwap = false );
void BeginBackpackPositionTransaction();
void EndBackpackPositionTransaction();
//-----------------------------------------------------------------------
// CLIENT PICKUP UI HANDLING
//-----------------------------------------------------------------------
// Get the number of items picked up
virtual int GetNumItemPickedUpItems( void ) { return 0; }
// 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<itemid_t> *vecCraftedIndices ) { return; }
// Force the player to discard an item to make room for a new item, if they have one.
// Returns true if the discard panel has been brought up, and the player will be forced to discard an item.
virtual bool CheckForRoomAndForceDiscard( void );
//-----------------------------------------------------------------------
// CLIENT ITEM PICKUP ACKNOWLEDGEMENT FILES
//
// This system avoids showing multiple pickups for items that we've found, but haven't been
// able to move out of unack'd position due to the GC being unavailable. We keep a list of
// items we've ack'd in a client file, and don't re-show pickups for them. When a GC item
// update tells us the item has moved out of the unack'd position, we remove it from our file.
//-----------------------------------------------------------------------
bool HasBeenAckedByClient( CEconItemView *pItem ); // Returns true if it's in our client file
void SetAckedByClient( CEconItemView *pItem ); // Adds it to our client file
void SetAckedByGC( CEconItemView *pItem, bool bSave ); // Removes it from our client file
private:
CUtlRBTree< itemid_t, int32, CDefLess< itemid_t > > m_rbItemIdsClientAck;
// As we move items around in batches (on pickups usually) we need to know what slots will be filled
// by items we've moved, and haven't received a response from Steam.
typedef CUtlMap< uint32, uint64, int > tPredictedSlots;
tPredictedSlots m_mapPredictedFilledSlots;
public:
// TODO: Does this belong here?
bool BGetPlayerQuestIdPointsRemaining( uint16 unQuestID, uint32 &numPointsRemaining, uint32 &numPointsUncommitted );
public:
CEconItemView *CreateReferenceEconItem( item_definition_index_t iDefIndex, int iPaintIndex, uint8 ub1 = 0 );
void RemoveReferenceEconItem( item_definition_index_t iDefIndex, int iPaintIndex, uint8 ub1 );
CEconItemView *FindReferenceEconItem( item_definition_index_t iDefIndex, int iPaintIndex, uint8 ub1 );
CEconItemView *FindOrCreateReferenceEconItem( item_definition_index_t iDefIndex, int iPaintIndex, uint8 ub1 = 0 );
CEconItemView *FindOrCreateReferenceEconItem( itemid_t ullFauxItemId );
CUtlVector< CEconItemView* > m_pTempReferenceItems; // A collection of econitemviews that are created temporarily just to pull inventory data from.
#endif //CLIENT_DLL
public:
virtual int GetBackpackPositionFromBackend( uint32 iBackendPosition ) { return ExtractBackpackPositionFromBackend(iBackendPosition); }
protected:
//-----------------------------------------------------------------------
// Inventory registry
void DeregisterInventory( CPlayerInventory *pInventory );
struct inventories_t
{
CPlayerInventory *pInventory;
IInventoryUpdateListener *pListener;
};
CUtlVector<inventories_t> m_pInventories;
friend class CPlayerInventory;
inline bool IsValidPlayerClass( equipped_class_t unClass );
inline bool IsValidSlot( equipped_slot_t unSlot );
#ifdef CLIENT_DLL
// Keep track of the number of items we've tried to discard, but haven't recieved responses on
int m_iPredictedDiscards;
typedef CUtlMap< uint32, CUtlString, int > tPersonaNamesByAccountID;
tPersonaNamesByAccountID m_mapPersonaNamesCache;
bool m_bInBackpackSort;
// Allows transaction item updating when moving many items
CMsgSetItemPositions m_itemPositions;
bool m_bIsBatchingPositions;
private:
CON_COMMAND_MEMBER_F( CInventoryManager, "econ_clear_inventory_images", ClearLocalInventoryImages, "clear the local inventory images (they will regenerate)", FCVAR_CLIENTDLL );
#endif //CLIENT_DLL
};
//=================================================================================
// Implement these functions in your game code to create custom derived versions
CInventoryManager *InventoryManager( void );
#ifdef CLIENT_DLL
// Inventory Less function.
// Used to sort the inventory items into their positions.
class CManagedItemViewsLess
{
public:
bool Less( CEconItemView * const & src1, CEconItemView * const & src2, void *pCtx )
{
uint64 unIndex1 = src1->GetItemID();
uint64 unIndex2 = src2->GetItemID();
if ( unIndex1 == unIndex2 )
{
return EconRarity_CombinedItemAndPaintRarity( src1->GetStaticData()->GetRarity(), src1->GetCustomPaintKitIndex() ) >
EconRarity_CombinedItemAndPaintRarity( src2->GetStaticData()->GetRarity(), src2->GetCustomPaintKitIndex() );
}
return unIndex1 == 0ull || ( unIndex1 < unIndex2 );
}
};
class CInventoryItemUpdateManager: public CAutoGameSystemPerFrame
{
public:
virtual void Update( float frametime );
void AddItemView( CEconItemView *pItemView )
{
FOR_EACH_VEC( m_ManagedItems, i )
{
if ( m_ManagedItems[i] == pItemView )
return;
}
m_ManagedItems.Insert( pItemView );
}
void RemoveItemView( CEconItemView *pItemView )
{
m_ManagedItems.FindAndRemove( pItemView );
}
void AddItemViewToFixupList( CEconItemView *pItemView )
{
m_fixupListMutex.Lock();
m_fixupList.AddToHead( pItemView );
m_fixupListMutex.Unlock();
}
void RemoveItemViewFromFixupList( CEconItemView *pItemView )
{
m_fixupListMutex.Lock();
m_fixupList.FindAndRemove( pItemView );
m_fixupListMutex.Unlock();
}
private:
CUtlSortVector< CEconItemView*, CManagedItemViewsLess > m_ManagedItems;
CUtlVector< CEconItemView* > m_fixupList;
CThreadFastMutex m_fixupListMutex;
};
extern CInventoryItemUpdateManager g_InventoryItemUpdateManager;
#endif
#endif // ITEM_INVENTORY_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,795 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "tier1/keyvalues.h"
#include "econ_gcmessages.h"
#include "econ_item_system.h"
#include "econ_item_inventory.h"
#include "game_item_schema.h"
#include "utldict.h"
#include "filesystem.h"
#include "steam/isteamhttp.h"
#if defined(CLIENT_DLL) || defined(GAME_DLL)
#include "ihasattributes.h"
#include "tier0/icommandline.h"
#endif
#if defined(CLIENT_DLL)
#include "igameevents.h"
#endif
// FIXME FIXME FIXME
#if defined(TF_DLL) || defined(TF_CLIENT_DLL)
#include "tf_item_system.h"
#endif // defined(TF_DLL) || defined(TF_CLIENT_DLL)
#if defined (DOTA_CLIENT_DLL) || defined (DOTA_DLL)
#include "econ/dota_item_system.h"
#endif // defined (DOTA_CLIENT_DLL) || defined (DOTA_DLL)
#if defined( CSTRIKE_CLIENT_DLL ) || defined( CSTRIKE15 )
#include "cstrike15_item_system.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if (defined(GAME_DLL) || defined(CLIENT_DLL)) && defined(_DEBUG)
ConVar item_debug( "item_debug", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY );
ConVar item_debug_validation( "item_debug_validation", "1", FCVAR_REPLICATED | FCVAR_ARCHIVE, "If set, CEconEntity::ValidateEntityAttachedToPlayer behaves as it would in release builds and also allows bot players to take the same code path as real players." );
static ConVar item_quality_chance_unique( "item_quality_chance_unique", "0.1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Percentage chance that a random item is unique." );
static ConVar item_quality_chance_rare( "item_quality_chance_rare", "0.5", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Percentage chance that a random item is a rare." );
static ConVar item_quality_chance_common( "item_quality_chance_common", "1.0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Percentage chance that a random item is common." );
#endif
//-----------------------------------------------------------------------------
// Purpose: Get at the global item system
//-----------------------------------------------------------------------------
CEconItemSystem *ItemSystem( void )
{
static GameItemSystem_t *pSystem = NULL;
if ( !pSystem )
{
pSystem = new GameItemSystem_t();
}
return pSystem;
}
//-----------------------------------------------------------------------------
// Purpose: Global schema access, declared in game_item_schema.h
//-----------------------------------------------------------------------------
GameItemSchema_t *GetItemSchema()
{
return ItemSystem()->GetItemSchema();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CEconItemSystem::CEconItemSystem( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CEconItemSystem::~CEconItemSystem( void )
{
Shutdown();
}
//-----------------------------------------------------------------------------
// Purpose: Parse in our data files.
//-----------------------------------------------------------------------------
void CEconItemSystem::Init( void )
{
#ifdef CLIENT_DLL
IGameEvent *event = gameeventmanager->CreateEvent( "item_schema_initialized" );
if ( event )
{
gameeventmanager->FireEventClientSide( event );
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEconItemSystem::Shutdown( void )
{
}
extern ConVar mp_tournament;
#ifdef GAME_DLL
ConVar mp_tournament_whitelist( "mp_tournament_whitelist", "item_whitelist.txt", FCVAR_NONE, "Specifies the item whitelist file to use." );
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEconItemSystem::ReloadWhitelist( void )
{
// Default state of items depends on whether we're in tourney mode, and whether there's a whitelist
bool bDefault = true;
bool bFoundWhitelist = false;
KeyValues::AutoDelete pWhitelistKV( "item_whitelist" );
#ifdef GAME_DLL
if ( mp_tournament.GetBool() && mp_tournament_whitelist.GetString() )
{
const char *pszWhitelistFile = mp_tournament_whitelist.GetString();
if ( pWhitelistKV->LoadFromFile( filesystem, pszWhitelistFile ) )
{
// Allow the whitelist to override the default, so they can turn it into a blacklist if they want to
bDefault = pWhitelistKV->GetBool( "unlisted_items_default_to" );
bFoundWhitelist = true;
}
else if ( pszWhitelistFile && pszWhitelistFile[0] )
{
Msg("Item Whitelist file '%s' could not be found. All items will be allowed.\n", pszWhitelistFile );
}
}
#endif
const CEconItemSchema::ItemDefinitionMap_t& mapItemDefs = m_itemSchema.GetItemDefinitionMap();
FOR_EACH_MAP_FAST( mapItemDefs, i )
{
mapItemDefs[i]->SetAllowedInMatch( bDefault );
}
// If we didn't find a file, we're done.
if ( !bFoundWhitelist )
return;
// Otherwise, go through the KVs and turn on the matching items.
Msg("Parsing item whitelist (default: %s)\n", bDefault ? "allowed" : "disallowed" );
for ( KeyValues *pKey = pWhitelistKV->GetFirstSubKey(); pKey != NULL; pKey = pKey->GetNextKey() )
{
bool bAllow = pKey->GetBool();
const char *pszItemName = pKey->GetName();
if ( pszItemName && pszItemName[0] && !FStrEq("unlisted_items_default_to", pszItemName) )
{
CEconItemDefinition *pItemDef = m_itemSchema.GetItemDefinitionByName( pszItemName );
if ( pItemDef )
{
pItemDef->SetAllowedInMatch( bAllow );
Msg(" -> %s '%s'\n", bAllow ? "Allowing" : "Removing", pszItemName );
}
else
{
Warning(" -> Could not find an item definition named '%s'\n", pszItemName );
}
}
}
Msg("Finished.\n");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEconItemSystem::ResetAttribStringCache( void )
{
CEconItemSchema::EconAttrDefsContainer_t &mapDefs = m_itemSchema.GetAttributeDefinitionContainer();
FOR_EACH_VEC( mapDefs, i )
{
if ( mapDefs[i] )
mapDefs[i]->ClearStringCache();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CEconItemSystem::DecryptItemFiles( KeyValues *pKV, const char *pName )
{
char szFullName[512];
Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", pName );
FileHandle_t f = filesystem->Open( szFullName, "rb", "MOD" );
if (!f)
{
#if !defined(CSTRIKE_DLL)
Warning("No %s file found. May be unable to create items.\n", pName );
#endif // CSTRIKE_DLL
return false;
}
int fileSize = filesystem->Size(f);
char *buffer = (char*)MemAllocScratch(fileSize + 1);
Assert(buffer);
filesystem->Read(buffer, fileSize, f); // read into local buffer
buffer[fileSize] = 0; // null terminate file as EOF
filesystem->Close( f ); // close file after reading
UTIL_DecodeICE( (unsigned char*)buffer, fileSize, GetEncryptionKey() );
bool retOK = pKV->LoadFromBuffer( szFullName, buffer, filesystem );
MemFreeScratch();
if ( !retOK )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Read the specified item schema file. Init the item schema with the contents
//-----------------------------------------------------------------------------
void CEconItemSystem::ParseItemSchemaFile( const char *pFilename )
{
CUtlVector< CUtlString > vecErrors;
bool bSuccess = m_itemSchema.BInit( pFilename, "MOD", &vecErrors );
if( !bSuccess )
{
FOR_EACH_VEC( vecErrors, nError )
{
Msg( "%s", vecErrors[nError].String() );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Generate a random item matching the specified criteria
//-----------------------------------------------------------------------------
int CEconItemSystem::GenerateRandomItem( CItemSelectionCriteria *pCriteria, entityquality_t *outEntityQuality )
{
// First, pick a random item quality (use the one passed in first)
if ( !pCriteria->BQualitySet() )
{
pCriteria->SetQuality( GetRandomQualityForItem() );
}
pCriteria->SetIgnoreEnabledFlag( true );
// Determine which item templates match the criteria
CUtlVector<int> vecMatches;
const CEconItemSchema::ItemDefinitionMap_t &mapDefs = m_itemSchema.GetItemDefinitionMap();
HackMakeValidList:
FOR_EACH_MAP_FAST( mapDefs, i )
{
if ( pCriteria->BEvaluate( mapDefs[i], m_itemSchema ) )
{
vecMatches.AddToTail( mapDefs.Key( i ) );
}
}
// No valid items?
int iValidItems = vecMatches.Count();
if ( !iValidItems )
{
// If we were searching for a unique item, drop back to a non-unique
if ( pCriteria->GetQuality() == AE_UNIQUE )
{
pCriteria->SetQuality( GetRandomQualityForItem( true ) );
goto HackMakeValidList;
}
return INVALID_ITEM_INDEX;
}
// Choose a random match
int iChosenIdx = RandomInt( 0, (iValidItems-1) );
int iChosenItem = vecMatches[iChosenIdx];
const CEconItemDefinition *pItemDef = m_itemSchema.GetItemDefinition( iChosenItem );
if ( !pItemDef )
return INVALID_ITEM_INDEX;
// If we haven't specified an entity quality, we want to use the item's specified one
if ( pCriteria->GetQuality() == AE_USE_SCRIPT_VALUE )
{
int32 iScriptQuality = pItemDef->GetQuality();
pCriteria->SetQuality( iScriptQuality == AE_UNDEFINED ? GetRandomQualityForItem( true ) : iScriptQuality );
}
// If we haven't specified an item level, we want to use the item's specified one.
if ( !pCriteria->BItemLevelSet() )
{
pCriteria->SetItemLevel( RandomInt( pItemDef->GetMinLevel(), pItemDef->GetMaxLevel() ) );
}
if ( outEntityQuality )
{
*outEntityQuality = pCriteria->GetQuality();
}
return iChosenItem;
}
//-----------------------------------------------------------------------------
// Purpose: Return a random quality for the item specified
//-----------------------------------------------------------------------------
entityquality_t CEconItemSystem::GetRandomQualityForItem( bool bPreventUnique )
{
/*
// Start on the rarest, and work backwards
if ( !bPreventUnique )
{
if ( RandomFloat(0,1) < item_quality_chance_unique.GetFloat() )
return AE_UNIQUE;
}
if ( RandomFloat(0,1) < item_quality_chance_rare.GetFloat() )
return AE_RARITY2;
if ( RandomFloat(0,1) < item_quality_chance_common.GetFloat() )
return AE_RARITY1;
*/
return AE_NORMAL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CEconItemAttribute *CEconItemSystem::GenerateAttribute( attrib_definition_index_t iAttributeDefinition, float flValue )
{
// Create a new instance of the chosen attribute
CEconItemAttribute *pAttribute = new CEconItemAttribute( iAttributeDefinition, flValue );
return pAttribute;
}
//-----------------------------------------------------------------------------
// Purpose: Generate an attribute by name. Used for debugging.
//-----------------------------------------------------------------------------
CEconItemAttribute *CEconItemSystem::GenerateAttribute( const char *pszName, float flValue )
{
// Find the attribute index matching the class
CEconItemSchema::EconAttrDefsContainer_t &mapDefs = m_itemSchema.GetAttributeDefinitionContainer();
FOR_EACH_VEC( mapDefs, i )
{
if ( !mapDefs[i] )
continue;
if ( Q_stricmp(pszName, mapDefs[i]->GetDefinitionName()) )
continue;
return GenerateAttribute( mapDefs[i]->GetDefinitionIndex(), flValue );
}
return NULL;
}
static ISteamHTTP *GetISteamHTTP()
{
if ( steamapicontext != NULL && steamapicontext->SteamHTTP() )
{
return steamapicontext->SteamHTTP();
}
#ifndef CLIENT_DLL
if ( steamgameserverapicontext != NULL )
{
return steamgameserverapicontext->SteamHTTP();
}
#endif
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Common functionality for using our raw buffer data to initialize
// the schema when safe.
//-----------------------------------------------------------------------------
bool IDelayedSchemaData::InitializeSchemaInternal( CEconItemSchema *pItemSchema, CUtlBuffer& bufRawData, bool bInitAsBinary, uint32 nExpectedVersion )
{
DevMsg( 2, "Applying new item schema, version %08X\n", nExpectedVersion );
CUtlVector<CUtlString> vecErrors;
bool bSuccess = bInitAsBinary
? pItemSchema->BInitBinaryBuffer( bufRawData, &vecErrors )
: pItemSchema->BInitTextBuffer( bufRawData, &vecErrors );
if( bSuccess )
{
// Sanity-check that we received the version that they sent us
uint32 nOurVersion = pItemSchema->GetVersion();
if ( nExpectedVersion != 0 && nOurVersion != nExpectedVersion )
{
Warning( "**WARNING** Item schema mismatch after update!\n" );
Warning( "GC told us to expect %08X, we got %08X\n", nExpectedVersion, nOurVersion );
}
}
else
{
Warning( "**WARNING** Failed to apply item schema!\n" );
FOR_EACH_VEC( vecErrors, nError )
{
Warning( "%s\n", vecErrors[nError].Get() );
}
}
return bSuccess;
}
//-----------------------------------------------------------------------------
// Purpose: The GC sent us a single block of binary data.
//-----------------------------------------------------------------------------
class DelayedSchemaData_GCDirectData : public IDelayedSchemaData
{
public:
DelayedSchemaData_GCDirectData( const std::string& strBuffer )
: m_bufRawData( strBuffer.data(), strBuffer.size(), CUtlBuffer::READ_ONLY )
{
//
}
virtual bool InitializeSchema( CEconItemSchema *pItemSchema )
{
return InitializeSchemaInternal( pItemSchema, m_bufRawData, true, 0 );
}
private:
CUtlBuffer m_bufRawData;
};
//-----------------------------------------------------------------------------
// Purpose: We received a text file from an HTML request.
//-----------------------------------------------------------------------------
class DelayedSchemaData_HTTPResponseData : public IDelayedSchemaData
{
public:
DelayedSchemaData_HTTPResponseData( ISteamHTTP *pHTTP, HTTPRequestHandle handleHTTPRequest, uint32 unBodySize, uint32 nExpectedVersion )
: m_nExpectedVersion( nExpectedVersion )
{
Assert( pHTTP );
m_bufRawData.SetBufferType( true, true );
m_bufRawData.SeekPut( CUtlBuffer::SEEK_HEAD, unBodySize );
m_bValid = pHTTP->GetHTTPResponseBodyData( handleHTTPRequest, (uint8*)m_bufRawData.Base(), m_bufRawData.TellPut() );
}
virtual bool InitializeSchema( CEconItemSchema *pItemSchema )
{
if ( !m_bValid )
return false;
return InitializeSchemaInternal( pItemSchema, m_bufRawData, false, m_nExpectedVersion );
}
private:
bool m_bValid;
CUtlBuffer m_bufRawData;
uint32 m_nExpectedVersion;
};
#if GC_UPDATE_ITEM_SCHEMA_SUPPORTED
//-----------------------------------------------------------------------------
// Purpose: Update the item schema from the GC
//-----------------------------------------------------------------------------
class CGCUpdateItemSchema : public GCSDK::CGCClientJob
{
public:
CGCUpdateItemSchema( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {
m_szUrl[0] = '\0';
m_nExpectedVersion = 0;
bHTTPCompleted = false;
}
char m_szUrl[512];
uint32 m_nExpectedVersion;
bool bHTTPCompleted;
CCallResult< CGCUpdateItemSchema, HTTPRequestCompleted_t > callback;
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
GCSDK::CProtoBufMsg< CMsgUpdateItemSchema > msg( pNetPacket );
#if (defined(GAME_DLL) || defined(CLIENT_DLL))
bool bUseGCCopy = true;
if ( steamapicontext && steamapicontext->SteamUtils() && steamapicontext->SteamUtils()->GetConnectedUniverse() != k_EUniversePublic )
{
bUseGCCopy = CommandLine()->FindParm( "-use_local_item_data" ) == 0;
}
#else
bool bUseGCCopy = true;
#endif
if ( bUseGCCopy == false )
{
Msg( "Loading item schema from local file.\n" );
KeyValuesAD pItemsGameKV( "ItemsGameFile" );
if ( pItemsGameKV->LoadFromFile( g_pFullFileSystem, "scripts/items/items_game.txt", "GAME" ) )
{
CUtlBuffer buffer;
pItemsGameKV->WriteAsBinary( buffer );
CUtlVector< CUtlString > vecErrors;
bool bSuccess = ItemSystem()->GetItemSchema()->BInitBinaryBuffer( buffer, &vecErrors );
if( !bSuccess )
{
FOR_EACH_VEC( vecErrors, nError )
{
Warning( "%s\n", vecErrors[nError].Get() );
}
}
}
return true;
}
// Check if we're already up-to-date
m_nExpectedVersion = msg.Body().item_schema_version();
uint32 nCurrentSchemaVersion = ItemSystem()->GetItemSchema()->GetVersion();
if ( m_nExpectedVersion != 0 && m_nExpectedVersion == nCurrentSchemaVersion )
{
Msg( "Current item schema is up-to-date with version %08X.\n", nCurrentSchemaVersion );
return true;
}
// !TEST!
//const char *szURL = "http://cdntest.steampowered.com/apps/440/scripts/items/items_game.b8b7a85b4dd98b139957004b86ec0bc070a59d18.txt";
if ( msg.Body().has_items_game() )
{
DevMsg( 2, "Received %d bytes item schema version %08X direct data; update is queued.\n", (int)msg.Body().items_game().size(), m_nExpectedVersion );
ItemSystem()->GetItemSchema()->MaybeInitFromBuffer( new DelayedSchemaData_GCDirectData( msg.Body().items_game() ) );
}
else
{
// Remember URL
const char *szURL = msg.Body().items_game_url().c_str();
if ( !szURL || !szURL[0] )
{
Warning( "GC sent malformed CGCUpdateItemSchema message: No schema data, no URL\n" );
}
else
{
Q_strncpy( m_szUrl, szURL, sizeof( m_szUrl ) );
//Msg( "Fetching %s to update item schema\n", m_szUrl );
// Send an HTTP request for the file
ISteamHTTP *pHTTP = GetISteamHTTP();
if ( !pHTTP )
{
// We must be a game server. Request the direct data.
Msg( "ISteamHTTP not available to update item schema, requesting direct data for version %08X\n", m_nExpectedVersion );
return true;
}
HTTPRequestHandle hReq = pHTTP->CreateHTTPRequest( k_EHTTPMethodGET, m_szUrl );
pHTTP->SetHTTPRequestNetworkActivityTimeout( hReq, 10 );
SteamAPICall_t hCall;
if ( !pHTTP->SendHTTPRequest( hReq, &hCall ) )
{
Warning( "Failed to update item schema: couldn't fetch %s\n", m_szUrl );
return true;
}
//
// *Wait* for completion.
//
// This is important. The GC needs to be able to safely assume that
// we will not process the next message until we have finished
// dealing with this one.
//
bHTTPCompleted = false;
#ifndef CLIENT_DLL
if ( steamgameserverapicontext != NULL && pHTTP == steamgameserverapicontext->SteamHTTP() )
{
callback.SetGameserverFlag();
}
#endif
callback.Set( hCall, this, &CGCUpdateItemSchema::OnHTTPCompleted );
// Wait for it to finish.
while ( !bHTTPCompleted )
{
BYieldingWaitOneFrame();
}
}
}
return true;
}
void OnHTTPCompleted( HTTPRequestCompleted_t *arg, bool bFailed )
{
// Clear flag, no matter what else, so we can stop yielding
bHTTPCompleted = true;
ISteamHTTP *pHTTP = GetISteamHTTP();
Assert( pHTTP );
if ( !pHTTP ) return;
if ( arg->m_eStatusCode != k_EHTTPStatusCode200OK )
{
Warning( "Failed to update item schema: HTTP status %d fetching %s\n", arg->m_eStatusCode, m_szUrl );
}
else
{
if ( !arg->m_bRequestSuccessful )
{
bFailed = true;
}
if ( !bFailed )
{
uint32 unBodySize;
if ( !pHTTP->GetHTTPResponseBodySize( arg->m_hRequest, &unBodySize ) )
{
Assert( false );
bFailed = true;
}
else
{
DevMsg( 2, "Fetched %d bytes item schema version %08X via HTTP; update is queued.\n", unBodySize, m_nExpectedVersion );
ItemSystem()->GetItemSchema()->MaybeInitFromBuffer( new DelayedSchemaData_HTTPResponseData( pHTTP, arg->m_hRequest, unBodySize, m_nExpectedVersion ) );
}
}
if ( bFailed )
{
Warning( "Failed to update item schema from %s\n", m_szUrl );
}
}
pHTTP->ReleaseHTTPRequest( arg->m_hRequest );
}
};
GC_REG_CLIENT_JOB( CGCUpdateItemSchema, k_EMsgGCUpdateItemSchema );
#endif
#ifdef CLIENT_DLL
//-----------------------------------------------------------------------------
// Purpose: Update the item schema from the GC
//-----------------------------------------------------------------------------
CON_COMMAND_F( econ_show_items_with_tag, "Lists the item definitions that have a specified tag.", FCVAR_CLIENTDLL )
{
if ( args.ArgC() != 2 )
return;
econ_tag_handle_t tagHandle = GetItemSchema()->GetHandleForTag( args.Arg( 1 ) );
FOR_EACH_MAP( GetItemSchema()->GetSortedItemDefinitionMap(), i )
{
const CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinitionMap()[i];
if ( pItemDef->HasEconTag( tagHandle ) )
{
Msg(" '%s'\n", pItemDef->GetDefinitionName() );
}
}
}
#endif // CLIENT_DLL
#ifdef CLIENT_DLL
//-----------------------------------------------------------------------------
// Purpose: Get a file from a given URL.
// Generalized version of the item schema update.
//-----------------------------------------------------------------------------
CGCFetchWebResource::CGCFetchWebResource( GCSDK::CGCClient *pClient, CUtlString strName, CUtlString strURL, bool bForceSkipCache/*=false*/, KeyValues *pkvGETParams/*=NULL*/ ) : GCSDK::CGCClientJob( pClient )
{
m_strName = strName;
m_strURL = strURL;
m_bHTTPCompleted = false;
m_bForceSkipCache = bForceSkipCache;
m_pkvGETParams = pkvGETParams->MakeCopy();
}
CGCFetchWebResource::~CGCFetchWebResource()
{
if ( m_pkvGETParams )
{
m_pkvGETParams->deleteThis();
}
}
bool CGCFetchWebResource::BYieldingRunGCJob()
{
ISteamHTTP *pHTTP = GetISteamHTTP();
if ( !pHTTP )
{
// We must be a game server.
Msg( "ISteamHTTP not available to update web resource.\n" );
return true;
}
// Send an HTTP request for the file.
HTTPRequestHandle hReq = pHTTP->CreateHTTPRequest( k_EHTTPMethodGET, m_strURL.Get() );
pHTTP->SetHTTPRequestNetworkActivityTimeout( hReq, 10 );
// Skip any data that may be cached in the Steam client or elsewhere
if ( m_bForceSkipCache )
{
pHTTP->SetHTTPRequestHeaderValue( hReq, "Cache-Control", "no-cache, no-store" );
}
// Add any GET params
if ( m_pkvGETParams )
{
FOR_EACH_VALUE( m_pkvGETParams, kvSubKey )
{
pHTTP->SetHTTPRequestGetOrPostParameter( hReq, kvSubKey->GetName(), kvSubKey->GetString() );
}
}
SteamAPICall_t hCall;
if ( !pHTTP->SendHTTPRequest( hReq, &hCall ) )
{
Warning( "Failed to update web resource: couldn't fetch %s\n", m_strURL.Get() );
return true;
}
// Wait for completion.
m_bHTTPCompleted = false;
callback.Set( hCall, this, &CGCFetchWebResource::OnHTTPCompleted );
// Wait for it to finish.
while ( !m_bHTTPCompleted )
{
BYieldingWaitOneFrame();
}
return true;
}
void CGCFetchWebResource::OnHTTPCompleted( HTTPRequestCompleted_t *arg, bool bFailed )
{
// Clear flag so we can stop yielding.
m_bHTTPCompleted = true;
ISteamHTTP *pHTTP = GetISteamHTTP();
Assert( pHTTP );
if ( !pHTTP )
return;
if ( arg->m_eStatusCode != k_EHTTPStatusCode200OK )
{
Warning( "Failed to update web resource: HTTP status %d fetching %s\n", arg->m_eStatusCode, m_strURL.Get() );
}
else
{
if ( !arg->m_bRequestSuccessful )
{
bFailed = true;
}
if ( !bFailed )
{
uint32 unBodySize;
if ( !pHTTP->GetHTTPResponseBodySize( arg->m_hRequest, &unBodySize ) )
{
Assert( false );
bFailed = true;
}
else
{
DevMsg( 2, "Fetched %d bytes for web resource via HTTP.\n", unBodySize );
CUtlBuffer bufRawData;
bufRawData.SetBufferType( true, true );
bufRawData.SeekPut( CUtlBuffer::SEEK_HEAD, unBodySize );
bool bValid = pHTTP->GetHTTPResponseBodyData( arg->m_hRequest, (uint8*) bufRawData.Base(), bufRawData.TellPut() );
if ( bValid )
{
KeyValues* pResourceKV = new KeyValues( "" );
pResourceKV->LoadFromBuffer( "", bufRawData );
ItemSystem()->GetItemSchema()->SetWebResource( m_strName, pResourceKV );
}
}
}
if ( bFailed )
{
Warning( "Failed to update web resource from %s\n", m_strURL.Get() );
}
}
pHTTP->ReleaseHTTPRequest( arg->m_hRequest );
}
#endif

View File

@@ -0,0 +1,138 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef ECON_ITEM_SYSTEM_H
#define ECON_ITEM_SYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "econ_item_view.h"
#include "game_item_schema.h"
#include "game/shared/econ/iecon_item_system.h"
//==================================================================================
// ITEM SYSTEM
//==================================================================================
#define INVALID_ITEM_INDEX -1
#define GC_MOTD_CACHE_FILE "cfg/motd_entries.txt"
// The item system parses and creates a list of item classes from the item_classes.txt file.
//-----------------------------------------------------------------------------
// Criteria used by the system to generate a random attribute
struct randomattributecriteria_t
{
randomattributecriteria_t()
{
entityType = AE_MAX_TYPES;
iAttributeLevel = 0;
pItem = NULL;
}
entityquality_t entityType;
int iAttributeLevel;
CEconItemView *pItem;
};
//-----------------------------------------------------------------------------
// Purpose: Container for all the static item definitions in the item data files
//-----------------------------------------------------------------------------
class CEconItemSystem : public IEconItemSystem
{
public:
CEconItemSystem( void );
virtual ~CEconItemSystem( void );
// Setup & parse in the item data files.
void Init( void );
void Shutdown( void );
// Return the static item data for the specified item index
const GameItemDefinition_t *GetStaticDataForItemByDefIndex( item_definition_index_t iItemDefIndex ) const
{
return static_cast< const GameItemDefinition_t* >( m_itemSchema.GetItemDefinition( iItemDefIndex ) );
}
const CEconItemDefinition *GetStaticDataForItemByName( const char *pszDefName ) const
{
return m_itemSchema.GetItemDefinitionByName( pszDefName );
}
const CEconItemAttributeDefinition *GetStaticDataForAttributeByDefIndex( attrib_definition_index_t iAttribDefinitionIndex ) const
{
return m_itemSchema.GetAttributeDefinition( iAttribDefinitionIndex );
}
const CEconItemAttributeDefinition *GetStaticDataForAttributeByName( const char *pszDefName ) const
{
return m_itemSchema.GetAttributeDefinitionByName( pszDefName );
}
// Select and return a random item's definition index matching the specified criteria
int GenerateRandomItem( CItemSelectionCriteria *pCriteria, entityquality_t *outEntityQuality );
// Select and return the base item definition index for a class's load-out slot
// Note: baseitemcriteria_t is game-specific and/or may not exist!
virtual int GenerateBaseItem( struct baseitemcriteria_t *pCriteria ) { return INVALID_ITEM_INDEX; }
// Return a random item quality
entityquality_t GetRandomQualityForItem( bool bPreventUnique = false );
// Generate an attribute of the specified definition
CEconItemAttribute *GenerateAttribute( attrib_definition_index_t iAttributeDefinition, float flValue );
// Generate an attribute by name. Used for debugging.
CEconItemAttribute *GenerateAttribute( const char *pszName, float flValue );
// Decrypt the item files and return the keyvalue
bool DecryptItemFiles( KeyValues *pKV, const char *pName );
GameItemSchema_t *GetItemSchema() { return &m_itemSchema; }
// Open the server's whitelist, and if it exists, set the appropriate items allowed.
void ReloadWhitelist( void );
void ResetAttribStringCache( void );
// Public interface.
virtual IEconItemSchema* GetItemSchemaInterface() { return GetItemSchema(); }
virtual void RequestReservedItemDefinitionList() {};
virtual void ReserveItemDefinition( uint32 nDefIndex, const char* pszUserName ) {};
virtual void ReleaseItemDefReservation( uint32 nDefIndex, const char* pszUserName ) {};
protected:
// Read the specified item schema file. Init the item schema with the contents
void ParseItemSchemaFile( const char *pFilename );
// Key to decrypt the item description files
const unsigned char *GetEncryptionKey( void ) { return (unsigned char *)"A5fSXbf7"; }
private:
GameItemSchema_t m_itemSchema;
};
CEconItemSystem *ItemSystem( void );
// CGCFetchWebResource
class CGCFetchWebResource : public GCSDK::CGCClientJob
{
public:
CGCFetchWebResource( GCSDK::CGCClient *pClient, CUtlString strName, CUtlString strURL, bool bForceSkipCache = false, KeyValues *pkvGETParams = NULL );
virtual ~CGCFetchWebResource();
bool BYieldingRunGCJob();
void OnHTTPCompleted( HTTPRequestCompleted_t *arg, bool bFailed );
private:
CUtlString m_strName;
CUtlString m_strURL;
bool m_bForceSkipCache;
bool m_bHTTPCompleted;
KeyValues *m_pkvGETParams;
CCallResult< CGCFetchWebResource, HTTPRequestCompleted_t > callback;
};
#endif // ECON_ITEM_SYSTEM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,613 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef ECON_ITEM_CONSTANTS_H
#define ECON_ITEM_CONSTANTS_H
#ifdef _WIN32
#pragma once
#endif
#include "game_item_schema.h"
#include "econ_item_constants.h"
#include "localization_provider.h"
#include "econ_item_interface.h"
#include "econ_item.h"
#include "tier1/utlhashtable.h"
#if defined(CLIENT_DLL)
#include "iclientrenderable.h"
#if defined(CSTRIKE15)
#include "materialsystem/custommaterialowner.h"
#endif //#if defined(CSTRIKE15)
#include "materialsystem/icompositetexturegenerator.h"
#endif //#if defined(CLIENT_DLL)
#include "materialsystem/MaterialSystemUtil.h"
#if defined(TF_DLL)
#include "tf_item_schema.h"
#endif //#if defined(TF_DLL)
#if defined(CLIENT_DLL)
#define CEconItemView C_EconItemView
#if defined(CSTRIKE15)
typedef void (*ImageReadyCallback_t)( const CEconItemView *pItemView, CUtlBuffer &rawImageRgba, int nWidth, int nHeight, uint64 nItemID );
struct RenderToRTData_t;
class CMergedMDL;
#endif //#if defined(CSTRIKE15)
#endif //#if defined(CLIENT_DLL)
#include "econ_item_view_helpers.h"
#define RGB_INT_RED 12073019
#define RGB_INT_BLUE 5801378
#define ECON_ITEM_GENERATED_ICON_WIDTH 512
#define ECON_ITEM_GENERATED_ICON_HEIGHT 384
#define ECON_ITEM_GENERATED_PINBOARD_ICON_WIDTH 512
#define ECON_ITEM_GENERATED_PINBOARD_ICON_HEIGHT 384
#define ECON_ITEM_GENERATED_ICON_DIR "resource/Flash/econ/weapons/cached/"
#define SCHEMA_BASE_ITEM_MAX 499 // def indices 1-499 are reserved for default aka stock items
class CEconItemAttribute;
class CAttributeManager;
#if defined(CSTRIKE_CLIENT_DLL)
class IVisualsDataProcessor;
#endif
struct stickerMaterialReference_t
{
CMaterialReference m_pMaterialReferenceFirstPerson;
CMaterialReference m_pMaterialReferenceThirdPerson;
int m_nSlotIndex;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CAttributeList
{
friend class CEconItemView;
friend class CTFPlayer;
DECLARE_CLASS_NOBASE( CAttributeList );
public:
DECLARE_EMBEDDED_NETWORKVAR();
DECLARE_DATADESC();
CAttributeList();
CAttributeList& operator=( const CAttributeList &src );
void Init();
void SetManager( CAttributeManager *pManager );
void IterateAttributes( class IEconItemAttributeIterator *pIterator );
// Remove all attributes on this item
void DestroyAllAttributes( void );
// Prevent clients from modifying attributes directly from this list. They should do it from the CEconItemView.
private:
// Add an attribute to this item
void AddAttribute( CEconItemAttribute *pAttribute );
void SetOrAddAttributeValueByName( const char *pszAttribDefName, float flValue );
// Remove an attribute by name
void RemoveAttribute( const char *pszAttribDefName );
void RemoveAttributeByIndex( int iIndex );
public:
// Returns the attribute that matches the attribute defname
CEconItemAttribute *GetAttributeByName( const char *pszAttribDefName );
const CEconItemAttribute *GetAttributeByName( const char *pszAttribDefName ) const;
// Returns the attribute matching the specified class, carried by this entity, if it exists.
CEconItemAttribute *GetAttributeByClass( const char *szAttribClass );
const CEconItemAttribute *GetAttributeByClass( const char *szAttribClass ) const;
// Returns the attribute that matches the attribute defindex
CEconItemAttribute *GetAttributeByDefIndex( uint16 unAttrDefIndex );
const CEconItemAttribute *GetAttributeByDefIndex( uint16 unAttrDefIndex ) const;
// The only way to set the value of an attribute after its creation is through the attribute list
// that contains it. This way the matching attribute manager is told one of its attributes has changed.
void SetValue( CEconItemAttribute *pAttrib, float flValue );
void UpdateManagerCache( void );
private:
// Attribute accessing
int GetNumAttributes( void ) const { return m_Attributes.Count(); }
CEconItemAttribute *GetAttribute( int iIndex ) { Assert( iIndex >= 0 && iIndex < m_Attributes.Count()); return &m_Attributes[iIndex]; }
const CEconItemAttribute *GetAttribute( int iIndex ) const { Assert( iIndex >= 0 && iIndex < m_Attributes.Count()); return &m_Attributes[iIndex]; }
// Our list of attributes
CUtlVector<CEconItemAttribute> m_Attributes;
CAttributeManager *m_pManager;
};
//-----------------------------------------------------------------------------
// Purpose: An attribute that knows how to read itself from a datafile, describe itself to the user,
// and serialize itself between Servers, Clients, and Steam.
// Unlike the attributes created in the Game DLL, this attribute doesn't know how to actually
// do anything in the game, it just knows how to describe itself.
//-----------------------------------------------------------------------------
class CEconItemAttribute
{
DECLARE_CLASS_NOBASE( CEconItemAttribute );
public:
DECLARE_EMBEDDED_NETWORKVAR();
CEconItemAttribute( const attrib_definition_index_t iAttributeIndex, float flValue );
CEconItemAttribute( const attrib_definition_index_t iAttributeIndex, uint32 unValue );
CEconItemAttribute & operator=( const CEconItemAttribute &val );
// Get the index of this attribute's definition inside the script file
attrib_definition_index_t GetAttribIndex( void ) const { return m_iAttributeDefinitionIndex; }
void SetAttribIndex( attrib_definition_index_t iIndex ) { m_iAttributeDefinitionIndex = iIndex; }
// Get the static data contained in this attribute's definition
const CEconItemAttributeDefinition *GetStaticData( void ) const;
// Get the float value of this attribute.
float GetValue( void ) const;
// Get the value of this attribute as an unsigned integer.
uint32 GetIntValue( void ) const;
float GetInitialValue( void ) const { return m_flInitialValue; }
int GetRefundableCurrency( void ) const { return m_nRefundableCurrency; }
void AddRefundableCurrency( int nAdd ) { m_nRefundableCurrency += nAdd; }
void RemovedRefundableCurrency( int nSubtract ) { m_nRefundableCurrency -= nSubtract; }
// Get & Set the setbonus flag. Allowed to set it here because it doesn't affect attribute caches.
bool GetSetBonus( void ) { return m_bSetBonus; }
void SetSetBonus( bool bBonus ) { m_bSetBonus = bBonus; }
private:
// The only way to set the value of an attribute after its creation is through the attribute list
// that contains it. This way the matching attribute manager is told one of its attributes has changed.
// Set the float value of this attribute.
// Note that the value must be stored as a float!
void SetValue( float flValue );
// Set the value of this attribute as an unsigned integer.
// Note that the value must be stored as an integer!
// See CEconItemAttributeDefinition
void SetIntValue( uint32 unValue );
friend class CAttributeList;
friend class CEconItemSystem;
void Init( void );
//--------------------------------------------------------
private:
// This is the index of the attribute into the attributes read from the data files
CNetworkVar( attrib_definition_index_t, m_iAttributeDefinitionIndex );
// This is the value of the attribute. Used to modify the item's variables.
CNetworkVar( float, m_flValue );
// This is the value that the attribute was first set to by an item definition
CNetworkVar( float, m_flInitialValue );
CNetworkVar( int, m_nRefundableCurrency );
CNetworkVar( bool, m_bSetBonus ); // Attribute has been generated by a set bonus.
public:
// Used for copy constructor only
CEconItemAttribute( void );
};
//-----------------------------------------------------------------------------
// Purpose: An item that knows how to read itself from a datafile, describe itself to the user,
// and serialize itself between Servers, Clients, and Steam.
//
// In the client DLL, we derive it from CDefaultClientRenderable so that
// it can be passed in the pProxyData parameter of material proxies.
//-----------------------------------------------------------------------------
#if defined(CLIENT_DLL)
class CEconItemView : public CDefaultClientRenderable, public IEconItemInterface, public CCustomMaterialOwner
#else
class CEconItemView : public IEconItemInterface
#endif
{
#if defined(CLIENT_DLL) || defined(GAME_DLL)
DECLARE_CLASS_NOBASE( CEconItemView );
public:
DECLARE_EMBEDDED_NETWORKVAR();
DECLARE_DATADESC();
#endif
public:
CEconItemView();
CEconItemView( const CEconItemView &src );
virtual ~CEconItemView();
CEconItemView& operator=( const CEconItemView &src );
bool operator==( const CEconItemView &other ) const;
bool operator!=( const CEconItemView &other ) const { return !operator==( other ); }
virtual const GameItemDefinition_t *GetItemDefinition() const
{
return GetStaticData();
}
public:
// IEconItemInterface implementation.
virtual int32 GetQuality() const;
virtual int32 GetRarity() const;
virtual style_index_t GetStyle() const;
virtual uint8 GetFlags() const;
virtual eEconItemOrigin GetOrigin() const;
virtual uint16 GetQuantity() const;
virtual const char *GetCustomName() const;
virtual const char *GetCustomDesc() const;
virtual int GetItemSetIndex() const;
virtual bool GetInUse() const { return GetSOCData() ? GetSOCData()->GetInUse() : false; }
virtual void IterateAttributes( class IEconItemAttributeIterator *pIterator ) const OVERRIDE;
bool IsValid( void ) const { return m_bInitialized; }
void Invalidate( void );
// Initialize from the specified data
// client will load SO cache as needed
void Init( int iDefIndex, int iQuality, int iLevel, uint32 iAccountID = 0 );
void SetInitialized( bool bInit ) { m_bInitialized = bInit; }
bool Init( CEconItem* pItem );
// Get the static data contained in this item's definition
const GameItemDefinition_t *GetStaticData( void ) const;
void SetNonSOEconItem( CEconItem* pItem ) { m_pNonSOEconItem = pItem; }
void MarkDescriptionDirty( void );
virtual bool IsStyleUnlocked( int iStyle ) const;
private:
void EnsureDescriptionIsBuilt( void ) const;
public:
void SetGrayedOutReason( const char *pszGrayedOutReason );
// Set & Get the index of this item's definition inside the script file
void SetItemIndex( item_definition_index_t iIndex ) { m_iItemDefinitionIndex = iIndex; MarkDescriptionDirty(); }
item_definition_index_t GetItemIndex( void ) const { return m_iItemDefinitionIndex; }
// Set & Get the quality & level of this item.
void SetItemQuality( int iQuality ) { m_iEntityQuality = iQuality; MarkDescriptionDirty(); }
int GetItemQuality( void ) const { return m_iEntityQuality; }
void SetItemLevel( uint32 unLevel ) { m_iEntityLevel = unLevel; MarkDescriptionDirty(); }
uint32 GetItemLevel( void ) const { return m_iEntityLevel; }
int GetItemQuantity() const;
#ifdef CLIENT_DLL
void SetIsStoreItem( bool bIsStoreItem ) { m_bIsStoreItem = bIsStoreItem; MarkDescriptionDirty(); }
void SetIsTradeItem( bool bIsTradeItem ) { m_bIsTradeItem = bIsTradeItem; MarkDescriptionDirty(); }
void SetItemQuantity( int iQuantity ) { m_iEntityQuantity = iQuantity; MarkDescriptionDirty(); }
void SetClientItemFlags( uint8 unFlags );
void SetItemRarityOverride( int iRarity ) { m_iRarityOverride = iRarity; MarkDescriptionDirty(); }
void SetItemQualityOverride( int iQuality ) { m_iQualityOverride = iQuality; MarkDescriptionDirty(); }
void SetItemStyleOverride( style_index_t unNewStyleOverride );
#endif
style_index_t GetItemStyle() const;
// Access the worldwide global index of this item
void SetItemID( itemid_t iIdx ) { m_iItemID = iIdx; m_iItemIDHigh = (m_iItemID >> 32); m_iItemIDLow = (m_iItemID & 0xFFFFFFFF); }
#ifdef CLIENT_DLL
// On the client, we need to rebuild it from the high & low networked pieces
virtual itemid_t GetItemID( void ) const { uint64 iTmp = ((((int64)m_iItemIDHigh)<<32) | m_iItemIDLow); return (itemid_t)iTmp; }
#else
itemid_t GetItemID( void ) const { return m_iItemID; }
#endif
uint32 GetItemIDHigh( void ) const { return m_iItemIDHigh; }
uint32 GetItemIDLow( void ) const { return m_iItemIDLow; }
itemid_t GetFauxItemIDFromDefinitionIndex( void ) const;
uint32 GetAccountID( void ) const { return m_iAccountID; }
// Access the inventory position of this item
void SetInventoryPosition( uint32 iPosition ) { m_iInventoryPosition = iPosition; }
const uint32 GetInventoryPosition( void ) const { return m_iInventoryPosition; }
// Return the model to use for model panels containing this item
const char *GetInventoryModel( void );
// Return the image to use for model panels containing this item
const char *GetInventoryImage( void ) const;
bool HasGeneratedInventoryImage( void ) const;
bool GetInventoryImageData( int *iPosition, int *iSize );
const char *GetInventoryOverlayImage( int idx );
int GetInventoryOverlayImageCount( void );
IMaterial *GetToolStickerMaterial( void );
bool IsStickerTool( void );
// Return the model to use when displaying this model on the player character model, if any
const char *GetPlayerDisplayModel( int iClass = 0 ) const;
// Return the model to use when displaying this model in the world. See the notes on this in econ_item_schema.h
const char *GetWorldDisplayModel();
const char *GetExtraWearableModel();
const char *GetIconDisplayModel();
const char *GetBuyMenuDisplayModel();
const char *GetWorldDroppedModel();
const char *GetPedestalDisplayModel();
const char *GetMagazineModel();
// A piece of geometry that masks the scope lens out of the full-screen zoomed blur effect
const char *GetScopeLensMaskModel();
// Return the viewmodel stattrak module model path
const char *GetStatTrakModelByType( int nStatTrakType );
// Return the viewmodel uid module model path
const char *GetUidModel();
// Return the load-out slot that this item must be placed into
int GetAnimationSlot( void );
// Return an int that indicates whether the item should be dropped from a dead owner.
int GetDropType( void );
// Remove all attributes on this item
void DestroyAllAttributes( void );
// Add an attribute to this item
void AddAttribute( CEconItemAttribute *pAttribute );
void SetOrAddAttributeValueByName( const char *pszAttribDefName, float flValue );
void InitNetworkedDynamicAttributesForDemos( void );
void UpdateNetworkedDynamicAttributesForDemos( attrib_definition_index_t nDef, float flNewValue );
#if defined(CSTRIKE_CLIENT_DLL)
void UpdateGeneratedMaterial( bool bIgnorePicMip = false, CompositeTextureSize_t diffuseTextureSize = COMPOSITE_TEXTURE_SIZE_512 );
#endif //#if defined(CSTRIKE_CLIENT_DLL)
// Return the sticker model path for the given index
const char *GetStickerSlotModelBySlotIndex( int nIndex );
int GetNumSupportedStickerSlots( void );
Vector GetStickerSlotWorldProjectionStartBySlotIndex( int nIndex );
Vector GetStickerSlotWorldProjectionEndBySlotIndex( int nIndex );
const char *GetStickerWorldModelBoneParentNameBySlotIndex( int nIndex );
const char *GetStickerSlotMaterialBySlotIndex( int nIndex );
IMaterial *GetStickerIMaterialBySlotIndex( int nIndex, bool bThirdPerson = false );
void GenerateStickerMaterials( void );
bool ItemHasAnyStickersApplied( void );
bool ItemHasAnyFreeStickerSlots( void );
int GetStickerSlotFirstFreeFromIndex( int nIndex = 0 );
void SetCustomNameOverride( const char *pszCustomName );
// These functions are used by the client, as well as the server (in cs_gamestats.cpp)
virtual void GenerateKillEaterTypeVector( void );
virtual void GetKillEaterTypes( CUtlSortVector<uint32> &types );
virtual int32 GetKillEaterValueByType( uint32 uKillEaterType );
bool m_bKillEaterTypesCached;
CUtlSortVector<uint32> m_vCachedKillEaterTypes;
int m_nKillEaterValuesCacheFrame;
CUtlHashtable<uint32, int32> m_vCachedKillEaterValues;
private:
void Cleanup( void );
#if defined(CSTRIKE_CLIENT_DLL)
// create custom materials based on the custom attributes
void CreateCustomWeaponMaterials( int nWeaponId, bool bIgnorePicMip, CompositeTextureSize_t diffuseTextureSize = COMPOSITE_TEXTURE_SIZE_512 );
void CreateCustomClothingMaterials( const char *pchSkinIdent, int nSlotId, int nTeam, bool bIgnorePicMip, CompositeTextureSize_t diffuseTextureSize = COMPOSITE_TEXTURE_SIZE_512 );
public:
void Update( void );
void SaveInventoryImageAsPNG( int nWidth, int nHeight );
const CUtlBuffer *GetInventoryImageRgba( int nWidth, int nHeight, ImageReadyCallback_t pImageReadyCallback );
bool CanGenerateInventoryImageRgba( void );
void ClearInventoryImageRgba( void );
bool LoadCachedInventoryImage( void );
void SaveInventoryImage( CUtlBuffer &rawImageRgba );
void GenerateCachedInventoryImageName();
static void CleanInventoryImageCacheDir( void );
void FinishLoadCachedInventoryImage( void* pData, int numReadBytes, FSAsyncStatus_t asyncStatus );
enum AsyncFixupState_t
{
AFS_Init, // Initial state, need to load data
AFS_LoadingInProgress, // Async load kicked-off on job thread
AFS_LoadingDone, // Async load done, data ready for fixup on main thread
AFS_FixupDone, // Data fixed up on main thread
} m_asyncFixupState;
int m_nNumAsyncReadBytes;
FSAsyncStatus_t m_asyncStatus;
CUtlBuffer m_inventoryImageRgba;
private:
static bool m_sbHasCleanedInventoryImageCacheDir;
bool m_bInventoryImageRgbaRequested;
bool m_bInventoryImageTriedCache;
ImageReadyCallback_t m_pImageReadyCallback;
int m_nInventoryImageRgbaWidth;
int m_nInventoryImageRgbaHeight;
FSAsyncControl_t m_hAsyncControl;
char m_szCurrentLoadCachedFileName[ MAX_PATH ];
RenderToRTData_t *m_pRenderToRTData;
IVTFTexture *m_pScratchVTF;
CMergedMDL *m_pRenderToRTMDL;
#endif //#if defined(CSTRIKE_CLIENT_DLL)
CUtlVector< stickerMaterialReference_t > m_pStickerMaterials;
// Remove an attribute by name
void RemoveAttribute( const char *pszAttribDefName );
public:
const bool GetCombinedAttributeClassValue( float &flValue, string_t iszAttribClass ) const;
// Returns the attribute matching the specified class, carried by this entity, if it exists.
CEconItemAttribute *GetAttributeByClass( const char *szAttribClass );
const CEconItemAttribute *GetAttributeByClass( const char *szAttribClass ) const;
// Returns the attribute that matches the attribute def index, if it exists
CEconItemAttribute *GetAttributeByDefIndex( int iAttributeDefIndex );
const CEconItemAttribute *GetAttributeByDefIndex( int iAttributeDefIndex ) const;
// Returns the attribute that matches the def name, if it exists
CEconItemAttribute *GetAttributeByName( const char *pszAttribDefName );
const CEconItemAttribute *GetAttributeByName( const char *pszAttribDefName ) const;
// Attribute accessing
int GetNumAttributes( void ) const { return m_AttributeList.GetNumAttributes(); }
CEconItemAttribute *GetAttribute( int iIndex ) { return m_AttributeList.GetAttribute( iIndex ); }
const CEconItemAttribute *GetAttribute( int iIndex ) const { return m_AttributeList.GetAttribute( iIndex ); }
CAttributeList *GetAttributeList( void ) { return m_AttributeList.Get(); }
const CAttributeList *GetAttributeList( void ) const { return m_AttributeList.Get(); }
// Items that have attributes that modify their RGB values
int GetModifiedRGBValue( bool bAltColor=false );
int GetCustomPaintKitIndex( void ) const;
const char* GetCustomPaintKitDbgName( void ) const;
// Returns true if subject is a part of this item's collection set and is not yet collected.
bool CanCollect( CEconItemView &subject );
// Returns the UGC file ID of the custom texture assigned to this item. If non-zero, then it has a custom texture.
uint64 GetCustomUserTextureID();
const CPaintKit *GetCustomPaintKit( void ) const;
CEconItem *GetSOCData( void ) const;
bool IsEquipped( void ) const { return GetSOCData() && GetSOCData()->IsEquipped(); }
bool IsEquippedForClass( equipped_class_t unClass ) const { return GetSOCData() && GetSOCData()->IsEquippedForClass( unClass ); }
void UpdateEquippedState( equipped_class_t unClass, equipped_slot_t unSlot ) { if ( GetSOCData() ) { GetSOCData()->UpdateEquippedState( unClass, unSlot ); } }
equipped_slot_t GetEquippedPositionForClass( equipped_class_t unClass ) const { return GetSOCData() ? GetSOCData()->GetEquippedPositionForClass( unClass ) : INVALID_EQUIPPED_SLOT; }
EItemSlot GetSlot( void ) const { return EItemSlotFromName( GetItemDefinition()->GetRawDefinition()->GetString("item_slot") ); }
// Attached particle systems
int GetQualityParticleType();
int GetSkin() const;
#if defined(CSTRIKE_CLIENT_DLL)
IVisualsDataProcessor *GetVisualsDataProcessor( int nIndex ) { return ( nIndex < m_ppVisualsDataProcessors.Count() ) ? m_ppVisualsDataProcessors[ nIndex ] : NULL; }
IVisualsDataProcessor *GetVisualsDataProcessorByName( const char* szName ) const;
static CEconItemView * FindOrCreateEconItemViewForItemID( uint64 uiItemId );
#else
typedef CUtlMap< itemid_t, uint64, int, CDefLess< itemid_t > > UtlMapLookupByID_t;
static UtlMapLookupByID_t s_mapLookupByID;
#endif
#if defined ( GAME_DLL )
void UpdateNetworkedCustomName();
#endif
protected:
// Index of the item definition in the item script file.
CNetworkVar( item_definition_index_t, m_iItemDefinitionIndex );
// The quality of this item.
CNetworkVar( int, m_iEntityQuality );
// The level of this item.
CNetworkVar( uint32, m_iEntityLevel );
// The global index of this item, worldwide.
itemid_t m_iItemID;
CNetworkVar( uint32, m_iItemIDHigh );
CNetworkVar( uint32, m_iItemIDLow );
// Account ID of the person who has this in their inventory
CNetworkVar( uint32, m_iAccountID );
// Position inside the player's inventory
CNetworkVar( uint32, m_iInventoryPosition );
// This is an alternate source of data, if this item models something that isn't in the SO cache.
CEconItem* m_pNonSOEconItem;
CNetworkVar( bool, m_bInitialized );
#if defined( CLIENT_DLL )
// exist on the client only
bool m_bIsStoreItem;
bool m_bIsTradeItem;
int m_iEntityQuantity;
int m_iRarityOverride;
int m_iQualityOverride;
uint8 m_unClientFlags;
// clients have the ability to force a style on an item view -- this is used for store previews,
// character panels, etc.
style_index_t m_unOverrideStyle;
public:
// Return the single-line name of this item.
const wchar_t *GetItemName( bool bUncustomized = false ) const;
// Return the full structure with all of our description lines.
const class CEconItemDescription *GetDescription() const { EnsureDescriptionIsBuilt(); return m_pDescription; }
private:
mutable class CEconItemDescription *m_pDescription;
mutable char *m_pszGrayedOutReason;
#endif
#if defined(CSTRIKE_CLIENT_DLL)
CUtlVector< IVisualsDataProcessor* > m_ppVisualsDataProcessors;
#endif
protected:
#if defined(CLIENT_DLL)
// IClientRenderable
virtual const Vector& GetRenderOrigin( void ) { return vec3_origin; }
virtual const QAngle& GetRenderAngles( void ) { return vec3_angle; }
virtual bool ShouldDraw( void ) { return false; }
virtual bool IsTransparent( void ) { return false;}
virtual const matrix3x4_t &RenderableToWorldTransform() { static matrix3x4_t mat; SetIdentityMatrix( mat ); return mat; }
virtual void GetRenderBounds( Vector& mins, Vector& maxs ) { return; }
#endif
private:
CNetworkVarEmbedded( CAttributeList, m_AttributeList );
CNetworkVarEmbedded( CAttributeList, m_NetworkedDynamicAttributesForDemos );
// the above attribute lists store all attributes as floats... since we only have one string attribute
// we're networking it separately instead of doing the work to expand attribute lists to support string attrs.
CNetworkString( m_szCustomName, MAX_ITEM_CUSTOM_NAME_DATABASE_SIZE );
char m_szCustomNameOverride[ MAX_ITEM_CUSTOM_NAME_DATABASE_SIZE ];
GCSDK::CAutoPtr< char > m_autoptrInventoryImageGeneratedPath;
};
#endif // ECON_ITEM_CONSTANTS_H

View File

@@ -0,0 +1,90 @@
//====== Copyright c 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef ECON_ITEM_VIEW_HELPERS_H
#define ECON_ITEM_VIEW_HELPERS_H
#ifdef _WIN32
#pragma once
#endif
// These helpers are used to abstract away the distinction between inventory items with legitimate itemIDs
// and items that are expressed as definition index + paint index.
// returns an itemID that encodes the definition index and paint id
inline uint64 CombinedItemIdMakeFromDefIndexAndPaint( uint16 iDefIndex, uint16 iPaint, uint8 ub1 = 0 )
{
if ( iDefIndex == 0 && iPaint == 0 )
return 0;
else
return 0xF000000000000000ull | ( uint64( ub1 ) << 32 ) | ( uint64( iPaint ) << 16 ) | ( uint64( iDefIndex ) );
}
// Returns whether the itemID in question is really an encoded base item
inline bool CombinedItemIdIsDefIndexAndPaint( uint64 ullItemId )
{
return ullItemId >= 0xF000000000000000ull;
}
// Extracts the definition index from an encoded itemID
inline uint16 CombinedItemIdGetDefIndex( uint64 ullItemId )
{
return uint16( ullItemId );
}
// Extracts the paint index from an encoded itemID
inline uint16 CombinedItemIdGetPaint( uint64 ullItemId )
{
return uint16( ullItemId >> 16 );
}
// Extracts the extra byte from an encoded itemID
inline uint16 CombinedItemIdGetUB1( uint64 ullItemId )
{
return uint8( ullItemId >> 32 );
}
///////////////////////////////////////////////////////////////////////////
//
// Tint ID manipulators
//
// Fomat of the TintID int32 value from low bits towards high bits:
// low byte (TintID & 0xFF) = bucket containing HSV subspace definition
// ((TintID >> 8)&0x7F): 7-bits indicating hue location from minhue(0) to maxhue(0x7F) in the HSV subspace
// ((TintID >> 15)&0x7F): 7-bits indicating saturation location in hue-interpolated minsat(0) to maxsat(0x7F) range in the HSV subspace
// ((TintID >> 22)&0x7F): 7-bits indicating value location in hue-interpolated minval(0) to maxval(0x7F) range in the HSV subspace
// ((TintID >> 29)&0x7): 3-bits reserved (must be zero)
//
#if ECON_SPRAY_TINT_IDS_FLOAT_COLORSPACE
inline uint32 CombinedTintIDMakeFromIDHSVf( uint8 unID, float fH, float fS, float fV )
{
return
uint32( unID & 0xFF )
| ( ( uint32( fH * 0x7F ) & 0x7F ) << ( 8 + 7 * 0 ) )
| ( ( uint32( fS * 0x7F ) & 0x7F ) << ( 8 + 7 * 1 ) )
| ( ( uint32( fV * 0x7F ) & 0x7F ) << ( 8 + 7 * 2 ) )
;
}
inline uint32 CombinedTintIDMakeFromIDHSVu( uint8 unID, uint32 fH, uint32 fS, uint32 fV )
{
return
uint32( unID & 0xFF )
| ( ( uint32( fH ) & 0x7F ) << ( 8 + 7 * 0 ) )
| ( ( uint32( fS ) & 0x7F ) << ( 8 + 7 * 1 ) )
| ( ( uint32( fV ) & 0x7F ) << ( 8 + 7 * 2 ) )
;
}
inline float CombinedTintIDGetHSVc( uint32 unTintID, int c )
{
return ( ( unTintID >> ( 8 + 7 * c ) ) & 0x7F ) / float( 0x7F );
}
#endif
inline uint8 CombinedTintIDGetHSVID( uint32 unTintID )
{
return unTintID & 0xFF;
}
#endif // ECON_ITEM_VIEW_HELPERS_H

View File

@@ -0,0 +1,70 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef GAME_ITEM_SCHEMA_H
#define GAME_ITEM_SCHEMA_H
#ifdef _WIN32
#pragma once
#endif
#if defined(TF_CLIENT_DLL) || defined(TF_DLL) || defined(TF_GC_DLL)
// TF
class CTFItemSchema;
class CTFItemDefinition;
class CTFItemSystem;
typedef CTFItemSchema GameItemSchema_t;
typedef CTFItemDefinition GameItemDefinition_t;
typedef CTFItemSystem GameItemSystem_t;
#include "tf_item_schema.h"
#elif defined( DOTA_CLIENT_DLL ) || defined( DOTA_DLL ) || defined ( DOTA_GC_DLL )
// DOTA
class CDOTAItemSchema;
class CDOTAItemDefinition;
class CDOTAItemSystem;
typedef CDOTAItemSchema GameItemSchema_t;
typedef CDOTAItemDefinition GameItemDefinition_t;
typedef CDOTAItemSystem GameItemSystem_t;
#include "econ/dota_item_schema.h"
#elif defined( PORTAL2 ) || defined( PORTAL2_GC_DLL )
// PORTAL2
class CPortal2ItemSchema;
class CPortal2ItemDefinition;
class CPortal2ItemSystem;
typedef CPortal2ItemSchema GameItemSchema_t;
typedef CPortal2ItemDefinition GameItemDefinition_t;
typedef CPortal2ItemSystem GameItemSystem_t;
#include "portal2_item_schema.h"
#elif defined( CSTRIKE15 ) || defined( CSTRIKE_GC_DLL )
class CCStrike15ItemSchema;
class CCStrike15ItemDefinition;
class CCStrike15ItemSystem;
typedef CCStrike15ItemSchema GameItemSchema_t;
typedef CCStrike15ItemDefinition GameItemDefinition_t;
typedef CCStrike15ItemSystem GameItemSystem_t;
#include "cstrike15_item_schema.h"
#else
// Fallback Case
class CEconItemSchema;
class CEconItemDefinition;
class CEconItemSystem;
typedef CEconItemSchema GameItemSchema_t;
typedef CEconItemDefinition GameItemDefinition_t;
typedef CEconItemSystem GameItemSystem_t;
#include "econ_item_schema.h"
#endif
extern GameItemSchema_t *GetItemSchema();
#endif // GAME_ITEM_SYSTEM_H

View File

@@ -0,0 +1,46 @@
//========= Copyright © 1996-2003, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef IHASATTRIBUTES_H
#define IHASATTRIBUTES_H
#ifdef _WIN32
#pragma once
#endif
//#include "attribute_manager.h"
class CAttributeManager;
class CAttributeContainer;
class CBaseEntity;
class CAttributeList;
// To allow an entity to have attributes, derive it from IHasAttributes and
// contain an CAttributeManager in it. Then:
// - Call InitializeAttributes() before your entity's Spawn()
// - Call AddAttribute() to add attributes to the entity
// - Call all the CAttributeManager hooks at the appropriate times in your entity.
// To get networking of the attributes to work on your entity:
// - Add this to your entity's send table:
// SendPropDataTable( SENDINFO_DT( m_AttributeManager ), &REFERENCE_SEND_TABLE(DT_AttributeManager) ),
// - Call this inside your entity's OnDataChanged():
// GetAttributeManager()->OnDataChanged( updateType );
//-----------------------------------------------------------------------------
// Purpose: Derive from this if your entity wants to contain attributes.
//-----------------------------------------------------------------------------
class IHasAttributes
{
public:
virtual CAttributeManager *GetAttributeManager( void ) = 0;
virtual CAttributeContainer *GetAttributeContainer( void ) = 0;
virtual CBaseEntity *GetAttributeOwner( void ) = 0;
virtual CAttributeList *GetAttributeList( void ) = 0;
// Reapply yourself to whoever you should be providing attributes to.
virtual void ReapplyProvision( void ) = 0;
};
#endif // IHASATTRIBUTES_H

View File

@@ -0,0 +1,24 @@
//========= Copyright © Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef IHASOWNER_H
#define IHASOWNER_H
#ifdef _WIN32
#pragma once
#endif
class CBaseEntity;
//-----------------------------------------------------------------------------
// Purpose: Allows an entity to access its owner regardless of entity type
//-----------------------------------------------------------------------------
class IHasOwner
{
public:
virtual CBaseEntity *GetOwnerViaInterface( void ) = 0;
};
#endif // IHASOWNER_H

View File

@@ -0,0 +1,544 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: CItemSelectionCriteria, which serves as a criteria for selection
// of a econ item
//
//=============================================================================
#include "cbase.h"
#include "item_selection_criteria.h"
#include "game_item_schema.h" // TODO: Fix circular dependency
#if defined(TF_CLIENT_DLL) || defined(TF_DLL)
#include "tf_gcmessages.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// copied from \common\econ_item_view.h
#define AE_USE_SCRIPT_VALUE 9999 // Can't be -1, due to unsigned ints used on the backend
using namespace GCSDK;
//-----------------------------------------------------------------------------
// Purpose: Copy Constructor
//-----------------------------------------------------------------------------
CItemSelectionCriteria::CItemSelectionCriteria( const CItemSelectionCriteria &that )
{
(*this) = that;
}
struct EmptyStruct_t
{
};
//-----------------------------------------------------------------------------
// Purpose: Operator=
//-----------------------------------------------------------------------------
CItemSelectionCriteria &CItemSelectionCriteria::operator=( const CItemSelectionCriteria &rhs )
{
// Leverage the serialization code we already have for the copy
CSOItemCriteria msgTemp;
rhs.BSerializeToMsg( msgTemp );
BDeserializeFromMsg( msgTemp );
return *this;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CItemSelectionCriteria::~CItemSelectionCriteria( void )
{
m_vecConditions.PurgeAndDeleteElements();
}
const char *CItemSelectionCriteria::GetValueForFirstConditionOfFieldName( const char *pchName ) const
{
FOR_EACH_VEC( m_vecConditions, i )
{
if ( V_strcmp( m_vecConditions[i]->GetField(), pchName ) == 0 )
return m_vecConditions[i]->GetValue();
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Initialize from a KV structure
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BInitFromKV( KeyValues *pKVCriteria, const CEconItemSchema &pschema )
{
// Read in the base fields
if ( pKVCriteria->FindKey( "level" ) )
{
SetItemLevel( pKVCriteria->GetInt( "level" ) );
}
if ( pKVCriteria->FindKey( "quality" ) )
{
uint8 nQuality;
if ( !pschema.BGetItemQualityFromName( pKVCriteria->GetString( "quality" ), &nQuality ) )
return false;
SetQuality( nQuality );
}
if ( pKVCriteria->FindKey( "rarity" ) )
{
uint8 nRarity;
if ( !pschema.BGetItemRarityFromName( pKVCriteria->GetString( "rarity" ), &nRarity ) )
return false;
SetRarity( nRarity );
}
if ( pKVCriteria->FindKey( "inventoryPos" ) )
{
SetInitialInventory( pKVCriteria->GetInt( "inventoryPos" ) );
}
if ( pKVCriteria->FindKey( "quantity" ) )
{
SetInitialQuantity( pKVCriteria->GetInt( "quantity" ) );
}
if ( pKVCriteria->FindKey( "ignore_enabled" ) )
{
SetIgnoreEnabledFlag( pKVCriteria->GetBool( "ignore_enabled" ) );
}
if ( pKVCriteria->FindKey( "recent_only" ) )
{
SetRecentOnly( pKVCriteria->GetBool( "recent_only" ) );
}
return true;
}
bool CItemSelectionCriteria::BInitFromItemAndPaint( int nItemDef, int nPaintID, const CEconItemSchema &schemaa )
{
/** Removed for partner depot **/
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Adds a condition to the selection criteria
// Input: pszField - Field to evaluate on
// eOp - Operator to apply to the value of the field
// flValue - The value to compare.
// bRequired - When true, causes BEvauluate to fail if pszField doesn't
// exist in the KV being checked.
// Output: True if the condition was added, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BAddCondition( const char *pszField, EItemCriteriaOperator eOp, float flValue, bool bRequired )
{
// Check for condition limit
if ( UCHAR_MAX == GetConditionsCount() )
{
AssertMsg( false, "Too many conditions on a a CItemSelectionCriteria. Max: 255" );
return false;
}
// Enforce maximum string lengths
if ( Q_strlen( pszField ) >= k_cchCreateItemLen )
return false;
if ( V_strcmp( pszField, "*lootlist" ) == 0 )
{
m_bIsLootList = true;
}
// Create the appropriate condition for the operator
switch ( eOp )
{
case k_EOperator_Float_EQ:
case k_EOperator_Float_Not_EQ:
case k_EOperator_Float_LT:
case k_EOperator_Float_Not_LT:
case k_EOperator_Float_LTE:
case k_EOperator_Float_Not_LTE:
case k_EOperator_Float_GT:
case k_EOperator_Float_Not_GT:
case k_EOperator_Float_GTE:
case k_EOperator_Float_Not_GTE:
m_vecConditions.AddToTail( new CFloatCondition( pszField, eOp, flValue, bRequired ) );
return true;
default:
AssertMsg1( false, "Bad operator (%d) passed to BAddCondition. Float based operator required for this overload.", eOp );
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: Adds a condition to the selection criteria
// Input: pszField - Field to evaluate on
// eOp - Operator to apply to the value of the field
// pszValue - The value to compare.
// bRequired - When true, causes BEvauluate to fail if pszField doesn't
// exist in the KV being checked.
// Output: True if the condition was added, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BAddCondition( const char *pszField, EItemCriteriaOperator eOp, const char * pszValue, bool bRequired )
{
// Check for condition limit
if ( UCHAR_MAX == GetConditionsCount() )
{
AssertMsg( false, "Too many conditions on a a CItemSelectionCriteria. Max: 255" );
return false;
}
// Enforce maximum string lengths
if ( V_strlen( pszField ) >= k_cchCreateItemLen || Q_strlen( pszValue ) >= k_cchCreateItemLen )
return false;
if ( V_strcmp( pszField, "*lootlist" ) == 0 )
{
m_bIsLootList = true;
}
// Create the appropriate condition for the operator
switch ( eOp )
{
case k_EOperator_String_EQ:
case k_EOperator_String_Not_EQ:
m_vecConditions.AddToTail( new CStringCondition( pszField, eOp, pszValue, bRequired ) );
return true;
case k_EOperator_Subkey_Contains:
case k_EOperator_Subkey_Not_Contains:
m_vecConditions.AddToTail( new CSetCondition( pszField, eOp, pszValue, bRequired ) );
return true;
default:
// Try the float operators
return BAddCondition( pszField, eOp, Q_atof( pszValue ), bRequired );
}
}
//-----------------------------------------------------------------------------
// Purpose: Checks if a given item matches the item selection criteria
// Input: itemDef - The item definition to evaluate against
// Output: True is the item passes the filter, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BEvaluate( const CEconItemDefinition* pItemDef, const CEconItemSchema &pschema ) const
{
// Disabled items never match
if ( !m_bIgnoreEnabledFlag && !pItemDef->BEnabled() )
return false;
if ( m_bRecentOnly && !pItemDef->IsRecent() )
return false;
// Filter against level
if ( BItemLevelSet() && (GetItemLevel() != AE_USE_SCRIPT_VALUE) &&
( GetItemLevel() < pItemDef->GetMinLevel() || GetItemLevel() > pItemDef->GetMaxLevel() ) )
return false;
// Filter against quality
if ( BQualitySet() && (GetQuality() != AE_USE_SCRIPT_VALUE) )
{
if ( GetQuality() != pItemDef->GetQuality() )
{
// Filter out item defs that have a non-any quality if we have a non-matching & non-any quality criteria
if ( k_unItemQuality_Any != GetQuality() &&
k_unItemQuality_Any != pItemDef->GetQuality() )
return false;
// Filter out item defs that don't have our exact quality if our quality criteria requires explicit matches
const CEconItemQualityDefinition *pQuality = pschema.GetQualityDefinition( GetQuality() );
if ( m_bForcedQualityMatch || ( pQuality && pQuality->GetRequiresExplicitMatches() ) )
return false;
}
}
// Filter against the additional conditions
FOR_EACH_VEC( m_vecConditions, i )
{
// Skip over dynamic fields that require special logic from an econitem to process
if ( m_vecConditions[i]->GetField()[ 0 ] == '*' )
continue;
if ( !m_vecConditions[i]->BEvaluate( pItemDef->GetRawDefinition() ) )
return false;
}
return true;
}
bool CItemSelectionCriteria::BEvaluate( const CEconItem *pItem, const CEconItemSchema &pschema ) const
{
const CEconItemDefinition *pItemDef = pItem->GetItemDefinition();
if ( !BEvaluate( pItemDef, pschema ) )
return false;
// Filter against the dynamic conditions
FOR_EACH_VEC( m_vecConditions, i )
{
// Skip over dynamic fields that require special logic from an econitem to process
const char *pchCondition = m_vecConditions[i]->GetField();
if ( pchCondition[ 0 ] != '*' )
continue;
pchCondition++;
if ( V_strcmp( pchCondition, "rarity" ) == 0 )
{
const CEconItemRarityDefinition *pRarity = pschema.GetRarityDefinitionByName( m_vecConditions[i]->GetValue() );
Assert( pRarity );
if ( m_vecConditions[i]->GetEOp() == k_EOperator_Not || m_vecConditions[i]->GetEOp() == k_EOperator_String_Not_EQ )
{
if ( pItem->GetRarity() == pRarity->GetDBValue() )
return false;
}
else
{
if ( pItem->GetRarity() != pRarity->GetDBValue() )
return false;
}
}
else if ( V_strcmp( pchCondition, "quality" ) == 0 )
{
const CEconItemQualityDefinition *pQuality = pschema.GetQualityDefinitionByName( m_vecConditions[i]->GetValue() );
Assert( pQuality );
if ( m_vecConditions[i]->GetEOp() == k_EOperator_Not || m_vecConditions[i]->GetEOp() == k_EOperator_String_Not_EQ )
{
if ( pItem->GetQuality() == pQuality->GetDBValue() )
return false;
}
else
{
if ( pItem->GetQuality() != pQuality->GetDBValue() )
return false;
}
}
else if ( V_strcmp( pchCondition, "itemdef" ) == 0 )
{
if ( pItemDef->GetDefinitionIndex() != V_atoi( m_vecConditions[i]->GetValue() ) )
return false;
}
else if ( V_strcmp( pchCondition, "paintkit" ) == 0 )
{
if ( pItem->GetCustomPaintKitIndex() != V_atoi( m_vecConditions[i]->GetValue() ) )
return false;
}
else if ( V_strcmp( pchCondition, "kill_eater_score_type" ) == 0 )
{
static const CSchemaAttributeDefHandle pAttr_KillEaterScoreType( "kill eater score type" );
attrib_value_t unKillEaterScoreType;
bool bHasKillEaterScoreType = pItem->FindAttribute( pAttr_KillEaterScoreType, &unKillEaterScoreType );
if ( !bHasKillEaterScoreType || unKillEaterScoreType != (uint32)V_atoi( m_vecConditions[ i ]->GetValue() ) )
{
return false;
}
}
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Determines if the item matches this condition of the criteria
// Input: pKVItem - Pointer to the raw KeyValues definition of the item
// Output: True is the item matches, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::CCondition::BEvaluate( KeyValues *pKVItem ) const
{
KeyValues *pKVField = pKVItem->FindKey( m_sField.String() );
// Treat an empty string as a missing field as well.
bool bIsEmptyString = false;
if ( m_EOp == k_EOperator_String_EQ || m_EOp == k_EOperator_String_Not_EQ )
{
const char *pszItemVal = pKVField ? pKVField->GetString() : NULL;
bIsEmptyString = ( pszItemVal == NULL || pszItemVal[0] == '\0' );
}
// Deal with missing fields
if ( NULL == pKVField || bIsEmptyString )
{
if ( m_bRequired )
return false;
else
return true;
}
// Run the operator specific check
bool bRet = BInternalEvaluate( pKVItem );
// If this is a "not" operator, reverse the result
if ( m_EOp & k_EOperator_Not )
return !bRet;
else
return bRet;
}
//-----------------------------------------------------------------------------
// Purpose: Runs the operator specific check for this condition
// Input: pKVItem - Pointer to the raw KeyValues definition of the item
// Output: True is the item matches, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::CStringCondition::BInternalEvaluate( KeyValues *pKVItem ) const
{
Assert( k_EOperator_String_EQ == m_EOp || k_EOperator_String_Not_EQ == m_EOp );
if( !( k_EOperator_String_EQ == m_EOp || k_EOperator_String_Not_EQ == m_EOp ) )
return false;
const char *pszItemVal = pKVItem->GetString( m_sField.String() );
return ( 0 == Q_stricmp( m_sValue.String(), pszItemVal ) );
}
bool CItemSelectionCriteria::CStringCondition::BSerializeToMsg( CSOItemCriteriaCondition & msg ) const
{
CCondition::BSerializeToMsg( msg );
msg.set_string_value( m_sValue.Get() );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Runs the operator specific check for this condition
// Input: pKVItem - Pointer to the raw KeyValues definition of the item
// Output: True is the item matches, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::CSetCondition::BInternalEvaluate( KeyValues *pKVItem ) const
{
Assert( k_EOperator_Subkey_Contains == m_EOp || k_EOperator_Subkey_Not_Contains == m_EOp );
if( !( k_EOperator_Subkey_Contains == m_EOp || k_EOperator_Subkey_Not_Contains == m_EOp ) )
return false;
return ( NULL != pKVItem->FindKey( m_sField.String() )->FindKey( m_sValue.String() ) );
}
bool CItemSelectionCriteria::CSetCondition::BSerializeToMsg( CSOItemCriteriaCondition & msg ) const
{
CCondition::BSerializeToMsg( msg );
msg.set_string_value( m_sValue.Get() );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Runs the operator specific check for this condition
// Input: pKVItem - Pointer to the raw KeyValues definition of the item
// Output: True is the item matches, false otherwise
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::CFloatCondition::BInternalEvaluate( KeyValues *pKVItem ) const
{
float itemValue = pKVItem->GetFloat( m_sField.String() );
switch ( m_EOp )
{
case k_EOperator_Float_EQ:
case k_EOperator_Float_Not_EQ:
return ( itemValue == m_flValue );
case k_EOperator_Float_LT:
case k_EOperator_Float_Not_LT:
return ( itemValue < m_flValue );
case k_EOperator_Float_LTE:
case k_EOperator_Float_Not_LTE:
return ( itemValue <= m_flValue );
case k_EOperator_Float_GT:
case k_EOperator_Float_Not_GT:
return ( itemValue > m_flValue );
case k_EOperator_Float_GTE:
case k_EOperator_Float_Not_GTE:
return ( itemValue >= m_flValue );
default:
AssertMsg1( false, "Unknown operator: %d", m_EOp );
return false;
}
}
bool CItemSelectionCriteria::CFloatCondition::BSerializeToMsg( CSOItemCriteriaCondition & msg ) const
{
CCondition::BSerializeToMsg( msg );
msg.set_float_value( m_flValue );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Serialize the item selection criteria to the given message
// Input: msg - The message to serialize to.
// Output: True if the operation was successful, false otherwise.
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BSerializeToMsg( CSOItemCriteria & msg ) const
{
msg.set_item_level( m_unItemLevel );
msg.set_item_quality( m_nItemQuality );
msg.set_item_rarity( m_nItemRarity );
msg.set_item_level_set( m_bItemLevelSet );
msg.set_item_quality_set( m_bQualitySet );
msg.set_item_rarity_set( m_bRaritySet );
msg.set_initial_inventory( m_unInitialInventory );
msg.set_initial_quantity( m_unInitialQuantity );
msg.set_ignore_enabled_flag( m_bIgnoreEnabledFlag );
msg.set_recent_only( m_bRecentOnly );
FOR_EACH_VEC( m_vecConditions, i )
{
CSOItemCriteriaCondition *pConditionMsg = msg.add_conditions();
m_vecConditions[i]->BSerializeToMsg( *pConditionMsg );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Deserializes the item selection criteria from the given message
// Input: msg - The message to deserialize from.
// Output: True if the operation was successful, false otherwise.
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::BDeserializeFromMsg( const CSOItemCriteria & msg )
{
m_unItemLevel = msg.item_level();
m_nItemQuality = msg.item_quality();
m_nItemRarity = msg.item_rarity();
m_bItemLevelSet = msg.item_level_set();
m_bQualitySet = msg.item_quality_set();
m_bRaritySet = msg.item_rarity_set();
m_unInitialInventory = msg.initial_inventory();
m_unInitialQuantity = msg.initial_quantity();
m_bIgnoreEnabledFlag = msg.ignore_enabled_flag();
m_bRecentOnly = msg.recent_only();
uint32 unCount = msg.conditions_size();
m_vecConditions.EnsureCapacity( unCount );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Serializes a condition to a message.
// Input: msg - The message to serialize to.
// Output: True if the operation was successful, false otherwise.
//-----------------------------------------------------------------------------
bool CItemSelectionCriteria::CCondition::BSerializeToMsg( CSOItemCriteriaCondition & msg ) const
{
msg.set_op( m_EOp );
msg.set_field( m_sField.String() );
msg.set_required( m_bRequired );
return true;
}

View File

@@ -0,0 +1,267 @@
//====== Copyright ©, Valve Corporation, All rights reserved. =======
//
// Purpose: CItemSelectionCriteria, which serves as a criteria for selection
// of a econ item
//
//=============================================================================
#ifndef ITEM_SELECTION_CRITERIA_H
#define ITEM_SELECTION_CRITERIA_H
#ifdef _WIN32
#pragma once
#endif
#include "game_item_schema.h"
// Maximum string length in item create APIs
const int k_cchCreateItemLen = 64;
// Operators for BAddNewItemCriteria
enum EItemCriteriaOperator
{
k_EOperator_String_EQ = 0, // Field is string equal to value
k_EOperator_Not = 1, // Logical not
k_EOperator_String_Not_EQ = 1, // Field is not string equal to value
k_EOperator_Float_EQ = 2, // Field as a float is equal to value
k_EOperator_Float_Not_EQ = 3, // Field as a float is not equal to value
k_EOperator_Float_LT = 4, // Field as a float is less than value
k_EOperator_Float_Not_LT = 5, // Field as a float is not less than value
k_EOperator_Float_LTE = 6, // Field as a float is less than or equal value
k_EOperator_Float_Not_LTE = 7, // Field as a float is not less than or equal value
k_EOperator_Float_GT = 8, // Field as a float is greater than value
k_EOperator_Float_Not_GT = 9, // Field as a float is not greater than value
k_EOperator_Float_GTE = 10, // Field as a float is greater than or equal value
k_EOperator_Float_Not_GTE = 11, // Field as a float is not greater than or equal value
k_EOperator_Subkey_Contains = 12, // Field contains value as a subkey
k_EOperator_Subkey_Not_Contains = 13, // Field does not contain value as a subkey
// Must be last
k_EItemCriteriaOperator_Count = 14,
};
EItemCriteriaOperator EItemCriteriaOperatorFromName( const char *pch );
const char *PchNameFromEItemCriteriaOperator( int eItemCriteriaOperator );
class CEconItemSchema;
class CEconItemDefinition;
class CEconItem;
class CSOItemCriteria;
class CSOItemCriteriaCondition;
const uint8 k_unItemRarity_Any = 0xF;
const uint8 k_unItemQuality_Any = 0xF;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CItemSelectionCriteria
// A class that contains all the conditions a server needs to specify what
// kind of random item they wish to generate.
//-----------------------------------------------------------------------------
class CItemSelectionCriteria
{
public:
// Constructors and destructor
CItemSelectionCriteria() :
m_bItemLevelSet( false ),
m_unItemLevel( 0 ),
m_bQualitySet( false ),
m_nItemQuality( k_unItemQuality_Any ),
m_bRaritySet( false ),
m_nItemRarity( k_unItemRarity_Any ),
m_unInitialInventory( 0 ),
m_unInitialQuantity( 1 ),
m_bForcedQualityMatch( false ),
m_bIgnoreEnabledFlag( false ),
m_bRecentOnly( false ),
m_bIsLootList( false )
{
}
CItemSelectionCriteria( const CItemSelectionCriteria &that );
CItemSelectionCriteria &operator=( const CItemSelectionCriteria& rhs );
~CItemSelectionCriteria();
// Accessors and Settors
bool BItemLevelSet( void ) const { return m_bItemLevelSet; }
uint32 GetItemLevel( void ) const { Assert( m_bItemLevelSet ); return m_unItemLevel; }
void SetItemLevel( uint32 unLevel ) { m_unItemLevel = unLevel; m_bItemLevelSet = true; }
bool BQualitySet( void ) const { return m_bQualitySet; }
int32 GetQuality( void ) const { Assert( m_bQualitySet ); return m_nItemQuality; }
void SetQuality( int32 nQuality ) { m_nItemQuality = nQuality; m_bQualitySet = true; }
bool BRaritySet( void ) const { return m_bRaritySet; }
int32 GetRarity( void ) const { Assert( m_bRaritySet ); return m_nItemRarity; }
void SetRarity( int32 nRarity ) { m_nItemRarity = nRarity; m_bRaritySet = true; }
uint32 GetInitialInventory( void ) const { return m_unInitialInventory; }
void SetInitialInventory( uint32 unInventory ) { m_unInitialInventory = unInventory; }
uint32 GetInitialQuantity( void ) const { return m_unInitialQuantity; }
void SetInitialQuantity( uint32 unQuantity ) { m_unInitialQuantity = unQuantity; }
void SetExplicitQualityMatch( bool bExplicit ) { m_bForcedQualityMatch = bExplicit; }
void SetIgnoreEnabledFlag( bool bIgnore ) { m_bIgnoreEnabledFlag = bIgnore; }
void SetRecentOnly( bool bCheck ) { m_bRecentOnly = bCheck; }
bool IsLootList( void ) const { return m_bIsLootList; }
// Add conditions to the criteria
bool BAddCondition( const char *pszField, EItemCriteriaOperator eOp, float flValue, bool bRequired );
bool BAddCondition( const char *pszField, EItemCriteriaOperator eOp, const char * pszValue, bool bRequired );
int GetConditionsCount() { return m_vecConditions.Count(); }
const char *GetValueForFirstConditionOfFieldName( const char *pchName ) const;
// Alternate ways of initializing
bool BInitFromKV( KeyValues *pKVCriteria, const CEconItemSchema &schemaa );
bool BInitFromItemAndPaint( int nItemDef, int nPaintID, const CEconItemSchema &schemaa );
// Serializes the criteria to and from messages
bool BSerializeToMsg( CSOItemCriteria & msg ) const;
bool BDeserializeFromMsg( const CSOItemCriteria & msg );
// Evaluates an item definition against this criteria. Returns true if
// the definition passes the filter
bool BEvaluate( const CEconItemDefinition* pItemDef, const CEconItemSchema &pschema ) const;
bool BEvaluate( const CEconItem *pItem, const CEconItemSchema &pschema ) const;
private:
//-----------------------------------------------------------------------------
// CItemSelectionCriteria::CCondition
// Represents one condition of the criteria
//-----------------------------------------------------------------------------
class CCondition
{
public:
CCondition( const char *pszField, EItemCriteriaOperator eOp, bool bRequired )
: m_sField( pszField ), m_EOp( eOp ), m_bRequired( bRequired )
{
}
virtual ~CCondition( ) { }
// Returns if the given KeyValues block passes this condition
// Performs common checks and calls BInternalEvaluate
bool BEvaluate( KeyValues *pKVItem ) const;
// Serializes the condition to the message
virtual bool BSerializeToMsg( CSOItemCriteriaCondition & msg ) const;
EItemCriteriaOperator GetEOp( void ) const { return m_EOp; }
virtual const char *GetField( void ) { return m_sField.Get(); }
virtual const char *GetValue( void ) { Assert(0); return NULL; }
protected:
// Returns true if applying the element's operator on m_sField of
// pKVItem returns true. This is only called if m_pszField exists in pKVItem
virtual bool BInternalEvaluate( KeyValues *pKVItem ) const = 0;
// The field of the raw KeyValue form of the item definition to check
CUtlString m_sField;
// The operator this clause uses
EItemCriteriaOperator m_EOp;
// When true, BEvaluate returns false if m_sField does not exist in pKVItem
bool m_bRequired;
};
//-----------------------------------------------------------------------------
// CItemSelectionCriteria::CStringCondition
// CCondition that handles the string-based operators
//-----------------------------------------------------------------------------
class CStringCondition : public CCondition
{
public:
CStringCondition( const char *pszField, EItemCriteriaOperator eOp, const char *pszValue, bool bRequired )
: CCondition( pszField, eOp, bRequired ), m_sValue( pszValue )
{
}
virtual ~CStringCondition( ) { }
virtual const char *GetValue( void ) { return m_sValue.Get(); }
protected:
virtual bool BInternalEvaluate( KeyValues *pKVItem ) const;
virtual bool BSerializeToMsg( CSOItemCriteriaCondition & msg ) const;
// The value to check against
CUtlString m_sValue;
};
//-----------------------------------------------------------------------------
// CItemSelectionCriteria::CFloatCondition
// CCondition that handles the float-based operators
//-----------------------------------------------------------------------------
class CFloatCondition : public CCondition
{
public:
CFloatCondition( const char *pszField, EItemCriteriaOperator eOp, float flValue, bool bRequired )
: CCondition( pszField, eOp, bRequired ), m_flValue( flValue )
{
}
virtual ~CFloatCondition( ) { }
protected:
virtual bool BInternalEvaluate( KeyValues *pKVItem ) const;
virtual bool BSerializeToMsg( CSOItemCriteriaCondition & msg ) const;
// The value to check against
float m_flValue;
};
//-----------------------------------------------------------------------------
// CItemSelectionCriteria::CSetCondition
// CCondition that handles subkey checks
//-----------------------------------------------------------------------------
class CSetCondition : public CCondition
{
public:
CSetCondition( const char *pszField, EItemCriteriaOperator eOp, const char *pszValue, bool bRequired )
: CCondition( pszField, eOp, bRequired ), m_sValue( pszValue )
{
}
virtual ~CSetCondition( ) { }
protected:
virtual bool BInternalEvaluate( KeyValues *pKVItem ) const;
virtual bool BSerializeToMsg( CSOItemCriteriaCondition & msg ) const;
// The subkey to look for
CUtlString m_sValue;
};
// True if item level is specified in this criteria
bool m_bItemLevelSet;
// The level of the item to generate
uint32 m_unItemLevel;
// True if quality is specified in this criteria
bool m_bQualitySet;
// The quality of the item to generate
int32 m_nItemQuality;
// True if rarity is specified in this criteria
bool m_bRaritySet;
// The rarity of the item to generate
int32 m_nItemRarity;
// The initial inventory token of the item
uint32 m_unInitialInventory;
// The initial quantity of the item
uint32 m_unInitialQuantity;
// Enforced explicit quality matching
bool m_bForcedQualityMatch;
// Ignoring enabled flag (used when crafting)
bool m_bIgnoreEnabledFlag;
// Check Recent flag
bool m_bRecentOnly;
// Outputs an item from a loot list
bool m_bIsLootList;
// A list of the conditions
CUtlVector<CCondition *> m_vecConditions;
};
#endif //ITEM_SELECTION_CRITERIA_H

View File

@@ -0,0 +1,73 @@
#include "cbase.h"
#include "localization_provider.h"
enum { kScratchBufferSize = 1024 };
CLocalizationProvider *GLocalizationProvider()
{
static CVGUILocalizationProvider g_VGUILocalizationProvider;
return &g_VGUILocalizationProvider;
}
// vgui localization implementation
CVGUILocalizationProvider::CVGUILocalizationProvider()
{
}
locchar_t *CVGUILocalizationProvider::Find( const char *pchKey )
{
return (locchar_t*)g_pVGuiLocalize->Find( pchKey );
}
void CVGUILocalizationProvider::ConstructString( locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, int numFormatParameters, ... )
{
va_list argList;
va_start(argList, numFormatParameters);
g_pVGuiLocalize->ConstructStringVArgs( unicodeOutput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList);
va_end(argList);
}
void CVGUILocalizationProvider::ConstructString( OUT_Z_BYTECAP(unicodeBufferSizeInBytes) locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, KeyValues *localizationVariables )
{
g_pVGuiLocalize->ConstructString( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
}
void CVGUILocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc_In, CUtlConstString *out_ansi ) const
{
char ansi_Scratch[kScratchBufferSize];
g_pVGuiLocalize->ConvertUnicodeToANSI( loc_In, ansi_Scratch, kScratchBufferSize );
*out_ansi = ansi_Scratch;
}
void CVGUILocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc_In, CUtlConstWideString *out_unicode ) const
{
*out_unicode = loc_In;
}
void CVGUILocalizationProvider::ConvertUTF8ToLocchar( const char *utf8_In, CUtlConstStringBase<locchar_t> *out_loc ) const
{
locchar_t loc_Scratch[kScratchBufferSize];
V_UTF8ToUnicode( utf8_In, loc_Scratch, sizeof( loc_Scratch ) );
*out_loc = loc_Scratch;
}
void CVGUILocalizationProvider::ConvertUTF8ToLocchar( const char *utf8, locchar_t *locchar, int cubDestSizeInBytes )
{
V_UTF8ToUnicode( utf8, locchar, cubDestSizeInBytes );
}
int CVGUILocalizationProvider::ConvertLoccharToANSI( const locchar_t *loc, char *ansi, int ansiBufferSize )
{
return g_pVGuiLocalize->ConvertUnicodeToANSI( loc, ansi, ansiBufferSize );
}
int CVGUILocalizationProvider::ConvertLoccharToUnicode( const locchar_t *loc, wchar_t *unicode, int unicodeBufferSizeInBytes )
{
Q_wcsncpy( unicode, loc, unicodeBufferSizeInBytes );
return 0;
}

View File

@@ -0,0 +1,262 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: provide a layer of abstraction between GC and vgui localization systems
//
//=============================================================================
#ifndef LOCALIZATION_PROVIDER_H
#define LOCALIZATION_PROVIDER_H
#ifdef _WIN32
#pragma once
#endif
#include "language.h"
typedef wchar_t locchar_t;
//#define loc_snprintf V_snwprintf
#define loc_sprintf_safe V_swprintf_safe
//#define loc_sncat V_wcsncat
#define loc_scat_safe V_wcscat_safe
#define loc_sncpy Q_wcsncpy
#define loc_scpy_safe V_wcscpy_safe
#define loc_strlen Q_wcslen
#define loc_strchr wcschr
#define LOCCHAR(x) L ## x
// interface matches a subset of VGUI functions
class CLocalizationProvider
{
public:
virtual locchar_t *Find( const char *pchKey ) = 0;
virtual void ConstructString( OUT_Z_BYTECAP(unicodeBufferSizeInBytes) locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, int numFormatParameters, ... ) = 0;
virtual void ConstructString( OUT_Z_BYTECAP(unicodeBufferSizeInBytes) locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, KeyValues *localizationVariables) = 0;
virtual void ConvertLoccharToANSI ( const locchar_t *loc_In, CUtlConstString *out_ansi ) const = 0;
virtual void ConvertLoccharToUnicode( const locchar_t *loc_In, CUtlConstWideString *out_unicode ) const = 0;
virtual void ConvertUTF8ToLocchar ( const char *utf8_In, CUtlConstStringBase<locchar_t> *out_loc ) const = 0;
virtual int ConvertLoccharToANSI( const locchar_t *loc, OUT_Z_CAP(ansiBufferSize) char *ansi, int ansiBufferSize ) = 0;
virtual int ConvertLoccharToUnicode( const locchar_t *loc, OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicode, int unicodeBufferSizeInBytes ) = 0;
virtual void ConvertUTF8ToLocchar( const char *utf8, OUT_Z_BYTECAP(cubDestSizeInBytes) locchar_t *locchar, int cubDestSizeInBytes ) = 0;
virtual ELanguage GetELang() = 0;
};
CLocalizationProvider *GLocalizationProvider();
#include "vgui/ILocalize.h"
extern vgui::ILocalize *g_pVGuiLocalize;
// Game localization is handled by vgui
class CVGUILocalizationProvider : public CLocalizationProvider
{
public:
CVGUILocalizationProvider();
virtual locchar_t *Find( const char *pchKey );
virtual void ConstructString( OUT_Z_BYTECAP(unicodeBufferSizeInBytes) locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, int numFormatParameters, ... );
virtual void ConstructString( OUT_Z_BYTECAP(unicodeBufferSizeInBytes) locchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const locchar_t *formatString, KeyValues *localizationVariables );
virtual void ConvertLoccharToANSI ( const locchar_t *loc_In, CUtlConstString *out_ansi ) const;
virtual void ConvertLoccharToUnicode( const locchar_t *loc_In, CUtlConstWideString *out_unicode ) const;
virtual void ConvertUTF8ToLocchar ( const char *utf8_In, CUtlConstStringBase<locchar_t> *out_loc ) const;
virtual int ConvertLoccharToANSI( const locchar_t *loc, OUT_Z_CAP(ansiBufferSize) char *ansi, int ansiBufferSize );
virtual int ConvertLoccharToUnicode( const locchar_t *loc, OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicode, int unicodeBufferSizeInBytes );
virtual void ConvertUTF8ToLocchar( const char *utf8, OUT_Z_BYTECAP(cubDestSizeInBytes) locchar_t *locchar, int cubDestSizeInBytes );
virtual ELanguage GetELang() { return k_Lang_None; }
};
// --------------------------------------------------------------------------
// Purpose: CLocalizedStringArg<> is a class that will take a variable of any
// arbitary type and convert it to a string of whatever character type
// we're using for localization (locchar_t).
//
// Independently it isn't very useful, though it can be used to sort-of-
// intelligently fill out the correct format string. It's designed to be
// used for the arguments of CConstructLocalizedString, which can be of
// arbitrary number and type.
//
// If you pass in a (non-specialized) pointer, the code will assume that
// you meant that pointer to be used as a localized string. This will
// still fail to compile if some non-string type is passed in, but will
// handle weird combinations of const/volatile/whatever automatically.
// --------------------------------------------------------------------------
// The base implementation doesn't do anything except fail to compile if you
// use it. Getting an "incomplete type" error here means that you tried to construct
// a localized string with a type that doesn't have a specialization.
template < typename T >
class CLocalizedStringArg;
// --------------------------------------------------------------------------
template < typename T >
class CLocalizedStringArgStringImpl
{
public:
enum { kIsValid = true };
CLocalizedStringArgStringImpl( const locchar_t *pStr ) : m_pStr( pStr ) { }
const locchar_t *GetLocArg() const { return m_pStr; }
private:
const locchar_t *m_pStr;
};
// --------------------------------------------------------------------------
template < typename T >
class CLocalizedStringArg<T *> : public CLocalizedStringArgStringImpl<T>
{
public:
CLocalizedStringArg( const locchar_t *pStr ) : CLocalizedStringArgStringImpl<T>( pStr ) { }
};
// --------------------------------------------------------------------------
template < typename T >
class CLocalizedStringArgPrintfImpl
{
public:
enum { kIsValid = true };
CLocalizedStringArgPrintfImpl( T value, const locchar_t *loc_Format ) { loc_sprintf_safe( m_cBuffer, loc_Format, value ); }
const locchar_t *GetLocArg() const { return m_cBuffer; }
private:
enum { kBufferSize = 128, };
locchar_t m_cBuffer[ kBufferSize ];
};
// --------------------------------------------------------------------------
template < >
class CLocalizedStringArg<uint32> : public CLocalizedStringArgPrintfImpl<uint32>
{
public:
CLocalizedStringArg( uint32 unValue ) : CLocalizedStringArgPrintfImpl<uint32>( unValue, LOCCHAR("%u") ) { }
};
// --------------------------------------------------------------------------
template < >
class CLocalizedStringArg<float> : public CLocalizedStringArgPrintfImpl<float>
{
public:
// Display one decimal point if we've got a value less than one, and no point
// if we're greater.
CLocalizedStringArg( float fValue )
: CLocalizedStringArgPrintfImpl<float>( fValue,
fabsf( fValue ) < 1.0f ? LOCCHAR("%.1f") : LOCCHAR("%.0f") )
{
//
}
};
// --------------------------------------------------------------------------
// Purpose:
// --------------------------------------------------------------------------
class CConstructLocalizedString
{
public:
template < typename T >
CConstructLocalizedString( CLocalizationProvider* pLocalizationProvider, const locchar_t *loc_Format, T arg0 )
{
Assert( CLocalizedStringArg<T>::kIsValid );
m_loc_Buffer[0] = '\0';
if ( loc_Format )
{
pLocalizationProvider->ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 1, CLocalizedStringArg<T>( arg0 ).GetLocArg() );
}
}
template < typename T, typename U >
CConstructLocalizedString( CLocalizationProvider* pLocalizationProvider, const locchar_t *loc_Format, T arg0, U arg1 )
{
Assert( CLocalizedStringArg<T>::kIsValid );
Assert( CLocalizedStringArg<U>::kIsValid );
m_loc_Buffer[0] = '\0';
if ( loc_Format )
{
pLocalizationProvider->ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 2, CLocalizedStringArg<T>( arg0 ).GetLocArg(), CLocalizedStringArg<U>( arg1 ).GetLocArg() );
}
}
template < typename T, typename U, typename V >
CConstructLocalizedString( CLocalizationProvider* pLocalizationProvider, const locchar_t *loc_Format, T arg0, U arg1, V arg2 )
{
Assert( CLocalizedStringArg<T>::kIsValid );
Assert( CLocalizedStringArg<U>::kIsValid );
Assert( CLocalizedStringArg<V>::kIsValid );
m_loc_Buffer[0] = '\0';
if ( loc_Format )
{
pLocalizationProvider->ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 3,
CLocalizedStringArg<T>( arg0 ).GetLocArg(),
CLocalizedStringArg<U>( arg1 ).GetLocArg(),
CLocalizedStringArg<V>( arg2 ).GetLocArg() );
}
}
template < typename T, typename U, typename V, typename W >
CConstructLocalizedString( CLocalizationProvider* pLocalizationProvider, const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3 )
{
Assert( CLocalizedStringArg<T>::kIsValid );
Assert( CLocalizedStringArg<U>::kIsValid );
Assert( CLocalizedStringArg<V>::kIsValid );
Assert( CLocalizedStringArg<W>::kIsValid );
m_loc_Buffer[0] = '\0';
if ( loc_Format )
{
pLocalizationProvider->ConstructString( m_loc_Buffer,
sizeof( m_loc_Buffer ),
loc_Format,
4,
CLocalizedStringArg<T>( arg0 ).GetLocArg(),
CLocalizedStringArg<U>( arg1 ).GetLocArg(),
CLocalizedStringArg<V>( arg2 ).GetLocArg(),
CLocalizedStringArg<W>( arg3 ).GetLocArg() );
}
}
CConstructLocalizedString( CLocalizationProvider* pLocalizationProvider, const locchar_t *loc_Format, KeyValues *pKeyValues )
{
m_loc_Buffer[0] = '\0';
if ( loc_Format && pKeyValues )
{
pLocalizationProvider->ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, pKeyValues );
}
}
operator const locchar_t *() const
{
return Get();
}
const locchar_t *Get() const
{
return m_loc_Buffer;
}
private:
enum { kBufferSize = 512, };
locchar_t m_loc_Buffer[ kBufferSize ];
};
#endif // LOCALIZATION_PROVIDER_H