initial
This commit is contained in:
732
game/shared/econ/attribute_manager.cpp
Normal file
732
game/shared/econ/attribute_manager.cpp
Normal 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
|
||||
220
game/shared/econ/attribute_manager.h
Normal file
220
game/shared/econ/attribute_manager.h
Normal 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
|
||||
64
game/shared/econ/econ_contribution.cpp
Normal file
64
game/shared/econ/econ_contribution.cpp
Normal 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
|
||||
45
game/shared/econ/econ_contribution.h
Normal file
45
game/shared/econ/econ_contribution.h
Normal 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
|
||||
|
||||
12
game/shared/econ/econ_coupons.cpp
Normal file
12
game/shared/econ/econ_coupons.cpp
Normal 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;
|
||||
|
||||
|
||||
34
game/shared/econ/econ_coupons.h
Normal file
34
game/shared/econ/econ_coupons.h
Normal 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
|
||||
|
||||
};
|
||||
1706
game/shared/econ/econ_entity.cpp
Normal file
1706
game/shared/econ/econ_entity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
206
game/shared/econ/econ_entity.h
Normal file
206
game/shared/econ/econ_entity.h
Normal 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
|
||||
196
game/shared/econ/econ_entity_creation.cpp
Normal file
196
game/shared/econ/econ_entity_creation.cpp
Normal 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;
|
||||
}
|
||||
50
game/shared/econ/econ_entity_creation.h
Normal file
50
game/shared/econ/econ_entity_creation.h
Normal 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
|
||||
17
game/shared/econ/econ_game_account.cpp
Normal file
17
game/shared/econ/econ_game_account.cpp
Normal 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"
|
||||
|
||||
49
game/shared/econ/econ_game_account.h
Normal file
49
game/shared/econ/econ_game_account.h
Normal 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
|
||||
21
game/shared/econ/econ_game_account_client.cpp
Normal file
21
game/shared/econ/econ_game_account_client.cpp
Normal 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;
|
||||
}
|
||||
44
game/shared/econ/econ_game_account_client.h
Normal file
44
game/shared/econ/econ_game_account_client.h
Normal 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
|
||||
33
game/shared/econ/econ_game_account_server.cpp
Normal file
33
game/shared/econ/econ_game_account_server.cpp
Normal 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"
|
||||
98
game/shared/econ/econ_game_account_server.h
Normal file
98
game/shared/econ/econ_game_account_server.h
Normal 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
|
||||
530
game/shared/econ/econ_gcmessages.h
Normal file
530
game/shared/econ/econ_gcmessages.h
Normal 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
|
||||
1401
game/shared/econ/econ_item.cpp
Normal file
1401
game/shared/econ/econ_item.cpp
Normal file
File diff suppressed because it is too large
Load Diff
588
game/shared/econ/econ_item.h
Normal file
588
game/shared/econ/econ_item.h
Normal 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 © ); // 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
|
||||
469
game/shared/econ/econ_item_constants.cpp
Normal file
469
game/shared/econ/econ_item_constants.cpp
Normal 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 );
|
||||
}
|
||||
710
game/shared/econ/econ_item_constants.h
Normal file
710
game/shared/econ/econ_item_constants.h
Normal 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
|
||||
74
game/shared/econ/econ_item_description.cpp
Normal file
74
game/shared/econ/econ_item_description.cpp
Normal 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;
|
||||
}
|
||||
133
game/shared/econ/econ_item_description.h
Normal file
133
game/shared/econ/econ_item_description.h
Normal 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
|
||||
377
game/shared/econ/econ_item_factory.cpp
Normal file
377
game/shared/econ/econ_item_factory.cpp
Normal 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 );
|
||||
}
|
||||
74
game/shared/econ/econ_item_factory.h
Normal file
74
game/shared/econ/econ_item_factory.h
Normal 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
|
||||
310
game/shared/econ/econ_item_interface.cpp
Normal file
310
game/shared/econ/econ_item_interface.cpp
Normal 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;
|
||||
}
|
||||
442
game/shared/econ/econ_item_interface.h
Normal file
442
game/shared/econ/econ_item_interface.h
Normal 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
|
||||
2546
game/shared/econ/econ_item_inventory.cpp
Normal file
2546
game/shared/econ/econ_item_inventory.cpp
Normal file
File diff suppressed because it is too large
Load Diff
490
game/shared/econ/econ_item_inventory.h
Normal file
490
game/shared/econ/econ_item_inventory.h
Normal 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
|
||||
8972
game/shared/econ/econ_item_schema.cpp
Normal file
8972
game/shared/econ/econ_item_schema.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4170
game/shared/econ/econ_item_schema.h
Normal file
4170
game/shared/econ/econ_item_schema.h
Normal file
File diff suppressed because it is too large
Load Diff
795
game/shared/econ/econ_item_system.cpp
Normal file
795
game/shared/econ/econ_item_system.cpp
Normal 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
|
||||
138
game/shared/econ/econ_item_system.h
Normal file
138
game/shared/econ/econ_item_system.h
Normal 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
|
||||
3708
game/shared/econ/econ_item_view.cpp
Normal file
3708
game/shared/econ/econ_item_view.cpp
Normal file
File diff suppressed because it is too large
Load Diff
613
game/shared/econ/econ_item_view.h
Normal file
613
game/shared/econ/econ_item_view.h
Normal 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
|
||||
90
game/shared/econ/econ_item_view_helpers.h
Normal file
90
game/shared/econ/econ_item_view_helpers.h
Normal 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
|
||||
70
game/shared/econ/game_item_schema.h
Normal file
70
game/shared/econ/game_item_schema.h
Normal 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
|
||||
46
game/shared/econ/ihasattributes.h
Normal file
46
game/shared/econ/ihasattributes.h
Normal 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
|
||||
24
game/shared/econ/ihasowner.h
Normal file
24
game/shared/econ/ihasowner.h
Normal 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
|
||||
544
game/shared/econ/item_selection_criteria.cpp
Normal file
544
game/shared/econ/item_selection_criteria.cpp
Normal 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;
|
||||
}
|
||||
|
||||
267
game/shared/econ/item_selection_criteria.h
Normal file
267
game/shared/econ/item_selection_criteria.h
Normal 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
|
||||
73
game/shared/econ/localization_provider.cpp
Normal file
73
game/shared/econ/localization_provider.cpp
Normal 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;
|
||||
}
|
||||
262
game/shared/econ/localization_provider.h
Normal file
262
game/shared/econ/localization_provider.h
Normal 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
|
||||
Reference in New Issue
Block a user