mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
764 lines
16 KiB
C++
764 lines
16 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
// dm_team.cpp: Deathmatch Team Manager.
|
|
|
|
#include "player.h"
|
|
#include "dm_team.h"
|
|
#include "dm_manager.h"
|
|
#include "playerstart.h"
|
|
|
|
typedef struct spawnsort_s {
|
|
PlayerStart *spawnpoint;
|
|
float fMetric;
|
|
} spawnsort_t;
|
|
|
|
static qboolean SpotWouldTelefrag( float *origin )
|
|
{
|
|
static Vector mins = Vector( -16, -16, 1 );
|
|
static Vector maxs = Vector( 16, 16, 97 );
|
|
trace_t trace;
|
|
|
|
trace = G_Trace( Vector(origin), mins, maxs, Vector(origin), NULL, MASK_PLAYERSOLID, qfalse, "SpotWouldTelefrag" );
|
|
|
|
if( trace.startsolid || trace.allsolid )
|
|
return qtrue;
|
|
else
|
|
return qfalse;
|
|
}
|
|
|
|
static int compare_spawnsort( const void *pe1, const void *pe2 )
|
|
{
|
|
float fDelta = ( ( spawnsort_t * )pe1 )->fMetric - ( ( spawnsort_t * )pe2 )->fMetric;
|
|
|
|
if( fDelta >= -0.001f )
|
|
{
|
|
if( fDelta <= 0.001f )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static PlayerStart *GetRandomSpawnpointFromList( spawnsort_t *pSpots, int nSpots )
|
|
{
|
|
int i = nSpots;
|
|
float fTotalMetric;
|
|
float fMinPosMetric;
|
|
float fChosen;
|
|
|
|
if( nSpots <= 0 ) {
|
|
return NULL;
|
|
}
|
|
|
|
qsort( pSpots, nSpots, sizeof( spawnsort_t ), compare_spawnsort );
|
|
|
|
if( pSpots[ 0 ].fMetric > 0.0f )
|
|
{
|
|
if( nSpots > 5 ) {
|
|
nSpots = 5;
|
|
}
|
|
|
|
fMinPosMetric = pSpots[ 0 ].fMetric * nSpots;
|
|
fTotalMetric = fMinPosMetric;
|
|
|
|
if( nSpots <= 1 )
|
|
{
|
|
fChosen = fMinPosMetric;
|
|
}
|
|
else
|
|
{
|
|
i = 0;
|
|
fTotalMetric = 0.0f;
|
|
|
|
for( i = 0; i < nSpots; i++ )
|
|
{
|
|
if( pSpots[ i ].fMetric <= 0.0f ) {
|
|
break;
|
|
}
|
|
|
|
fChosen = pSpots[ i ].fMetric * ( nSpots - i );
|
|
fTotalMetric += fChosen;
|
|
|
|
i++;
|
|
}
|
|
|
|
if( i < nSpots )
|
|
{
|
|
fChosen = fMinPosMetric;
|
|
}
|
|
|
|
fMinPosMetric = fTotalMetric;
|
|
}
|
|
|
|
fTotalMetric = ( fMinPosMetric - i * fChosen * 0.90f ) * G_Random();
|
|
for( i = 0; i < nSpots - 1; i++ )
|
|
{
|
|
fTotalMetric -= ( nSpots - i ) * pSpots[ i ].fMetric - ( fChosen * 0.90f );
|
|
if( fTotalMetric <= 0.0f ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pSpots[ i ].spawnpoint;
|
|
}
|
|
else
|
|
{
|
|
// return the spot anyway
|
|
return pSpots[ 0 ].spawnpoint;
|
|
}
|
|
}
|
|
|
|
void DM_Team::Reset( void )
|
|
{
|
|
m_spawnpoints.ClearObjectList();
|
|
m_players.ClearObjectList();
|
|
}
|
|
|
|
void DM_Team::AddDeaths( Player *player, int numDeaths )
|
|
{
|
|
if( level.intermissiontime || dmManager.GetTeamWin() )
|
|
return;
|
|
|
|
if( g_gametype->integer == GT_TEAM_ROUNDS || g_gametype->integer == GT_OBJECTIVE )
|
|
return;
|
|
|
|
player->AddDeaths( numDeaths );
|
|
|
|
if( m_teamnumber > TEAM_FREEFORALL )
|
|
m_iDeaths += numDeaths;
|
|
}
|
|
|
|
void DM_Team::AddKills( Player *player, int numKills )
|
|
{
|
|
if( level.intermissiontime || dmManager.GetTeamWin() )
|
|
return;
|
|
|
|
player->AddKills( numKills );
|
|
|
|
if( m_teamnumber > TEAM_FREEFORALL )
|
|
{
|
|
m_iKills += numKills;
|
|
|
|
if( g_gametype->integer == GT_TEAM_ROUNDS || g_gametype->integer == GT_OBJECTIVE )
|
|
player->AddDeaths( numKills );
|
|
else
|
|
m_teamwins += numKills;
|
|
}
|
|
}
|
|
|
|
void DM_Team::AddPlayer( Player *player )
|
|
{
|
|
m_players.AddObject( player );
|
|
}
|
|
|
|
void DM_Team::RemovePlayer( Player *player )
|
|
{
|
|
m_players.RemoveObject( player );
|
|
}
|
|
|
|
void DM_Team::TeamWin( void )
|
|
{
|
|
m_teamwins++;
|
|
m_wins_in_a_row++;
|
|
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
m_players.ObjectAt( i )->WonMatch();
|
|
}
|
|
|
|
UpdateTeamStatus();
|
|
|
|
if( m_teamnumber == TEAM_ALLIES )
|
|
{
|
|
gi.Cvar_Set( "g_scoreboardpicover", "textures/hud/allieswin" );
|
|
}
|
|
else if( m_teamnumber == TEAM_AXIS )
|
|
{
|
|
gi.Cvar_Set( "g_scoreboardpicover", "textures/hud/axiswin" );
|
|
}
|
|
}
|
|
|
|
void DM_Team::TeamLoss( void )
|
|
{
|
|
m_wins_in_a_row = 0;
|
|
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
m_players.ObjectAt( i )->LostMatch();
|
|
}
|
|
|
|
UpdateTeamStatus();
|
|
}
|
|
|
|
bool DM_Team::IsDead( void ) const
|
|
{
|
|
Player *player;
|
|
|
|
if( IsEmpty() )
|
|
{
|
|
if( dmManager.IsGameActive() ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if( !m_bHasSpawnedPlayers ) {
|
|
return false;
|
|
}
|
|
|
|
if( dmManager.AllowRespawn() ) {
|
|
return false;
|
|
}
|
|
|
|
for( int i = m_players.NumObjects(); i > 0; i-- )
|
|
{
|
|
player = m_players.ObjectAt( i );
|
|
|
|
if( player->IsSpectator() ) {
|
|
continue;
|
|
}
|
|
|
|
if( !player->IsDead() )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DM_Team::IsEmpty( void ) const
|
|
{
|
|
return m_players.NumObjects() <= 0;
|
|
}
|
|
|
|
bool DM_Team::IsReady( void ) const
|
|
{
|
|
return !NumNotReady();
|
|
}
|
|
|
|
int DM_Team::NumNotReady( void ) const
|
|
{
|
|
Player *player;
|
|
int num = 0;
|
|
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
player = m_players.ObjectAt( i );
|
|
|
|
if( player->IsReady() && !player->IsDead() )
|
|
i++;
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
int DM_Team::NumLivePlayers( void ) const
|
|
{
|
|
Player *player;
|
|
int num = 0;
|
|
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
player = m_players.ObjectAt( i );
|
|
|
|
if( !player->IsDead() && !player->IsSpectator() )
|
|
{
|
|
num++;
|
|
}
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
int DM_Team::TotalPlayersKills( void ) const
|
|
{
|
|
Player *player;
|
|
int iKills = 0;
|
|
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
player = m_players.ObjectAt( i );
|
|
|
|
if( !player->IsDead() && !player->IsSpectator() )
|
|
{
|
|
iKills += player->GetNumKills();
|
|
}
|
|
}
|
|
|
|
return iKills;
|
|
}
|
|
|
|
void DM_Team::TeamInvulnerable( void )
|
|
{
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
m_players.ObjectAt( i )->takedamage = DAMAGE_NO;
|
|
}
|
|
}
|
|
|
|
void DM_Team::BeginFight( void )
|
|
{
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
m_players.ObjectAt( i )->BeginFight();
|
|
}
|
|
}
|
|
|
|
void DM_Team::UpdateTeamStatus( void )
|
|
{
|
|
for( int i = 1; i <= m_players.NumObjects(); i++ )
|
|
{
|
|
m_players.ObjectAt( i )->UpdateStatus( va( "%d wins (%d in a row)", m_teamwins, m_wins_in_a_row ) );
|
|
}
|
|
}
|
|
|
|
float SpawnpointMetric_Ffa( const float *origin, DM_Team *dmTeam, const Player *player )
|
|
{
|
|
float fMinEnemyDistSquared = 23170.0f * 23170.0f;
|
|
int i;
|
|
int nPlayers = dmManager.PlayerCount();
|
|
float fDist;
|
|
|
|
for( i = 1; i < nPlayers; i++ )
|
|
{
|
|
Player *teammate = dmManager.GetPlayer( i );
|
|
if( teammate == player || teammate->IsDead() || teammate->IsSpectator() ) {
|
|
continue;
|
|
}
|
|
|
|
fDist = ( teammate->origin - Vector( origin ) ).lengthSquared();
|
|
|
|
if( fMinEnemyDistSquared > fDist ) {
|
|
fMinEnemyDistSquared = fDist;
|
|
}
|
|
}
|
|
|
|
return fMinEnemyDistSquared - ( G_Random( 0.25f ) + 1.0f ) * ( 1024.0f * 1024.0f );
|
|
}
|
|
|
|
float SpawnpointMetric_Team( const float *origin, DM_Team *dmTeam, const Player *player )
|
|
{
|
|
float fMinEnemyDistSquared = 23170.0f * 23170.0f;
|
|
float fSumFriendDistSquared = 0.0f;
|
|
float fDistSquared;
|
|
float fMetric;
|
|
int i;
|
|
int nPlayers = dmManager.PlayerCount();
|
|
int nFriends = 0;
|
|
|
|
for( i = 1; i < nPlayers; i++ )
|
|
{
|
|
Player *teammate = dmManager.GetPlayer( i );
|
|
if( teammate == player || teammate->IsDead() || teammate->IsSpectator() ) {
|
|
continue;
|
|
}
|
|
|
|
fDistSquared = ( teammate->origin - Vector( origin ) ).lengthSquared();
|
|
|
|
if( teammate->GetDM_Team() == dmTeam )
|
|
{
|
|
nFriends++;
|
|
fSumFriendDistSquared += fDistSquared;
|
|
}
|
|
else
|
|
{
|
|
if( fMinEnemyDistSquared > fDistSquared ) {
|
|
fMinEnemyDistSquared = fDistSquared;
|
|
}
|
|
}
|
|
}
|
|
|
|
fMetric = fMinEnemyDistSquared - ( G_Random( 0.25f ) + 1.0f ) * ( 1024.0f * 1024.0f );
|
|
|
|
if( nFriends )
|
|
{
|
|
fMetric += 0.25f * ( ( 23170.0f * 23170.0f ) - fSumFriendDistSquared / nFriends );
|
|
}
|
|
|
|
return fMetric;
|
|
}
|
|
|
|
float SpawnpointMetric_Objective( const float *origin, DM_Team *dmTeam, const Player *player )
|
|
{
|
|
return rand() * 0.0000000005f;
|
|
}
|
|
|
|
PlayerStart *DM_Team::GetRandomFfaSpawnpoint( Player *player )
|
|
{
|
|
return GetRandomSpawnpointWithMetric( player, SpawnpointMetric_Ffa );
|
|
}
|
|
|
|
PlayerStart *DM_Team::GetRandomTeamSpawnpoint( Player *player )
|
|
{
|
|
return GetRandomSpawnpointWithMetric( player, SpawnpointMetric_Team );
|
|
}
|
|
|
|
PlayerStart *DM_Team::GetRandomObjectiveSpawnpoint( Player *player )
|
|
{
|
|
return GetRandomSpawnpointWithMetric( player, SpawnpointMetric_Objective );
|
|
}
|
|
|
|
float DM_Team::PlayersRangeFromSpot( PlayerStart *spot )
|
|
{
|
|
float bestplayerdistance = 9999999.0f;
|
|
Vector vDist;
|
|
int i;
|
|
gentity_t *ent;
|
|
Player *player;
|
|
|
|
if( g_gametype->integer > GT_FFA ) {
|
|
return bestplayerdistance;
|
|
}
|
|
|
|
// find the nearest player from the post
|
|
for( i = 0, ent = g_entities; i < game.maxclients; i++, ent++ )
|
|
{
|
|
if( !ent->client || !ent->entity ) {
|
|
continue;
|
|
}
|
|
|
|
player = ( Player * )ent->entity;
|
|
if( !player->IsDead() && !player->IsSpectator() && m_teamnumber != player->GetTeam() )
|
|
{
|
|
vDist = spot->origin - player->origin;
|
|
if( bestplayerdistance > vDist.length() )
|
|
bestplayerdistance = vDist.length();
|
|
}
|
|
}
|
|
|
|
return bestplayerdistance;
|
|
}
|
|
|
|
PlayerStart *DM_Team::FarthestSpawnPoint( void )
|
|
{
|
|
int i;
|
|
int iNumPoints;
|
|
float bestdistance;
|
|
float bestplayerdistance;
|
|
PlayerStart *pSpot;
|
|
PlayerStart *pBestSpot;
|
|
PlayerStart *pSpot2;
|
|
PlayerStart *pSpot3;
|
|
|
|
bestplayerdistance = 0.0f;
|
|
pBestSpot = NULL;
|
|
pSpot2 = NULL;
|
|
pSpot3 = NULL;
|
|
iNumPoints = m_spawnpoints.NumObjects();
|
|
|
|
for( i = 1; i <= iNumPoints; i++ )
|
|
{
|
|
pSpot = m_spawnpoints.ObjectAt( i );
|
|
|
|
bestdistance = PlayersRangeFromSpot( m_spawnpoints.ObjectAt( i ) );
|
|
if( bestdistance > bestplayerdistance )
|
|
{
|
|
bestplayerdistance = bestdistance;
|
|
pSpot3 = pSpot2;
|
|
pSpot2 = pBestSpot;
|
|
pBestSpot = pSpot;
|
|
}
|
|
}
|
|
|
|
if( pSpot3 && G_Random() < 0.2f )
|
|
{
|
|
return pSpot3;
|
|
}
|
|
else if( pSpot2 && G_Random() < 0.3f )
|
|
{
|
|
return pSpot2;
|
|
}
|
|
else
|
|
{
|
|
return pBestSpot;
|
|
}
|
|
}
|
|
|
|
PlayerStart *DM_Team::GetRandomSpawnpoint( void )
|
|
{
|
|
PlayerStart *spot = NULL;
|
|
int numPoints = m_spawnpoints.NumObjects();
|
|
|
|
if( numPoints )
|
|
{
|
|
spot = FarthestSpawnPoint();
|
|
if( !spot )
|
|
{
|
|
spot = m_spawnpoints.ObjectAt( ( int )( G_Random( numPoints ) + 1.0f ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
warning( "DM_Team::GetRandomSpawnpoint", "No spawnpoints found\n" );
|
|
spot = NULL;
|
|
}
|
|
|
|
return spot;
|
|
}
|
|
|
|
PlayerStart *DM_Team::GetRandomSpawnpointWithMetric( Player *player, float( *MetricFunction ) ( const float *origin, DM_Team *dmTeam, const Player *player ) )
|
|
{
|
|
static float offset[ 4 ][ 3 ];
|
|
spawnsort_t points[ 1024 ];
|
|
PlayerStart *spot = NULL;
|
|
int numSpots = 0;
|
|
int iPoint = 0;
|
|
|
|
for( int i = 1; i <= m_spawnpoints.NumObjects(); i++ )
|
|
{
|
|
spot = m_spawnpoints.ObjectAt( i );
|
|
if( spot->m_bForbidSpawns || player->GetLastSpawnpoint() == spot ) {
|
|
continue;
|
|
}
|
|
|
|
if( !SpotWouldTelefrag( spot->origin ) )
|
|
{
|
|
points[ numSpots ].spawnpoint = spot;
|
|
points[ numSpots ].fMetric = MetricFunction( spot->origin, this, player );
|
|
numSpots++;
|
|
|
|
if( numSpots >= ( sizeof( points ) / sizeof( points[ 0 ] ) ) ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
spot = GetRandomSpawnpointFromList( points, numSpots );
|
|
if( spot ) {
|
|
return spot;
|
|
}
|
|
|
|
numSpots = 0;
|
|
|
|
for( int i = 1; i <= m_spawnpoints.NumObjects(); i++ )
|
|
{
|
|
spot = m_spawnpoints.ObjectAt( i );
|
|
if( spot->m_bForbidSpawns ) {
|
|
continue;
|
|
}
|
|
|
|
for( int j = 0; j < sizeof( offset ) / sizeof( offset[ 0 ] ); j++ )
|
|
{
|
|
Vector vNewSpawn = spot->origin + offset[ j ];
|
|
|
|
if( G_SightTrace(
|
|
spot->origin,
|
|
player->mins,
|
|
player->maxs,
|
|
vNewSpawn,
|
|
( Entity * )NULL,
|
|
( Entity * )NULL,
|
|
MASK_PLAYERSOLID,
|
|
qfalse,
|
|
"DM_Team::GetRandomSpawnpointWithMetric" ) == 1 )
|
|
{
|
|
Vector vEnd = vNewSpawn - Vector( 0, 0, 64 );
|
|
|
|
trace_t trace = G_Trace(
|
|
vNewSpawn,
|
|
player->mins,
|
|
player->maxs,
|
|
vEnd,
|
|
player,
|
|
MASK_PLAYERSOLID,
|
|
qfalse,
|
|
"TempSpawnPoint" );
|
|
|
|
if( !trace.allsolid && !trace.startsolid &&
|
|
trace.fraction != 1.0f && trace.fraction != 1.0f &&
|
|
trace.plane.dist >= 0.8f )
|
|
{
|
|
points[ numSpots ].spawnpoint = new PlayerStart;
|
|
points[ numSpots ].spawnpoint->setOrigin( trace.endpos );
|
|
points[ numSpots ].spawnpoint->setAngles( spot->angles );
|
|
points[ numSpots ].fMetric = MetricFunction( vNewSpawn, this, player );
|
|
|
|
if( numSpots >= ( sizeof( points ) / sizeof( points[ 0 ] ) ) ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
spot = GetRandomSpawnpointFromList( points, numSpots );
|
|
for( int i = 0; i < numSpots; i++ )
|
|
{
|
|
// delete all created spawnpoint
|
|
if( points[ numSpots ].spawnpoint != spot ) {
|
|
delete points[ numSpots ].spawnpoint;
|
|
}
|
|
}
|
|
|
|
if( spot ) {
|
|
return spot;
|
|
}
|
|
|
|
numSpots = 0;
|
|
|
|
for( int i = 1; i <= m_spawnpoints.NumObjects(); i++ )
|
|
{
|
|
spot = m_spawnpoints.ObjectAt( i );
|
|
if( !spot->m_bForbidSpawns && player->GetLastSpawnpoint() != spot ) {
|
|
continue;
|
|
}
|
|
|
|
if( !SpotWouldTelefrag( spot->origin ) )
|
|
{
|
|
points[ numSpots ].spawnpoint = spot;
|
|
points[ numSpots ].fMetric = MetricFunction( spot->origin, this, player );
|
|
|
|
if( numSpots >= ( sizeof( points ) / sizeof( points[ 0 ] ) ) ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return GetRandomSpawnpointFromList( points, numSpots );
|
|
}
|
|
|
|
void DM_Team::InitSpawnPoints
|
|
(
|
|
void
|
|
)
|
|
{
|
|
int i;
|
|
|
|
if( teamType == TEAM_SPECTATOR )
|
|
{
|
|
for( i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i-- )
|
|
{
|
|
PlayerStart *spawnpoint = ( PlayerStart * )level.m_SimpleArchivedEntities.ObjectAt( i );
|
|
const char *classname = spawnpoint->getClassID();
|
|
|
|
if( !Q_stricmp( classname, "info_player_deathmatch" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
else if( !Q_stricmp( classname, "info_player_intermission" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if( g_gametype->integer <= GT_FFA )
|
|
{
|
|
for( i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i-- )
|
|
{
|
|
PlayerStart *spawnpoint = ( PlayerStart * )level.m_SimpleArchivedEntities.ObjectAt( i );
|
|
const char *classname = spawnpoint->getClassID();
|
|
|
|
if( !Q_stricmp( classname, "info_player_deathmatch" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
}
|
|
|
|
if( m_spawnpoints.NumObjects() <= 1 )
|
|
{
|
|
// Try with team spawnpoints
|
|
for( i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i-- )
|
|
{
|
|
PlayerStart *spawnpoint = ( PlayerStart * )level.m_SimpleArchivedEntities.ObjectAt( i );
|
|
const char *classname = spawnpoint->getClassID();
|
|
|
|
if( !Q_stricmp( classname, "info_player_allied" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
else if( !Q_stricmp( classname, "info_player_axis" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( g_gametype->integer >= GT_TEAM )
|
|
{
|
|
if( teamType >= TEAM_ALLIES )
|
|
{
|
|
for( i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i-- )
|
|
{
|
|
PlayerStart *spawnpoint = ( PlayerStart * )level.m_SimpleArchivedEntities.ObjectAt( i );
|
|
const char *classname = spawnpoint->getClassID();
|
|
|
|
if( teamType == TEAM_ALLIES && !Q_stricmp( classname, "info_player_allied" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
else if( teamType == TEAM_AXIS && !Q_stricmp( classname, "info_player_axis" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !m_spawnpoints.NumObjects() )
|
|
{
|
|
// Try with info_player_deathmatch
|
|
for( int i = level.m_SimpleArchivedEntities.NumObjects(); i > 0; i-- )
|
|
{
|
|
PlayerStart *spawnpoint = ( PlayerStart * )level.m_SimpleArchivedEntities.ObjectAt( i );
|
|
const char *classname = spawnpoint->getClassID();
|
|
|
|
if( !Q_stricmp( classname, "info_player_deathmatch" ) )
|
|
{
|
|
m_spawnpoints.AddObject( spawnpoint );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DM_Team::DM_Team()
|
|
{
|
|
m_countdown = 0;
|
|
m_teamwins = 0;
|
|
m_wins_in_a_row = 0;
|
|
m_teamnumber = -1;
|
|
m_iKills = 0;
|
|
m_iDeaths = 0;
|
|
m_bHasSpawnedPlayers = false;
|
|
}
|
|
|
|
DM_Team::~DM_Team()
|
|
{
|
|
|
|
}
|
|
|
|
CLASS_DECLARATION( Listener, DM_Team, NULL )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|