summaryrefslogtreecommitdiff
path: root/game/server/tf/tf_team.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf/tf_team.cpp')
-rw-r--r--game/server/tf/tf_team.cpp482
1 files changed, 482 insertions, 0 deletions
diff --git a/game/server/tf/tf_team.cpp b/game/server/tf/tf_team.cpp
new file mode 100644
index 0000000..b680269
--- /dev/null
+++ b/game/server/tf/tf_team.cpp
@@ -0,0 +1,482 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=============================================================================
+#include "cbase.h"
+#include "tf_team.h"
+#include "entitylist.h"
+#include "util.h"
+#include "tf_obj.h"
+#include "tf_gamerules.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: SendProxy that converts the UtlVector list of objects to entindexes, where it's reassembled on the client
+//-----------------------------------------------------------------------------
+void SendProxy_TeamObjectList( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
+{
+ CTFTeam *pTeam = (CTFTeam*)pStruct;
+
+ Assert( iElement < pTeam->GetNumObjects() );
+
+ CBaseObject *pObject = pTeam->GetObject(iElement);
+
+ EHANDLE hObject;
+ hObject = pObject;
+
+ SendProxy_EHandleToInt( pProp, pStruct, &hObject, pOut, iElement, objectID );
+}
+
+int SendProxyArrayLength_TeamObjects( const void *pStruct, int objectID )
+{
+ CTFTeam *pTeam = (CTFTeam*)pStruct;
+ int iObjects = pTeam->GetNumObjects();
+ return iObjects;
+}
+
+//=============================================================================
+//
+// TF Team tables.
+//
+IMPLEMENT_SERVERCLASS_ST( CTFTeam, DT_TFTeam )
+
+ SendPropInt( SENDINFO( m_nFlagCaptures ), 8 ),
+ SendPropInt( SENDINFO( m_iRole ), 4, SPROP_UNSIGNED ),
+
+ SendPropArray2(
+ SendProxyArrayLength_TeamObjects,
+ SendPropInt( "team_object_array_element", 0, SIZEOF_IGNORE, NUM_NETWORKED_EHANDLE_BITS, SPROP_UNSIGNED, SendProxy_TeamObjectList ),
+ MAX_PLAYERS * MAX_OBJECTS_PER_PLAYER,
+ 0,
+ "team_object_array"
+ ),
+
+ SendPropEHandle( SENDINFO( m_hLeader ) ),
+
+END_SEND_TABLE()
+
+
+LINK_ENTITY_TO_CLASS( tf_team, CTFTeam );
+
+//=============================================================================
+//
+// TF Team Manager Functions.
+//
+CTFTeamManager s_TFTeamManager;
+
+CTFTeamManager *TFTeamMgr()
+{
+ return &s_TFTeamManager;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFTeamManager::CTFTeamManager()
+{
+ m_UndefinedTeamColor.r = 255;
+ m_UndefinedTeamColor.g = 255;
+ m_UndefinedTeamColor.b = 255;
+ m_UndefinedTeamColor.a = 0;
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFTeamManager::Init( void )
+{
+ // Clear the list.
+ Shutdown();
+
+ // Create the team list.
+ for ( int iTeam = 0; iTeam < TF_TEAM_COUNT; ++iTeam )
+ {
+ COMPILE_TIME_ASSERT( TF_TEAM_COUNT == ARRAYSIZE( g_aTeamNames ) );
+ COMPILE_TIME_ASSERT( TF_TEAM_COUNT == ARRAYSIZE( g_aTeamColors ) );
+ int index = Create( g_aTeamNames[iTeam], g_aTeamColors[iTeam] );
+ Assert( index == iTeam );
+ if ( index != iTeam )
+ return false;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFTeamManager::Shutdown( void )
+{
+ // Note, don't delete each team since they are in the gEntList and will
+ // automatically be deleted from there, instead.
+ g_Teams.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CTFTeamManager::Create( const char *pName, color32 color )
+{
+ CTeam *pTeam = static_cast<CTeam*>( CreateEntityByName( "tf_team" ) );
+ if ( pTeam )
+ {
+ // Add the team to the global list of teams.
+ int iTeam = g_Teams.AddToTail( pTeam );
+
+ // Initialize the team.
+ pTeam->Init( pName, iTeam );
+ pTeam->NetworkProp()->SetUpdateInterval( 0.75f );
+
+ // Set the team color.
+ CTFTeam *pTFTeam = static_cast<CTFTeam*>( pTeam );
+ pTFTeam->SetColor( color );
+
+ return iTeam;
+ }
+
+ // Error.
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CTFTeamManager::GetFlagCaptures( int iTeam )
+{
+ if ( !IsValidTeam( iTeam ) )
+ return -1;
+
+ CTFTeam *pTeam = GetGlobalTFTeam( iTeam );
+ if ( !pTeam )
+ return -1;
+
+ return pTeam->GetFlagCaptures();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFTeamManager::IncrementFlagCaptures( int iTeam )
+{
+ if ( !IsValidTeam( iTeam ) )
+ return;
+
+ CTFTeam *pTeam = GetGlobalTFTeam( iTeam );
+ if ( !pTeam )
+ return;
+
+ pTeam->IncrementFlagCaptures();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFTeamManager::AddTeamScore( int iTeam, int iScoreToAdd )
+{
+ if ( !IsValidTeam( iTeam ) )
+ return;
+
+ CTeam *pTeam = GetGlobalTeam( iTeam );
+ if ( !pTeam )
+ return;
+
+ pTeam->AddScore( iScoreToAdd );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFTeamManager::IsValidTeam( int iTeam )
+{
+ if ( ( iTeam >= 0 ) && ( iTeam < g_Teams.Count() ) )
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CTFTeamManager::GetTeamCount( void )
+{
+ return g_Teams.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFTeam *CTFTeamManager::GetTeam( int iTeam )
+{
+ Assert( ( iTeam >= 0 ) && ( iTeam < g_Teams.Count() ) );
+ if ( IsValidTeam( iTeam ) )
+ {
+ return static_cast<CTFTeam*>( g_Teams[iTeam] );
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFTeam *CTFTeamManager::GetSpectatorTeam()
+{
+ return GetTeam( 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+color32 CTFTeamManager::GetUndefinedTeamColor( void )
+{
+ return m_UndefinedTeamColor;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sends a message to the center of the player's screen.
+//-----------------------------------------------------------------------------
+void CTFTeamManager::PlayerCenterPrint( CBasePlayer *pPlayer, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
+{
+ ClientPrint( pPlayer, HUD_PRINTCENTER, msg_name, param1, param2, param3, param4 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sends a message to the center of the given teams screen.
+//-----------------------------------------------------------------------------
+void CTFTeamManager::TeamCenterPrint( int iTeam, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
+{
+ CTeamRecipientFilter filter( iTeam, true );
+ UTIL_ClientPrintFilter( filter, HUD_PRINTCENTER, msg_name, param1, param2, param3, param4 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sends a message to the center of the player's teams screen (minus
+// the player).
+//-----------------------------------------------------------------------------
+void CTFTeamManager::PlayerTeamCenterPrint( CBasePlayer *pPlayer, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 )
+{
+ CTeamRecipientFilter filter( pPlayer->GetTeamNumber(), true );
+ filter.RemoveRecipient( pPlayer );
+ UTIL_ClientPrintFilter( filter, HUD_PRINTCENTER, msg_name, param1, param2, param3, param4 );
+}
+
+//=============================================================================
+//
+// TF Team Functions.
+//
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor.
+//-----------------------------------------------------------------------------
+CTFTeam::CTFTeam()
+{
+ m_TeamColor.r = 0;
+ m_TeamColor.g = 0;
+ m_TeamColor.b = 0;
+ m_TeamColor.a = 0;
+
+ m_nFlagCaptures = 0;
+ m_nTotalFlagCaptures = 0;
+ m_flTotalSecondsKOTHPointOwned = 0.f;
+ m_flTotalPLRTrackPercentTraveled = 0.f;
+
+ m_hLeader = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFTeam::SetColor( color32 color )
+{
+ m_TeamColor = color;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+color32 CTFTeam::GetColor( void )
+{
+ return m_TeamColor;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input: pPlayer - print to just that client, NULL = all clients
+//-----------------------------------------------------------------------------
+void CTFTeam::ShowScore( CBasePlayer *pPlayer )
+{
+ if ( pPlayer )
+ {
+ ClientPrint( pPlayer, HUD_PRINTNOTIFY, UTIL_VarArgs( "Team %s: %d\n", GetName(), GetScore() ) );
+ }
+ else
+ {
+ UTIL_ClientPrintAll( HUD_PRINTNOTIFY, UTIL_VarArgs( "Team %s: %d\n", GetName(), GetScore() ) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// OBJECTS
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Purpose: Add the specified object to this team.
+//-----------------------------------------------------------------------------
+void CTFTeam::AddObject( CBaseObject *pObject )
+{
+ TRACE_OBJECT( UTIL_VarArgs( "%0.2f CTFTeam::AddObject adding object %p:%s to team %s\n", gpGlobals->curtime,
+ pObject, pObject->GetClassname(), GetName() ) );
+
+ bool alreadyInList = IsObjectOnTeam( pObject );
+ Assert( !alreadyInList );
+ if ( !alreadyInList )
+ {
+ m_aObjects.AddToTail( pObject );
+ }
+
+ NetworkStateChanged();
+}
+
+//-----------------------------------------------------------------------------
+// Returns true if the object is in the team's list of objects
+//-----------------------------------------------------------------------------
+bool CTFTeam::IsObjectOnTeam( CBaseObject *pObject ) const
+{
+ return ( m_aObjects.Find( pObject ) != -1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove this object from the team
+// Removes all references from all sublists as well
+//-----------------------------------------------------------------------------
+void CTFTeam::RemoveObject( CBaseObject *pObject )
+{
+ if ( m_aObjects.Count() <= 0 )
+ return;
+
+ if ( m_aObjects.Find( pObject ) != -1 )
+ {
+ TRACE_OBJECT( UTIL_VarArgs( "%0.2f CTFTeam::RemoveObject removing %p:%s from %s\n", gpGlobals->curtime,
+ pObject, pObject->GetClassname(), GetName() ) );
+
+ m_aObjects.FindAndRemove( pObject );
+ }
+ else
+ {
+ TRACE_OBJECT( UTIL_VarArgs( "%0.2f CTFTeam::RemoveObject couldn't remove %p:%s from %s\n", gpGlobals->curtime,
+ pObject, pObject->GetClassname(), GetName() ) );
+ }
+
+ NetworkStateChanged();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CTFTeam::GetNumObjects( int iObjectType )
+{
+ // Asking for a count of a specific object type?
+ if ( iObjectType > 0 )
+ {
+ int iCount = 0;
+ for ( int i = 0; i < GetNumObjects(); i++ )
+ {
+ CBaseObject *pObject = GetObject(i);
+ if ( pObject && pObject->GetType() == iObjectType )
+ {
+ iCount++;
+ }
+ }
+ return iCount;
+ }
+
+ return m_aObjects.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CBaseObject *CTFTeam::GetObject( int num )
+{
+ Assert( num >= 0 && num < m_aObjects.Count() );
+ return m_aObjects[ num ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Get a pointer to the specified TF team
+//-----------------------------------------------------------------------------
+CTFTeam *GetGlobalTFTeam( int iIndex )
+{
+ if ( iIndex < 0 || iIndex >= GetNumberOfTeams() )
+ return NULL;
+
+ return ( dynamic_cast< CTFTeam* >( g_Teams[iIndex] ) );
+}
+
+//-----------------------------------------------------------------------------
+// Set the team leader
+//-----------------------------------------------------------------------------
+bool CTFTeam::SetTeamLeader( CBasePlayer *pPlayer )
+{
+ Assert ( pPlayer );
+
+ // player must be on this team
+ if ( m_aPlayers.Find(pPlayer) == m_aPlayers.InvalidIndex() )
+ {
+ Assert( !"can't set a player as leader of a team he's not on" );
+ return false;
+ }
+
+ m_hLeader = pPlayer;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get Leader
+//-----------------------------------------------------------------------------
+CBasePlayer *CTFTeam::GetTeamLeader( void )
+{
+ return m_hLeader.Get();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Add the specified player to this team. Remove them from their current team, if any.
+//-----------------------------------------------------------------------------
+void CTFTeam::AddPlayer( CBasePlayer *pPlayer )
+{
+ BaseClass::AddPlayer( pPlayer );
+
+ if ( GetTeamLeader() == NULL )
+ {
+ SetTeamLeader( pPlayer );
+ }
+
+ TFGameRules()->TeamPlayerCountChanged( this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove this player from the team
+//-----------------------------------------------------------------------------
+void CTFTeam::RemovePlayer( CBasePlayer *pPlayer )
+{
+ BaseClass::RemovePlayer( pPlayer );
+
+ if ( pPlayer == m_hLeader.Get() )
+ {
+ m_hLeader = NULL;
+
+ if ( m_aPlayers.Count() > 0 )
+ {
+ // pick a new leader randomly
+ int iLeader = random->RandomInt( 0, m_aPlayers.Count()-1 );
+ SetTeamLeader( m_aPlayers.Element(iLeader) );
+ }
+ }
+
+ TFGameRules()->TeamPlayerCountChanged( this );
+} \ No newline at end of file