//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Entity that propagates general data needed by clients for every player. // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "c_playerresource.h" #include "c_team.h" #include "gamestringpool.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" const float PLAYER_RESOURCE_THINK_INTERVAL = 0.2f; #define PLAYER_UNCONNECTED_NAME "unconnected" #define PLAYER_DEBUG_NAME "WWWWWWWWWWWWWWW" ConVar cl_names_debug( "cl_names_debug", "0", FCVAR_DEVELOPMENTONLY ); void RecvProxy_ChangedTeam( const CRecvProxyData *pData, void *pStruct, void *pOut ) { // Have the regular proxy store the data. RecvProxy_Int32ToInt32( pData, pStruct, pOut ); if ( g_PR ) { g_PR->TeamChanged(); } } IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_PlayerResource, DT_PlayerResource, CPlayerResource) RecvPropArray3( RECVINFO_ARRAY(m_iPing), RecvPropInt( RECVINFO(m_iPing[0]))), RecvPropArray3( RECVINFO_ARRAY(m_iScore), RecvPropInt( RECVINFO(m_iScore[0]))), RecvPropArray3( RECVINFO_ARRAY(m_iDeaths), RecvPropInt( RECVINFO(m_iDeaths[0]))), RecvPropArray3( RECVINFO_ARRAY(m_bConnected), RecvPropInt( RECVINFO(m_bConnected[0]))), RecvPropArray3( RECVINFO_ARRAY(m_iTeam), RecvPropInt( RECVINFO(m_iTeam[0]), 0, RecvProxy_ChangedTeam )), RecvPropArray3( RECVINFO_ARRAY(m_bAlive), RecvPropInt( RECVINFO(m_bAlive[0]))), RecvPropArray3( RECVINFO_ARRAY(m_iHealth), RecvPropInt( RECVINFO(m_iHealth[0]))), END_RECV_TABLE() BEGIN_PREDICTION_DATA( C_PlayerResource ) DEFINE_PRED_ARRAY( m_szName, FIELD_STRING, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_iPing, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_iScore, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_iDeaths, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_bConnected, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_iTeam, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_bAlive, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), DEFINE_PRED_ARRAY( m_iHealth, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ), END_PREDICTION_DATA() C_PlayerResource *g_PR; IGameResources * GameResources( void ) { return g_PR; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- C_PlayerResource::C_PlayerResource() { for ( int i=0; icurtime + PLAYER_RESOURCE_THINK_INTERVAL ); } } void C_PlayerResource::UpdatePlayerName( int slot ) { if ( slot < 1 || slot > MAX_PLAYERS ) { Error( "UpdatePlayerName with bogus slot %d\n", slot ); return; } player_info_t sPlayerInfo; char const *pchPlayerName = PLAYER_UNCONNECTED_NAME; if ( IsConnected( slot ) && engine->GetPlayerInfo( slot, &sPlayerInfo ) ) { pchPlayerName = sPlayerInfo.name; } if ( !m_szName[slot] || Q_stricmp( m_szName[slot], pchPlayerName ) ) { m_szName[slot] = AllocPooledString( pchPlayerName ); } } void C_PlayerResource::ClientThink() { BaseClass::ClientThink(); for ( int i = 1; i <= gpGlobals->maxClients; ++i ) { UpdatePlayerName( i ); } SetNextClientThink( gpGlobals->curtime + PLAYER_RESOURCE_THINK_INTERVAL ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const char *C_PlayerResource::GetPlayerName( int iIndex ) { if ( cl_names_debug.GetInt() ) return PLAYER_DEBUG_NAME; if ( iIndex < 1 || iIndex > MAX_PLAYERS ) { Assert( false ); return "ERRORNAME"; } if ( !IsConnected( iIndex ) ) return PLAYER_UNCONNECTED_NAME; // X360TBD: Network - figure out why the name isn't set if ( !m_szName[ iIndex ] || !Q_stricmp( m_szName[ iIndex ], PLAYER_UNCONNECTED_NAME ) ) { // If you get a full "reset" uncompressed update from server, then you can have NULLNAME show up in the scoreboard UpdatePlayerName( iIndex ); } // This gets updated in ClientThink, so it could be up to 1 second out of date, oh well. return m_szName[iIndex]; } bool C_PlayerResource::IsAlive(int iIndex ) { return m_bAlive[iIndex]; } int C_PlayerResource::GetTeam(int iIndex ) { if ( iIndex < 1 || iIndex > MAX_PLAYERS ) { Assert( false ); return 0; } else { return m_iTeam[iIndex]; } } const char * C_PlayerResource::GetTeamName(int index) { C_Team *team = GetGlobalTeam( index ); if ( !team ) return "Unknown"; return team->Get_Name(); } int C_PlayerResource::GetTeamScore(int index) { C_Team *team = GetGlobalTeam( index ); if ( !team ) return 0; return team->Get_Score(); } int C_PlayerResource::GetFrags(int index ) { return 666; } bool C_PlayerResource::IsLocalPlayer(int index) { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) return false; return ( index == pPlayer->entindex() ); } bool C_PlayerResource::IsHLTV(int index) { if ( !IsConnected( index ) ) return false; player_info_t sPlayerInfo; if ( engine->GetPlayerInfo( index, &sPlayerInfo ) ) { return sPlayerInfo.ishltv; } return false; } bool C_PlayerResource::IsReplay(int index) { if ( !IsConnected( index ) ) return false; player_info_t sPlayerInfo; if ( engine->GetPlayerInfo( index, &sPlayerInfo ) ) { return sPlayerInfo.isreplay; } return false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool C_PlayerResource::IsFakePlayer( int iIndex ) { if ( !IsConnected( iIndex ) ) return false; // Yuck, make sure it's up to date player_info_t sPlayerInfo; if ( engine->GetPlayerInfo( iIndex, &sPlayerInfo ) ) { return sPlayerInfo.fakeplayer; } return false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_PlayerResource::GetPing( int iIndex ) { if ( !IsConnected( iIndex ) ) return 0; return m_iPing[iIndex]; } //----------------------------------------------------------------------------- // Purpose: /*----------------------------------------------------------------------------- int C_PlayerResource::GetPacketloss( int iIndex ) { if ( !IsConnected( iIndex ) ) return 0; return m_iPacketloss[iIndex]; }*/ //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_PlayerResource::GetPlayerScore( int iIndex ) { if ( !IsConnected( iIndex ) ) return 0; return m_iScore[iIndex]; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_PlayerResource::GetDeaths( int iIndex ) { if ( !IsConnected( iIndex ) ) return 0; return m_iDeaths[iIndex]; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_PlayerResource::GetHealth( int iIndex ) { if ( !IsConnected( iIndex ) ) return 0; return m_iHealth[iIndex]; } const Color &C_PlayerResource::GetTeamColor(int index ) { if ( index < 0 || index >= MAX_TEAMS ) { Assert( false ); static Color blah; return blah; } else { return m_Colors[index]; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool C_PlayerResource::IsConnected( int iIndex ) { if ( iIndex < 1 || iIndex > MAX_PLAYERS ) return false; else return m_bConnected[iIndex]; }