diff options
Diffstat (limited to 'game/shared/tf/tf_mann_vs_machine_stats.cpp')
| -rw-r--r-- | game/shared/tf/tf_mann_vs_machine_stats.cpp | 1689 |
1 files changed, 1689 insertions, 0 deletions
diff --git a/game/shared/tf/tf_mann_vs_machine_stats.cpp b/game/shared/tf/tf_mann_vs_machine_stats.cpp new file mode 100644 index 0000000..985f684 --- /dev/null +++ b/game/shared/tf/tf_mann_vs_machine_stats.cpp @@ -0,0 +1,1689 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" + +#include "tf_mann_vs_machine_stats.h" +#include "filesystem.h" +#include "steamworks_gamestats.h" +#include "econ_item_description.h" +#include "econ_item_system.h" +#include "econ_item_schema.h" +#include "econ_item_constants.h" + +#ifdef GAME_DLL + #include "dt_utlvector_send.h" + #include "tf_gamerules.h" + #include "tf_player.h" + #include "tf_gc_server.h" +#else + #include "dt_utlvector_recv.h" + #include "c_tf_player.h" + #include "hud_macros.h" + #include "tf_hud_mann_vs_machine_status.h" + #include "c_tf_objective_resource.h" + #include "player_vs_environment/c_tf_upgrades.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar tf_mm_trusted; + +extern ConVar tf_mvm_respec_limit; +extern ConVar tf_mvm_respec_credit_goal; + +static CMannVsMachineStats *g_pMVMStats = NULL; + +//----------------------------------------------------------------------------- +#ifdef CLIENT_DLL + // Avoid redef warnings + #undef CTFPlayer + #define CTFPlayer C_TFPlayer + #define CMannVsMachineStats C_MannVsMachineStats +#endif + +BEGIN_NETWORK_TABLE_NOBASE( CMannVsMachineWaveStats, DT_CMannVsMachineWaveStats ) +#if defined( GAME_DLL ) + SendPropInt( SENDINFO( nCreditsDropped ), 16, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( nCreditsAcquired ), 16, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( nCreditsBonus ), 16, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( nPlayerDeaths ), 16, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( nBuyBacks ), 8, SPROP_UNSIGNED ), +#else + + RecvPropInt( RECVINFO( nCreditsDropped ) ), + RecvPropInt( RECVINFO( nCreditsAcquired ) ), + RecvPropInt( RECVINFO( nCreditsBonus ) ), + RecvPropInt( RECVINFO( nPlayerDeaths ) ), + RecvPropInt( RECVINFO( nBuyBacks ) ), +#endif +END_NETWORK_TABLE() + +LINK_ENTITY_TO_CLASS( tf_mann_vs_machine_stats, CMannVsMachineStats ); +IMPLEMENT_NETWORKCLASS_ALIASED( MannVsMachineStats, DT_MannVsMachineStats ) + +BEGIN_NETWORK_TABLE( CMannVsMachineStats, DT_MannVsMachineStats ) +#if defined ( GAME_DLL ) + SendPropInt( SENDINFO( m_iCurrentWaveIdx ), 8, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( m_iServerWaveID ), 8, SPROP_UNSIGNED ), + SendPropDataTable( SENDINFO_DT(m_runningTotalWaveStats), &REFERENCE_SEND_TABLE(DT_CMannVsMachineWaveStats) ), + SendPropDataTable( SENDINFO_DT(m_previousWaveStats), &REFERENCE_SEND_TABLE(DT_CMannVsMachineWaveStats) ), + SendPropDataTable( SENDINFO_DT(m_currentWaveStats), &REFERENCE_SEND_TABLE(DT_CMannVsMachineWaveStats) ), + SendPropInt( SENDINFO( m_iCurrencyCollectedForRespec ), -1, SPROP_VARINT ), + SendPropInt( SENDINFO( m_nRespecsAwardedInWave ), 8, SPROP_UNSIGNED ), +#else + RecvPropInt( RECVINFO( m_iCurrentWaveIdx ) ), + RecvPropInt( RECVINFO( m_iServerWaveID ) ), + RecvPropDataTable(RECVINFO_DT(m_runningTotalWaveStats), 0, &REFERENCE_RECV_TABLE(DT_CMannVsMachineWaveStats)), + RecvPropDataTable(RECVINFO_DT(m_previousWaveStats), 0, &REFERENCE_RECV_TABLE(DT_CMannVsMachineWaveStats)), + RecvPropDataTable(RECVINFO_DT(m_currentWaveStats), 0, &REFERENCE_RECV_TABLE(DT_CMannVsMachineWaveStats)), + RecvPropInt( RECVINFO( m_iCurrencyCollectedForRespec ) ), + RecvPropInt( RECVINFO( m_nRespecsAwardedInWave ) ), +#endif +END_NETWORK_TABLE() + +#ifdef CLIENT_DLL + +//----------------------------------------------------------------------------- +// Purpose: Server message that tells that a mann vs machine event occurred +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMStatsReset( bf_read &msg ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->ResetStats( ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Server message that tells that a mann vs machine event occurred +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMPlayerEvent( bf_read &msg ) +{ + // Deprecated. + // Dont delete this or its HOOK_MESSAGE below or else demos will break +} + +//----------------------------------------------------------------------------- +// Purpose: Reports Player Spending +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMLocalPlayerWaveSpendingValue( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + // PlayerIdx(8), Wave(1), Type(1), Cost(2) + uint64 playerID; + if ( !msg.ReadBytes( &playerID, sizeof(playerID) ) ) + { + DevMsg( " Unable to Get Player SteamID from __MsgFunc_MVMLocalPlayerWaveSpendingValue() " ); + return; + } + + uint8 idxWave = msg.ReadByte(); + eMannVsMachineEvent eType = (eMannVsMachineEvent)msg.ReadByte(); + int16 nCost = msg.ReadWord(); + + CPlayerWaveSpendingStats *pPlayerStats = g_pMVMStats->GetSpending( idxWave, playerID ); + if ( !pPlayerStats ) + return; + + CSteamID steamId( playerID ); + C_TFPlayer *pTFPlayer = ToTFPlayer( GetPlayerBySteamID( steamId ) ); + C_TFPlayer *pTFLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); + + switch ( eType ) + { + case kMVMEvent_Player_BoughtInstantRespawn: + pPlayerStats->nCreditsSpentOnBuyBacks += nCost; + // Read the event msg and pass it on to MVMStats + if ( pTFPlayer == pTFLocalPlayer ) + { + g_pMVMStats->SW_ReportClientBuyBackPurchase( idxWave, nCost ); + } + break; + case kMVMEvent_Player_BoughtBottle: + pPlayerStats->nCreditsSpentOnBottles += nCost; + break; + case kMVMEvent_Player_BoughtUpgrade: + pPlayerStats->nCreditsSpentOnUpgrades += nCost; + break; + case kMVMEvent_Player_ActiveUpgrades: + g_pMVMStats->SetPlayerActiveUpgradeCosts( playerID, nCost ); + break; + } // switch + +} +//----------------------------------------------------------------------------- +// Purpose: Server message that tells that a mann vs machine event occurred +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMResetPlayerStats( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + uint8 playerIndex = msg.ReadByte(); + + C_TFPlayer *pTFPlayer = ToTFPlayer( UTIL_PlayerByIndex( playerIndex ) ); + if ( !pTFPlayer ) + return; + + g_pMVMStats->ResetPlayerEvents( pTFPlayer ); +} + +//----------------------------------------------------------------------------- +// Purpose: Handling a Server message that notifies that a player has upgraded in MvM +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMPlayerUpgradedEvent( bf_read &msg ) +{ + //if ( !g_pMVMStats ) + // return; + // + //// Read the data + //// PlayerIdx(1), WaveIdx(1), ItemDef(2), AttributeDef(2), Quality(1), cost(2) + //uint8 playerIndex = msg.ReadByte(); + //uint8 idxWave = msg.ReadByte(); + //uint16 nItemDef = msg.ReadWord(); + //uint16 nAttributeDef = msg.ReadWord(); + //uint8 nQuality = msg.ReadByte(); + //int16 nCost = msg.ReadWord(); + + //CMannVsMachineUpgradeEvent upgrade; + //upgrade.nItemDef = nItemDef; + //upgrade.nAttributeDef = nAttributeDef; + //upgrade.nQuality = nQuality; + + //C_TFPlayer *pTFPlayer = ToTFPlayer( UTIL_PlayerByIndex( playerIndex ) ); + //C_TFPlayer *pTFLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); + + //// Report Stats if Local Player + //if ( pTFPlayer && pTFLocalPlayer && ( pTFPlayer == pTFLocalPlayer ) ) + //{ + // // Read the event msg and pass it on to MVMStats + // g_pMVMStats->SW_ReportClientUpgradePurchase( idxWave, nItemDef, nAttributeDef, nQuality, nCost ); + //} +} + +//----------------------------------------------------------------------------- +// Message for the Local Player that it should clear its upgrade vector +static void __MsgFunc_MVMLocalPlayerUpgradesClear( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + // Read the data + //uint8 count = msg.ReadByte(); + + g_pMVMStats->ClearLocalPlayerUpgrades(); +} + +//----------------------------------------------------------------------------- +// Message for the local player about an upgrade that it owns +static void __MsgFunc_MVMLocalPlayerUpgradesValue( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + // Read the data + // Class(1), ItemDef(2), Upgrade(1), cost(1) + uint8 playerClass = msg.ReadByte(); + uint16 nItemDef = msg.ReadWord(); + //uint8 upgrade = msg.ReadByte(); + //uint16 cost = msg.ReadByte(); + + g_pMVMStats->AddLocalPlayerUpgrade( playerClass, (item_definition_index_t)nItemDef ); +} + +//----------------------------------------------------------------------------- +// Message for the player that it should clear spending stats history for target wave +static void __MsgFunc_MVMResetPlayerWaveSpendingStats( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + // Read the data + // Wave(1) + uint8 idxWave = msg.ReadByte(); + + g_pMVMStats->ClearCurrentPlayerWaveSpendingStats( idxWave ); +} + +//----------------------------------------------------------------------------- +// Purpose: Server message that tells that the current wave has ended and a new one has begun (including resets) +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMWaveChange( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + // Read the data + uint16 waveID = msg.ReadWord(); + + CMannVsMachinePlayerStats stats; + + stats.nDeaths = msg.ReadByte(); + stats.nBotDamage = msg.ReadLong(); + stats.nGiantDamage = msg.ReadLong(); + stats.nTankDamage = msg.ReadLong(); + + // Send the Stats + g_pMVMStats->SW_ReportClientWaveSummary( waveID, stats ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +static void __MsgFunc_MVMResetPlayerUpgradeSpending( bf_read &msg ) +{ + if ( !g_pMVMStats ) + return; + + uint8 playerIndex = msg.ReadByte(); + + C_TFPlayer *pTFPlayer = ToTFPlayer( UTIL_PlayerByIndex( playerIndex ) ); + if ( !pTFPlayer ) + return; + + g_pMVMStats->ResetUpgradeSpending( pTFPlayer ); +} + +#endif // CLIENT_DLL + +//------------------------------------------------------------------------------ +// CMannVsMachineStats +//------------------------------------------------------------------------------ +CMannVsMachineStats::CMannVsMachineStats() +{ + g_pMVMStats = this; + +#ifdef GAME_DLL + SetCurrentWave( 0 ); + Q_memset( m_playerStats, 0, sizeof( m_playerStats ) ); +#else + m_iCurrentWaveIdx = 0; + + m_teamActiveUpgrades.Purge(); + m_teamActiveUpgrades.SetLessFunc( DefLessFunc (uint64) ); +#endif + m_currWaveSpendingStats.SetLessFunc( DefLessFunc (uint64) ); + m_prevWaveSpendingStats.SetLessFunc( DefLessFunc (uint64) ); + m_allPrevWaveSpendingStats.SetLessFunc( DefLessFunc (uint64) ); + + m_iCurrencyCollectedForRespec = 0; + m_nRespecsAwardedInWave = 0; + //m_nEventID = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: DTOR +//----------------------------------------------------------------------------- +CMannVsMachineStats::~CMannVsMachineStats() +{ + g_pMVMStats = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ResetStats( ) +{ +#ifdef GAME_DLL + // notify everyone to reset everything + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + UserMessageBegin( filter, "MVMStatsReset" ); + MessageEnd(); + + SetCurrentWave( 0 ); + + m_runningTotalWaveStats.ClearStats(); + m_previousWaveStats.ClearStats(); + m_currentWaveStats.ClearStats(); + +#else + m_vecLocalPlayerUpgrades.Purge(); + m_teamActiveUpgrades.Purge(); +#endif + + m_currWaveSpendingStats.RemoveAll(); + m_prevWaveSpendingStats.RemoveAll(); + m_allPrevWaveSpendingStats.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ResetPlayerEvents( CTFPlayer *pTFPlayer ) +{ + if ( pTFPlayer->IsBot() ) + return; + +#ifdef GAME_DLL + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + UserMessageBegin( filter, "MVMResetPlayerStats" ); + WRITE_BYTE( (uint8)pTFPlayer->entindex() ); + MessageEnd(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ResetUpgradeSpending( CTFPlayer *pTFPlayer ) +{ + if ( !pTFPlayer ) + return; + + if ( pTFPlayer->IsBot() ) + return; + + CSteamID steamID; + if ( pTFPlayer && pTFPlayer->GetSteamID( &steamID ) ) + { + int iWave = m_currWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_currWaveSpendingStats.InvalidIndex() ) + { + m_currWaveSpendingStats[iWave].nCreditsSpentOnUpgrades = 0; + } + + iWave = m_allPrevWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + m_allPrevWaveSpendingStats[iWave].nCreditsSpentOnUpgrades = 0; + } + + iWave = m_prevWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_prevWaveSpendingStats.InvalidIndex() ) + { + m_prevWaveSpendingStats[iWave].nCreditsSpentOnUpgrades = 0; + } + } + +#ifdef GAME_DLL + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + UserMessageBegin( filter, "MVMResetPlayerUpgradeSpending" ); + WRITE_BYTE( (uint8)pTFPlayer->entindex() ); + MessageEnd(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Returns acquired credits - default is all waves +//----------------------------------------------------------------------------- +uint32 CMannVsMachineStats::GetAcquiredCredits( int iWaveIdx, bool bWithBonus /*= true*/ ) +{ + CMannVsMachineLocalWaveStats waveStats = GetWaveStats( iWaveIdx ); + + if ( bWithBonus ) + return waveStats.nCreditsAcquired + waveStats.nCreditsBonus; + else + return waveStats.nCreditsAcquired; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns dropped credits for a target wave. If target wave is -1, returns sum of all waves +//----------------------------------------------------------------------------- +uint32 CMannVsMachineStats::GetDroppedCredits( int iWaveIdx ) +{ + CMannVsMachineLocalWaveStats waveStats = GetWaveStats( iWaveIdx ); + return waveStats.nCreditsDropped; +} + +//----------------------------------------------------------------------------- +// Number of Credits missed (dropped and not collected) +//----------------------------------------------------------------------------- +uint32 CMannVsMachineStats::GetMissedCredits( int iWaveIdx ) +{ + CMannVsMachineLocalWaveStats waveStats = GetWaveStats( iWaveIdx ); + return waveStats.nCreditsDropped - waveStats.nCreditsAcquired; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns credit bonus for a target wave. If target wave is -1, returns sum of all waves +//----------------------------------------------------------------------------- +uint32 CMannVsMachineStats::GetBonusCredits( int iWaveIdx ) +{ + CMannVsMachineLocalWaveStats waveStats = GetWaveStats( iWaveIdx ); + return waveStats.nCreditsBonus; +} +//=============================================================================// +#ifdef GAME_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::RoundOver( bool bHumansWon ) +{ + // Send Stats to OGS + // Increment server wave id since victory uses the previous "wave" and this one has yet to be incremented + m_iServerWaveID++; + SW_ReportWaveSummary( m_iCurrentWaveIdx, bHumansWon ); + m_iServerWaveID--; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SetCurrentWave( uint32 idxWave ) +{ + // Advancing Wave, compact in the stats + if ( idxWave > m_iCurrentWaveIdx ) + { + m_runningTotalWaveStats += m_previousWaveStats; + m_previousWaveStats = m_currentWaveStats; + } + + if ( idxWave == 0 ) + { + // Purge it all + m_runningTotalWaveStats.ClearStats(); + m_previousWaveStats.ClearStats(); + m_currentWaveStats.ClearStats(); + } + + m_iCurrentWaveIdx = idxWave; + + // Notify Players of Reset of current Wave for PlayerStats + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + + UserMessageBegin( filter, "MVMResetPlayerWaveSpendingStats" ); + WRITE_BYTE( (uint8)m_iCurrentWaveIdx ); + MessageEnd(); + + ResetWaveStats(); + OnStatsChanged(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::RoundEvent_WaveStart() +{ + // Starting a new wave + // Report the previous successful wave. + if ( m_iCurrentWaveIdx > 0 && m_currentWaveStats.nAttempts == 0) + { + SW_ReportWaveSummary( m_iCurrentWaveIdx - 1, true ); + } + + // reset stats + ResetWaveStats(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::RoundEvent_WaveEnd( bool bSuccess ) +{ + // if failed, report immediately, + // report successes on starting the next wave because of currency picked up late + ConVar *sv_cheats = g_pCVar->FindVar( "sv_cheats" ); + if ( !bSuccess && ( !sv_cheats || !sv_cheats->GetBool() ) ) + { + m_currentWaveStats.nAttempts++; + SW_ReportWaveSummary( m_iCurrentWaveIdx, false ); + ResetWaveStats(); + OnStatsChanged(); + + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + UserMessageBegin( filter, "MVMWaveFailed" ); + MessageEnd(); + } + + // Send a User message to Clients to send there data + // Tell each client their damage + CUtlVector< CTFPlayer * > playerVector; + CollectPlayers( &playerVector, TF_TEAM_PVE_DEFENDERS ); + for( int i=0; i<playerVector.Count(); ++i ) + { + CTFPlayer *player = playerVector[i]; + CMannVsMachinePlayerStats stats = m_playerStats[player->entindex()]; + + CSingleUserRecipientFilter filter( player ); + filter.MakeReliable(); + + // ServerWaveID(2), deaths(1), damageBot(4), damageGiant(4), damageTank(4) + UserMessageBegin( filter, "MVMWaveChange" ); + WRITE_WORD( (uint16)m_iServerWaveID ); + WRITE_BYTE( (uint8)stats.nDeaths ); + WRITE_LONG( stats.nBotDamage ); + WRITE_LONG( stats.nGiantDamage ); + WRITE_LONG( stats.nTankDamage ); + MessageEnd(); + } + + // Increment the ServerId + m_iServerWaveID++; + Q_memset( m_playerStats, 0, sizeof( m_playerStats ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::RoundEvent_AcquiredCredits( uint32 idxWave, int nAmount, bool bIsBonus ) +{ + if ( idxWave == (int)m_iCurrentWaveIdx ) + { + if ( bIsBonus ) + { + m_currentWaveStats.nCreditsBonus += nAmount; + } + else + { + m_currentWaveStats.nCreditsAcquired += nAmount; + } + } + else if ( idxWave == m_iCurrentWaveIdx - 1 ) + { + if ( bIsBonus ) + { + m_previousWaveStats.nCreditsBonus += nAmount; + } + else + { + m_previousWaveStats.nCreditsAcquired += nAmount; + } + } + + OnStatsChanged(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::RoundEvent_CreditsDropped( uint32 idxWave, int nAmount ) +{ + if ( idxWave == m_iCurrentWaveIdx ) + { + m_currentWaveStats.nCreditsDropped += nAmount; + } + else if ( idxWave == m_iCurrentWaveIdx - 1 ) + { + m_previousWaveStats.nCreditsDropped += nAmount; + } + OnStatsChanged(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_PointsChanged( CTFPlayer *pTFPlayer, int nPoints ) +{ + // + // Deprecated + // + + //if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + // return; + + //OnStatsChanged(); + //NotifyPlayerEvent( pTFPlayer, m_iCurrentWaveIdx, kMVMEvent_Player_Points, nPoints ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_Died( CTFPlayer *pTFPlayer ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + m_playerStats[pTFPlayer->entindex()].nDeaths += 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_Upgraded( CTFPlayer *pTFPlayer, uint16 nItemDef, uint16 nAttributeDef, uint8 nQuality, int16 nCost, bool bIsBottle ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + OnStatsChanged(); + + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + + // PlayerIdx(1), WaveIdx(1), ItemDef(2), AttributeDef(2), Quality(1), cost(2) + // send user message + UserMessageBegin( filter, "MVMPlayerUpgradedEvent" ); + WRITE_BYTE( (uint8)pTFPlayer->entindex() ); + WRITE_BYTE( (uint8)m_iCurrentWaveIdx ); + WRITE_WORD( nItemDef ); + WRITE_WORD( nAttributeDef ); + WRITE_BYTE( nQuality); + WRITE_WORD( nCost ); + MessageEnd(); + + if ( bIsBottle ) + { + NotifyTargetPlayerEvent( pTFPlayer, m_iCurrentWaveIdx, kMVMEvent_Player_BoughtBottle, nCost ); + } + else + { + NotifyTargetPlayerEvent( pTFPlayer, m_iCurrentWaveIdx, kMVMEvent_Player_BoughtUpgrade, nCost ); + } + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_PickedUpCredits( CTFPlayer *pTFPlayer, uint32 idxWave, int nCreditsAmount ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + OnStatsChanged(); + NotifyPlayerEvent( pTFPlayer, idxWave, kMVMEvent_Player_PickedUpCredits, nCreditsAmount ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_BoughtInstantRespawn( CTFPlayer *pTFPlayer, int nCost ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + m_currentWaveStats.nBuyBacks++; + OnStatsChanged(); + + NotifyTargetPlayerEvent( pTFPlayer, m_iCurrentWaveIdx, kMVMEvent_Player_BoughtInstantRespawn, nCost ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_DealtDamageToBots( CTFPlayer *pTFPlayer, int damage ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + m_playerStats[pTFPlayer->entindex()].nBotDamage += damage; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_DealtDamageToGiants( CTFPlayer *pTFPlayer, int damage ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + m_playerStats[pTFPlayer->entindex()].nGiantDamage += damage; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::PlayerEvent_DealtDamageToTanks( CTFPlayer *pTFPlayer, int damage ) +{ + if ( pTFPlayer->IsBot() || !TFGameRules() || !TFGameRules()->IsPVEModeActive() ) + return; + + m_playerStats[pTFPlayer->entindex()].nTankDamage += damage; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::NotifyPlayerEvent( CTFPlayer *pTFPlayer, uint32 idxWave, eMannVsMachineEvent eType, int nValue, int nParam ) +{ + // Deprecated +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::NotifyTargetPlayerEvent( CTFPlayer *pTFPlayer, uint32 idxWave, eMannVsMachineEvent eType, int nCost ) +{ + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + + // Client + UserMessageBegin( filter, "MVMLocalPlayerWaveSpendingValue" ); + uint64 id = pTFPlayer->GetSteamIDAsUInt64(); + + WRITE_BITS( &id, 64 ); + WRITE_BYTE( (uint8)idxWave ); + WRITE_BYTE( (uint8)eType ); + WRITE_WORD( (uint16)nCost ); + MessageEnd(); + + // Server + uint64 steamID = pTFPlayer->GetSteamIDAsUInt64(); + CPlayerWaveSpendingStats *pPlayerStats = g_pMVMStats->GetSpending( idxWave, steamID ); + if ( !pPlayerStats ) + return; + + switch ( eType ) + { + case kMVMEvent_Player_BoughtInstantRespawn: + // Don't track refunds (permanent cost) + pPlayerStats->nCreditsSpentOnBuyBacks += nCost; + break; + case kMVMEvent_Player_BoughtBottle: + // Don't track refunds (permanent cost) + pPlayerStats->nCreditsSpentOnBottles += nCost; + break; + case kMVMEvent_Player_BoughtUpgrade: + pPlayerStats->nCreditsSpentOnUpgrades += nCost; + break; + } +} + +//----------------------------------------------------------------------------- +// Tell the Player What Upgrades they have +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SendUpgradesToPlayer( CTFPlayer *pTFPlayer, CUtlVector< CUpgradeInfo > *upgrades ) +{ + CRecipientFilter filter; + filter.AddRecipient( pTFPlayer ); + + if ( upgrades == NULL ) + { + UserMessageBegin( filter, "MVMLocalPlayerUpgradesClear" ); + WRITE_BYTE( 0 ); + MessageEnd(); + return; + } + + // Send the reset command + UserMessageBegin( filter, "MVMLocalPlayerUpgradesClear" ); + WRITE_BYTE( 0 ); + MessageEnd(); + + // send all the upgrades + // Class(1), ItemDef(2), Upgrade(1), cost(2) + for ( int i = 0; i < upgrades->Count(); ++i ) + { + UserMessageBegin( filter, "MVMLocalPlayerUpgradesValue" ); + WRITE_BYTE( (uint8)upgrades->Element(i).m_iPlayerClass ); + WRITE_WORD( (uint16)upgrades->Element(i).m_itemDefIndex ); + WRITE_BYTE( (uint8)upgrades->Element(i).m_upgrade ); + WRITE_WORD( (uint16)upgrades->Element(i).m_nCost ); + MessageEnd(); + } +} + +//=============================================================================// +void CMannVsMachineStats::NotifyPlayerActiveUpgradeCosts( CTFPlayer *pTFPlayer, int nSpending ) +{ + NotifyTargetPlayerEvent( pTFPlayer, 0, kMVMEvent_Player_ActiveUpgrades, nSpending ); +} +#endif // GAME_DLL + +//----------------------------------------------------------------------------- +// Purpose: Clear The Player spending stats for this wave +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ClearCurrentPlayerWaveSpendingStats( int idxWave ) +{ + // If the wave is different then the current, we're changing waves and need to save this stuff off if we're advancing + + if ( idxWave != (int)m_iCurrentWaveIdx ) + { + // if wave incremented, we changed waves to save off the previous wave data + m_prevWaveSpendingStats.RemoveAll(); + + FOR_EACH_MAP_FAST( m_currWaveSpendingStats, i ) + { + // Save off current wave in to previous + int iWave = m_prevWaveSpendingStats.Insert(m_currWaveSpendingStats.Key(i), CPlayerWaveSpendingStats() ); + m_prevWaveSpendingStats[iWave] = m_currWaveSpendingStats[i]; + + // Append current wave in to all prev + int allIndex = m_allPrevWaveSpendingStats.Find( m_currWaveSpendingStats.Key(i) ); + if ( allIndex != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + m_allPrevWaveSpendingStats[allIndex] += m_currWaveSpendingStats[i]; + } + else + { + allIndex = m_allPrevWaveSpendingStats.Insert( m_currWaveSpendingStats.Key(i), CPlayerWaveSpendingStats() ); + m_allPrevWaveSpendingStats[allIndex] = m_currWaveSpendingStats[i]; + } + } + } + // Purge away current stats + m_currWaveSpendingStats.RemoveAll(); +} + +//----------------------------------------------------------------------------- +CPlayerWaveSpendingStats *CMannVsMachineStats::GetSpending( int iWaveIndex, uint64 steamId ) +{ + if ( iWaveIndex == (int)m_iCurrentWaveIdx ) + { + int iWave = m_currWaveSpendingStats.Find( steamId ); + if ( iWave != m_currWaveSpendingStats.InvalidIndex() ) + { + return &m_currWaveSpendingStats[iWave]; + } + else + { + iWave = m_currWaveSpendingStats.Insert( steamId, CPlayerWaveSpendingStats() ); + return &m_currWaveSpendingStats[iWave]; + } + } + else if ( iWaveIndex == -1 ) + { + int iWave = m_allPrevWaveSpendingStats.Find( steamId ); + if ( iWave != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + return &m_allPrevWaveSpendingStats[iWave]; + } + else + { + iWave = m_allPrevWaveSpendingStats.Insert( steamId, CPlayerWaveSpendingStats() ); + return &m_allPrevWaveSpendingStats[iWave]; + } + } + else if ( iWaveIndex == (int)(m_iCurrentWaveIdx - 1) ) + { + int iWave = m_prevWaveSpendingStats.Find( steamId ); + if ( iWave != m_prevWaveSpendingStats.InvalidIndex() ) + { + return &m_prevWaveSpendingStats[iWave]; + } + else + { + iWave = m_prevWaveSpendingStats.Insert( steamId, CPlayerWaveSpendingStats() ); + return &m_prevWaveSpendingStats[iWave]; + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetUpgradeSpending( CTFPlayer *pTFPlayer /*= NULL*/ ) +{ + int spending = 0; + + CSteamID steamID; + if ( pTFPlayer && pTFPlayer->GetSteamID( &steamID ) ) + { + int iWave = m_currWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_currWaveSpendingStats.InvalidIndex() ) + { + spending += m_currWaveSpendingStats[iWave].nCreditsSpentOnUpgrades; + } + + iWave = m_allPrevWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + spending += m_allPrevWaveSpendingStats[iWave].nCreditsSpentOnUpgrades; + } + } + else + { + FOR_EACH_MAP_FAST ( m_currWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_currWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_currWaveSpendingStats[iPlayer].nCreditsSpentOnUpgrades; + } + } + + FOR_EACH_MAP_FAST ( m_allPrevWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_allPrevWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_allPrevWaveSpendingStats[iPlayer].nCreditsSpentOnUpgrades; + } + } + } + + return spending; +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetBottleSpending( CTFPlayer *pTFPlayer /*= NULL*/ ) +{ + int spending = 0; + + CSteamID steamID; + if ( pTFPlayer && pTFPlayer->GetSteamID( &steamID ) ) + { + int iWave = m_currWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_currWaveSpendingStats.InvalidIndex() ) + { + spending += m_currWaveSpendingStats[iWave].nCreditsSpentOnBottles; + } + + iWave = m_allPrevWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + spending += m_allPrevWaveSpendingStats[iWave].nCreditsSpentOnBottles; + } + } + else + { + FOR_EACH_MAP_FAST ( m_currWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_currWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_currWaveSpendingStats[iPlayer].nCreditsSpentOnBottles; + } + } + + FOR_EACH_MAP_FAST ( m_allPrevWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_allPrevWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_allPrevWaveSpendingStats[iPlayer].nCreditsSpentOnBottles; + } + } + } + + return spending; +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetBuyBackSpending( CTFPlayer *pTFPlayer /*= NULL*/ ) +{ + int spending = 0; + + CSteamID steamID; + if ( pTFPlayer && pTFPlayer->GetSteamID( &steamID ) ) + { + int iWave = m_currWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_currWaveSpendingStats.InvalidIndex() ) + { + spending += m_currWaveSpendingStats[iWave].nCreditsSpentOnBuyBacks; + } + + iWave = m_allPrevWaveSpendingStats.Find( steamID.ConvertToUint64() ); + if ( iWave != m_allPrevWaveSpendingStats.InvalidIndex() ) + { + spending += m_allPrevWaveSpendingStats[iWave].nCreditsSpentOnBuyBacks; + } + } + else + { + FOR_EACH_MAP_FAST ( m_currWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_currWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_currWaveSpendingStats[iPlayer].nCreditsSpentOnBuyBacks; + } + } + + FOR_EACH_MAP_FAST ( m_allPrevWaveSpendingStats, iPlayer ) + { + CBasePlayer * pPlayer = GetPlayerBySteamID( CSteamID( m_allPrevWaveSpendingStats.Key( iPlayer ) ) ); + if ( pPlayer ) + { + spending += m_allPrevWaveSpendingStats[iPlayer].nCreditsSpentOnBuyBacks; + } + } + } + + return spending; +} + +//=============================================================================// +#ifdef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMannVsMachineStats::OnDataChanged( DataUpdateType_t updateType ) +{ + +} + +//----------------------------------------------------------------------------- +// Purpose: Clear Local Player Upgrades +//----------------------------------------------------------------------------- +CPlayerWaveSpendingStats *CMannVsMachineStats::GetLocalSpending ( int iWaveIdx ) +{ + CSteamID steamId; + if ( C_TFPlayer::GetLocalTFPlayer()->GetSteamID( &steamId ) ) + { + return GetSpending( iWaveIdx, steamId.ConvertToUint64() ); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Set the active upgrade costs for this player +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SetPlayerActiveUpgradeCosts( uint64 steamId, int nSpending ) +{ + int iUpgrade = m_teamActiveUpgrades.Find(steamId); + if ( iUpgrade != m_teamActiveUpgrades.InvalidIndex() ) + { + m_teamActiveUpgrades[iUpgrade] = nSpending; + } + else + { + m_teamActiveUpgrades.Insert( steamId, nSpending ); + } +} + +//----------------------------------------------------------------------------- +// Get Player Active Upgrade Costs +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetPlayerActiveUpgradeCosts( uint64 steamId64 ) +{ + // 0, give team total + if ( steamId64 == 0 ) + { + int nSpending = 0; + FOR_EACH_MAP_FAST ( m_teamActiveUpgrades, i ) + { + CSteamID steamId( m_teamActiveUpgrades.Key( i ) ); + CBasePlayer * pPlayer = GetPlayerBySteamID( steamId ); + if ( pPlayer ) + { + nSpending += m_teamActiveUpgrades[ i ]; + } + } + + return nSpending; + } + else + { + CSteamID steamId( steamId64 ); + CBasePlayer * pPlayer = GetPlayerBySteamID( steamId ); + if ( pPlayer ) + { + int iUpgrade = m_teamActiveUpgrades.Find( steamId64 ); + if ( iUpgrade != m_teamActiveUpgrades.InvalidIndex() ) + return m_teamActiveUpgrades[iUpgrade]; + } + } + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Clear Local Player Upgrades +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ClearLocalPlayerUpgrades () +{ + m_vecLocalPlayerUpgrades.Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: Add Local Player Upgrade +//----------------------------------------------------------------------------- +void CMannVsMachineStats::AddLocalPlayerUpgrade ( int iPlayerClass, item_definition_index_t iItemDef ) +{ + CUpgradeInfo upgrade; + upgrade.m_iPlayerClass = iPlayerClass; + upgrade.m_itemDefIndex = iItemDef; + upgrade.m_upgrade = 0; + upgrade.m_nCost = 0; + + m_vecLocalPlayerUpgrades.AddToTail( upgrade ); +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetLocalPlayerUpgradeSpending( int idxWave ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer == NULL ) + return 0; + + CPlayerWaveSpendingStats *pStats = GetLocalSpending( idxWave ); + return pStats ? pStats->nCreditsSpentOnUpgrades : 0; +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetLocalPlayerBottleSpending( int idxWave ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer == NULL ) + return 0; + + CPlayerWaveSpendingStats *pStats = GetLocalSpending( idxWave ); + return pStats ? pStats->nCreditsSpentOnBottles : 0; +} + +//----------------------------------------------------------------------------- +int CMannVsMachineStats::GetLocalPlayerBuyBackSpending ( int idxWave ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer == NULL ) + return 0; + + CPlayerWaveSpendingStats *pStats = GetLocalSpending( idxWave ); + return pStats ? pStats->nCreditsSpentOnBuyBacks : 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Submits the use of MvM Credits +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SW_ReportClientUpgradePurchase( uint8 waveIdx, uint16 nItemDef, uint16 nAttributeDef, uint8 nQuality, int16 nCost ) +{ + // Disabled due to bad key indexing. + // Make a V2 if this data is wanted + +// Old Table + //----------------------------------------------------------------------------- + // OGS TF2ClientMvMWaveCreditSpend: MvM mode - credit spend + //----------------------------------------------------------------------------- + //START_TABLE( k_ESchemaCatalogOGS, TF2ClientMvMWaveCreditSpend, TABLE_PROP_NORMAL ) + //INT_FIELD( nID, ID, int32 ) // Auto-increment fake key + //INT_FIELD( llSessionID, SessionID, uint64 ) + //INT_FIELD( llServerSessionID, ServerSessionID, uint64 ) // Duplicated data from Session table due to game client anomalies + //INT_FIELD( nServerWaveID, ServerWaveID, int32 ) // Incrementing WaveId PerAttempt + //INT_FIELD( ulAccountID, AccountID, uint64 ) // Duplicated data from Session table due to game client anomalies + //INT_FIELD( nWaveNumber, WaveNumber, uint8 ) + //INT_FIELD( nItemCategoryID, MvMItemCategoryID, int16 ) // References TF2MvMItemCategoryReference + //INT_FIELD( nItemNameID, MvMItemNameID, int32 ) // References TF2MvMItemNameReference + //INT_FIELD( nItemCost, ItemCost, int32 ) + //INT_FIELD( RTime32EventTime, EventTime, RTime32 ) + //PRIMARY_KEY_CLUSTERED( 100, nID ) + //WIPE_TABLE_BETWEEN_TESTS( k_EWipePolicyWipeForAllTests ) + //AUTOINCREMENT_FIELD( nID ) + //PARTITION_INTERVAL( k_EPartitionIntervalDaily ) + //OWNING_APPLICATION( 440 ) + //END_TABLE + + + +//#if !defined(NO_STEAM) +// ConVar *sv_cheats = g_pCVar->FindVar( "sv_cheats" ); +// if ( sv_cheats && sv_cheats->GetBool() ) +// return; +// +// C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer(); +// if ( !pTFPlayer ) +// return; +// +// // Get Data needed for this report +// const CEconItemAttributeDefinition *pAttributeDef = ItemSystem()->GetItemSchema()->GetAttributeDefinition( nAttributeDef ); +// if ( !pAttributeDef ) +// return; +// +// float flValue = 1.0f; +// if ( !MannVsMachine_GetUpgradeInfo( pAttributeDef->GetDefinitionIndex(), nQuality, flValue ) ) +// return; +// +// CSteamID steamIDForPlayer; +// if ( !pTFPlayer->GetSteamID( &steamIDForPlayer ) ) +// return; +// +// KeyValuesAD pKeyValues( "data" ); +// +// // Create and Send the report +// //SessionId, ServerSessionId, AccountID, ServerWaveID, WaveNumber, MvMItemCategoryID, MvMItemNameID, ItemCost, EventTime +// KeyValues* pKVData = new KeyValues( "TF2ClientMvMWaveCreditSpend" ); +// pKVData->SetInt( "ID", ++m_nEventID ); +// +// // ServerSessionID - Auto +// // SessionID - Auto +// +// // AccountID +// pKVData->SetUint64( "AccountID", steamIDForPlayer.ConvertToUint64() ); +// +// //ServerWaveID - Use provided ID not m_iServerWaveID as that may have changed +// pKVData->SetInt( "ServerWaveID", m_iServerWaveID ); +// +// // WaveNumber +// pKVData->SetInt( "WaveNumber", waveIdx + 1 ); +// +// // MvMItemNameID +// if ( nItemDef ) +// { +// const CEconItemDefinition *pItemDef = ItemSystem()->GetItemSchema()->GetItemDefinition( nItemDef ); +// pKVData->SetString( "MvMItemNameID", pItemDef->GetDefinitionName() ); +// } +// else +// { +// pKVData->SetString( "MvMItemNameID", g_aPlayerClassNames_NonLocalized[ pTFPlayer->GetPlayerClass()->GetClassIndex() ] ); +// } +// +// // MvMItemCategoryID +// pKVData->SetString( "MvMItemCategoryID", pAttributeDef->GetDefinitionName() ); +// +// // ItemCost +// pKVData->SetInt( "ItemCost", nCost ); +// +// // EventTime +// pKVData->SetInt( "EventTime", GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch() ); +// +// // Send to DB +// GetSteamWorksSGameStatsUploader().AddStatsForUpload( pKVData ); +// +//#endif // !defined(NO_STEAM) +} + +//----------------------------------------------------------------------------- +// Purpose: Submits the use of MvM Credits +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SW_ReportClientBuyBackPurchase ( uint8 waveIdx, uint16 nCost ) +{ +//#if !defined(NO_STEAM) +// ConVar *sv_cheats = g_pCVar->FindVar( "sv_cheats" ); +// if ( sv_cheats && sv_cheats->GetBool() ) +// return; +// +// C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer(); +// if ( !pTFPlayer ) +// return; +// +// CSteamID steamIDForPlayer; +// if ( !pTFPlayer->GetSteamID( &steamIDForPlayer ) ) +// return; +// +// // Create and Send the report +// //SessionId, ServerSessionId, AccountID, ServerWaveID, WaveNumber, MvMItemCategoryID, MvMItemNameID, ItemCost, EventTime +// KeyValues* pKVData = new KeyValues( "TF2ClientMvMWaveCreditSpend" ); +// +// // ID - Auto +// // ServerSessionID - Auto +// // SessionID - Auto +// +// // AccountID +// pKVData->SetUint64( "AccountID", steamIDForPlayer.ConvertToUint64() ); +// +// //ServerWaveID - Use provided ID not m_iServerWaveID as that may have changed +// pKVData->SetInt( "ServerWaveID", m_iServerWaveID ); +// +// // WaveNumber +// pKVData->SetInt( "WaveNumber", waveIdx + 1 ); +// +// // MvMItemNameID +// static char szAnsi[64]; +// g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( g_aPlayerClassNames[ pTFPlayer->GetPlayerClass()->GetClassIndex() ] ), szAnsi, sizeof(szAnsi) ); +// pKVData->SetString( "MvMItemNameID", szAnsi ); +// +// // MvMItemCategoryID +// pKVData->SetString( "MvMItemCategoryID", "BuyBack"); +// +// // ItemCost +// pKVData->SetInt( "ItemCost", nCost ); +// +// // EventTime +// pKVData->SetInt( "EventTime", GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch() ); +// +// // Send to DB +// GetSteamWorksSGameStatsUploader().AddStatsForUpload( pKVData ); +// +//#endif // !defined(NO_STEAM) +} + +//----------------------------------------------------------------------------- +// Purpose: Submits the use of MvM Credits +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SW_ReportClientWaveSummary( uint16 waveID, CMannVsMachinePlayerStats stats ) +{ + // Disabled due to bad key indexing. + // Make a V2 if this data is wanted + // Old Table + //----------------------------------------------------------------------------- + // OGS TF2ClientMvMWaveSummary: MvM mode � Player wave summary information + //----------------------------------------------------------------------------- + //START_TABLE( k_ESchemaCatalogOGS, TF2ClientMvMWaveSummary, TABLE_PROP_NORMAL ) + //INT_FIELD( nID, ID, int32 ) // Auto-increment fake key + //INT_FIELD( nServerWaveID, ServerWaveID, int32 ) // ID of ServerMvMWaveSummary Entry this is linked with, How do we get this? + //INT_FIELD( llSessionID, SessionID, uint64 ) + //INT_FIELD( llServerSessionID, ServerSessionID, uint64 ) // Duplicated data from Session table due to game client anomalies + //INT_FIELD( ulAccountID, AccountID, uint64 ) // Duplicated data from Session table due to game client anomalies + //INT_FIELD( nDamageToBots, DamageToBots, int32 ) + //INT_FIELD( nDamageToTanks, DamageToTanks, int32 ) + //INT_FIELD( nDamageToGiants, DamageToGiants, int32 ) + //INT_FIELD( nDeaths, Deaths, uint8 ) + //INT_FIELD( nClass, Class, int64 ) // References TF2ClassReference + //INT_FIELD( nPrimaryWeapon, PrimaryWeapon, int32 ) // References TF2MvMItemNameReference + //INT_FIELD( nSecondaryWeapon, SecondaryWeapon, int32 ) // References TF2MvMItemNameReference + //INT_FIELD( nMeleeWeapon, MeleeWeapon, int32 ) // References TF2MvMItemNameReference + //INT_FIELD( bHasBottle, HasBottle, int8 ) + //PRIMARY_KEY_CLUSTERED( 100, nID ) + //WIPE_TABLE_BETWEEN_TESTS( k_EWipePolicyWipeForAllTests ) + //AUTOINCREMENT_FIELD( nID ) + //PARTITION_INTERVAL( k_EPartitionIntervalDaily ) + //OWNING_APPLICATION( 440 ) + //END_TABLE + + +//#if !defined(NO_STEAM) +// ConVar *sv_cheats = g_pCVar->FindVar( "sv_cheats" ); +// if ( sv_cheats && sv_cheats->GetBool() ) +// return; +// +// C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer(); +// if ( !pTFPlayer ) +// return; +// +// CSteamID steamIDForPlayer; +// if ( !pTFPlayer->GetSteamID( &steamIDForPlayer ) ) +// return; +// +// // Class +// int iClass = pTFPlayer->GetPlayerClass()->GetClassIndex(); +// +// // Invalid Class, Spectators? +// if ( iClass < TF_FIRST_NORMAL_CLASS || iClass >= TF_LAST_NORMAL_CLASS ) +// return; +// +// // Create and Send the report +// //[ID] ,[ServerWaveID] ,[SessionID] ,[AccountID] ,[DamageToBots] ,[DamageToTanks] ,[DamageToGiants] +// //,[Deaths] ,[Class] ,[PrimaryWeapon] ,[SecondaryWeapon] ,[MeleeWeapon] ,[HasBottle] +// KeyValues* pKVData = new KeyValues( "TF2ClientMvMWaveSummary" ); +// pKVData->SetInt( "ID", ++m_nEventID ); +// +// // ServerSessionID - Auto +// // SessionID - Auto +// +// // AccountID +// pKVData->SetUint64( "AccountID", steamIDForPlayer.ConvertToUint64() ); +// +// //Damage +// pKVData->SetInt( "DamageToBots", stats.nBotDamage ); +// pKVData->SetInt( "DamageToGiants", stats.nGiantDamage ); +// pKVData->SetInt( "DamageToTanks", stats.nTankDamage ); +// +// // Death +// pKVData->SetInt( "Deaths", stats.nDeaths ); +// +// //ServerWaveID - Use provided ID not m_iServerWaveID as that may have changed +// pKVData->SetInt( "ServerWaveID", waveID ); +// +// static char szAnsi[512]; +// pKVData->SetString( "Class", g_aPlayerClassNames_NonLocalized[ iClass ] ); +// +// // Primary +// CEconItemView *pPrimaryView = TFInventoryManager()->GetItemInLoadoutForClass( iClass, LOADOUT_POSITION_PRIMARY ); +// const CEconItemDefinition *pPrimaryDef = pPrimaryView->GetItemDefinition(); +// +// if ( pPrimaryDef ) +// { +// g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find ( pPrimaryDef->GetItemBaseName() ) , szAnsi, sizeof(szAnsi) ); +// pKVData->SetString( "PrimaryWeapon", szAnsi ); +// } +// +// // Secondary +// CEconItemView *pSecondaryView = TFInventoryManager()->GetItemInLoadoutForClass( iClass, LOADOUT_POSITION_SECONDARY ); +// const CEconItemDefinition *pSecondaryDef = pSecondaryView->GetItemDefinition(); +// +// if ( pSecondaryDef ) +// { +// g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find ( pSecondaryDef->GetItemBaseName() ) , szAnsi, sizeof(szAnsi) ); +// pKVData->SetString( "SecondaryWeapon", szAnsi ); +// } +// +// // Melee +// CEconItemView *pMeleeView = TFInventoryManager()->GetItemInLoadoutForClass( iClass, LOADOUT_POSITION_MELEE ); +// const CEconItemDefinition *pMeleeDef = pMeleeView->GetItemDefinition(); +// +// if ( pMeleeDef ) +// { +// g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find ( pMeleeDef->GetItemBaseName() ) , szAnsi, sizeof(szAnsi) ); +// pKVData->SetString( "MeleeWeapon", szAnsi ); +// } +// +// // Check for power up bottle +// CEconItemView *pActionView = TFInventoryManager()->GetItemInLoadoutForClass( iClass, LOADOUT_POSITION_ACTION ); +// //489 is bottle - Power Up Canteen (MvM) +// pKVData->SetBool( "HasBottle", pActionView->GetItemDefIndex() == 489 ); +// +// // Send to DB +// GetSteamWorksSGameStatsUploader().AddStatsForUpload( pKVData ); +// +//#endif // !defined(NO_STEAM) +} +#endif // CLIENT_DLL +//=============================================================================// +//----------------------------------------------------------------------------- +// PRIVATE +//----------------------------------------------------------------------------- +// Purpose: Returns a copy of the WaveStats if legit +//----------------------------------------------------------------------------- +CMannVsMachineLocalWaveStats CMannVsMachineStats::GetWaveStats( int iWaveIdx ) +{ + CMannVsMachineLocalWaveStats waveStats; + + if ( iWaveIdx == (int)m_iCurrentWaveIdx ) + { + waveStats = m_currentWaveStats; + } + else if ( iWaveIdx >= 0 && iWaveIdx == (int)m_iCurrentWaveIdx - 1 ) + { + waveStats = m_previousWaveStats; + } + else if ( iWaveIdx == -1 ) + { + waveStats = m_runningTotalWaveStats; + waveStats += m_previousWaveStats; + waveStats += m_currentWaveStats; + } + return waveStats; +} + +//----------------------------------------------------------------------------- +// Purpose: Advances Event time for the next set of events +//----------------------------------------------------------------------------- +void CMannVsMachineStats::OnStatsChanged() +{ + NetworkStateChanged(); +} + +#ifdef GAME_DLL + +//----------------------------------------------------------------------------- +// Purpose: Reset the tracked wave stats +//----------------------------------------------------------------------------- +void CMannVsMachineStats::ResetWaveStats() +{ + m_currentWaveStats.ClearStats(); + m_nRespecsAwardedInWave = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Submits the WaveSummary Data to OGS +//----------------------------------------------------------------------------- +void CMannVsMachineStats::SW_ReportWaveSummary ( int waveIdx, bool bIsSuccess ) +{ +// Disabled due to bad key indexing. +// Make a V2 if this data is wanted +//#if !defined(NO_STEAM) +// ConVar *sv_cheats = g_pCVar->FindVar( "sv_cheats" ); +// if ( sv_cheats && sv_cheats->GetBool() ) +// return; +// +// CMannVsMachineWaveStats stats; +// if ( waveIdx == (int)m_iCurrentWaveIdx ) +// { +// stats = m_currentWaveStats; +// } +// else if ( waveIdx == (int)m_iCurrentWaveIdx - 1) +// { +// stats = m_previousWaveStats; +// } +// else +// { +// return; +// } +// +// KeyValues* pKVData = new KeyValues( "TF2ServerMvMWaveSummary" ); +// +// // ServerSessionID - Auto +// pKVData->SetUint64( "ServerSessionID", GetSteamWorksSGameStatsUploader().GetSessionID()); +// pKVData->SetInt( "ID", ++m_nEventID ); +// //ServerWaveID, if we won this wave, use the previous WaveID +// int iServerWaveID = m_iServerWaveID; +// if ( bIsSuccess ) +// { +// iServerWaveID--; +// } +// pKVData->SetInt( "ServerWaveID", iServerWaveID ); +// +// // WaveNumber +// pKVData->SetInt( "WaveNumber", waveIdx + 1 ); +// +// // PopulationFileID +// pKVData->SetString( "PopulationFileID", m_pPopFileName ); +// +// //// MoneyCollected +// pKVData->SetInt( "MoneyCollected", stats.nCreditsAcquired ); +// // +// //// MoneyMissed +// pKVData->SetInt( "MoneyMissed", stats.nCreditsDropped - stats.nCreditsAcquired ); +// // +// //// Attempts +// pKVData->SetInt( "Attempts", stats.nAttempts ); +// +// // IsSuccess +// pKVData->SetBool( "IsSuccess", bIsSuccess ); +// +// // IsSuccess +// bool bMannUp = false; +// bool bInLobby = false; +// CTFLobby *pLobby = GTFGCClientSystem()->GetLobby(); +// if ( pLobby ) +// { +// bInLobby = true; +// bMannUp = IsMannUpGroup( pLobby->GetMatchGroup() ); +// } +// +// pKVData->SetBool( "IsTrustedServer", bInLobby ); +// +// pKVData->SetBool( "IsMannUp", bMannUp ); +// +// // EventTime +// pKVData->SetInt( "EventTime", GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch() ); +// +// // Send to DB +// GetSteamWorksSGameStatsUploader().AddStatsForUpload( pKVData ); +// +//#endif // !defined(NO_STEAM) +} + +#endif // GAME_DLL + +//----------------------------------------------------------------------------- +// End CMannVsMachineStats +//----------------------------------------------------------------------------- + +void MannVsMachineStats_Init() +{ +#ifdef GAME_DLL + CBaseEntity::Create( "tf_mann_vs_machine_stats", vec3_origin, vec3_angle ); +#else + HOOK_MESSAGE( MVMPlayerEvent ); + HOOK_MESSAGE( MVMResetPlayerStats ); + HOOK_MESSAGE( MVMStatsReset ); + HOOK_MESSAGE( MVMPlayerUpgradedEvent ); + HOOK_MESSAGE( MVMLocalPlayerUpgradesClear ); + HOOK_MESSAGE( MVMLocalPlayerUpgradesValue ); + HOOK_MESSAGE( MVMResetPlayerWaveSpendingStats ); + HOOK_MESSAGE( MVMLocalPlayerWaveSpendingValue ); + HOOK_MESSAGE( MVMWaveChange ); + HOOK_MESSAGE( MVMResetPlayerUpgradeSpending ); +#endif +} + +//----------------------------------------------------------------------------- +// Helper Functions +//----------------------------------------------------------------------------- +uint32 MannVsMachineStats_GetCurrentWave() +{ + return g_pMVMStats ? g_pMVMStats->GetCurrentWave() : 0; +} + +uint32 MannVsMachineStats_GetAcquiredCredits( int idxWave /*= - 1 */, bool bIncludeBonus /*= true*/ ) +{ + return g_pMVMStats ? g_pMVMStats->GetAcquiredCredits( idxWave, bIncludeBonus ) : 0; +} + +uint32 MannVsMachineStats_GetDroppedCredits( int idxWave ) +{ + return g_pMVMStats ? g_pMVMStats->GetDroppedCredits( idxWave ) : 0; +} + +uint32 MannVsMachineStats_GetMissedCredits( int idxWave ) +{ + return g_pMVMStats ? g_pMVMStats->GetMissedCredits( idxWave ) : 0; +} + +CMannVsMachineStats *MannVsMachineStats_GetInstance() +{ + return g_pMVMStats; +} + + +#ifdef GAME_DLL + +void MannVsMachineStats_ResetPlayerEvents( CTFPlayer *pTFPlayer ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->ResetPlayerEvents( pTFPlayer ); + } +} + +void MannVsMachineStats_RoundEvent_CreditsDropped( uint32 waveIdx, int nAmount ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->RoundEvent_CreditsDropped( waveIdx, nAmount ); + } +} + +void MannVsMachineStats_PlayerEvent_PointsChanged( CTFPlayer *pTFPlayer, int nPoints ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->PlayerEvent_PointsChanged( pTFPlayer, nPoints ); + } +} + +void MannVsMachineStats_PlayerEvent_Died( CTFPlayer *pTFPlayer ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->PlayerEvent_Died( pTFPlayer ); + } +} + +void MannVsMachineStats_PlayerEvent_Upgraded( CTFPlayer *pTFPlayer, uint16 nItemDef, uint16 nAttributeDef, uint16 nQuality, int16 nCost, bool bIsBottle ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->PlayerEvent_Upgraded( pTFPlayer, nItemDef, nAttributeDef, nQuality, nCost, bIsBottle ); + } +} + +void MannVsMachineStats_PlayerEvent_PickedUpCredits( CTFPlayer *pTFPlayer, uint32 idxWave, int nCreditsAmount ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->PlayerEvent_PickedUpCredits( pTFPlayer, idxWave, nCreditsAmount ); + } +} + +void MannVsMachineStats_PlayerEvent_BoughtInstantRespawn( CTFPlayer *pTFPlayer, int nCost ) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->PlayerEvent_BoughtInstantRespawn( pTFPlayer, nCost ); + } +} + +void MannVsMachineStats_SetPopulationFile( const char * pPopulationFile) +{ + if ( g_pMVMStats ) + { + g_pMVMStats->SetPopFile( pPopulationFile ); + } +} + +#endif // GAME_DLL + |