1164 lines
30 KiB
C++
1164 lines
30 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /EF2/Code/DLLs/game/mp_modeTeamBase.cpp $
|
|
// $Revision:: 59 $
|
|
// $Author:: Singlis $
|
|
// $Date:: 9/26/03 2:36p $
|
|
//
|
|
// Copyright (C) 2002 by Ritual Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source may not be distributed and/or modified without
|
|
// expressly written permission by Ritual Entertainment, Inc.
|
|
//
|
|
// Description:
|
|
//
|
|
|
|
#include "_pch_cpp.h"
|
|
|
|
#include "mp_manager.hpp"
|
|
#include "mp_modeBase.hpp"
|
|
#include "mp_modeTeamBase.hpp"
|
|
|
|
|
|
CLASS_DECLARATION( MultiplayerModeBase, ModeTeamBase, NULL )
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------
|
|
// T E A M A R E N A
|
|
//-----------------------------------------------------------------
|
|
|
|
//================================================================
|
|
// Name: ModeTeamBase
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Constructor
|
|
//
|
|
// Parameters: const str& -- name of the arena
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
ModeTeamBase::ModeTeamBase()
|
|
{
|
|
_maxTeams = 2;
|
|
|
|
_leadTeam = NULL;
|
|
|
|
_useTeamSpawnpoints = false;
|
|
|
|
_redTeamIconIndex = gi.imageindex( "sysimg/icons/mp/team_red" );
|
|
_blueTeamIconIndex = gi.imageindex( "sysimg/icons/mp/team_blue" );
|
|
|
|
_redTeamHudIconIndex = gi.imageindex( "sysimg/icons/mp/team_red_hud" );
|
|
_blueTeamHudIconIndex = gi.imageindex( "sysimg/icons/mp/team_blue_hud" );
|
|
|
|
_redTeamSpectatorHudIconIndex = gi.imageindex( "sysimg/icons/mp/team_red_spectator" );
|
|
_blueTeamSpectatorHudIconIndex = gi.imageindex( "sysimg/icons/mp/team_blue_spectator" );
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: ~ModeTeamBase
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Destructor
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
|
|
ModeTeamBase::~ModeTeamBase()
|
|
{
|
|
_deleteTeams();
|
|
}
|
|
|
|
void ModeTeamBase::init( int maxPlayers )
|
|
{
|
|
MultiplayerModeBase::init( maxPlayers );
|
|
|
|
multiplayerManager.cacheMultiplayerFiles( "mp_teamBase" );
|
|
}
|
|
|
|
//================================================================
|
|
// Name: isEndOfMatch
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Determines if either team has met the frag limit.
|
|
// If so, announces a winner (should the base team
|
|
// arena be so bold?).
|
|
//
|
|
// If there is no frag limit set, no check is made.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: bool -- true if the match has ended based on fraglimit
|
|
//
|
|
//================================================================
|
|
bool ModeTeamBase::isEndOfMatch( void )
|
|
{
|
|
if (!getPointLimit())
|
|
{
|
|
return false ;
|
|
}
|
|
|
|
for (int idx=1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
Team* team = _teamList.ObjectAt(idx);
|
|
if (team->getDeaths() > getPointLimit())
|
|
{
|
|
multiplayerManager.centerPrintAllClients(va("$$%s$$ $$TeamLoses$$\n", team->getName().c_str() ), CENTERPRINT_IMPORTANCE_NORMAL );
|
|
|
|
if ( team->getName() == "Red" )
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_redtlose.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, NULL, 1.5f );
|
|
else
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_bltlose.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, NULL, 1.5f );
|
|
|
|
return true ;
|
|
}
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//================================================================
|
|
// Name: AddPlayer
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds a player to the arena. If force join is on,
|
|
// this player will be force to join with the fewest
|
|
// players.
|
|
//
|
|
// Parameters: Player* -- player to add
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::AddPlayer( Player *player )
|
|
{
|
|
// Make sure everything is ok
|
|
|
|
assert(player);
|
|
|
|
if ( !player )
|
|
{
|
|
warning("ModeDeathmatch::AddPlayer", "NULL Player\n");
|
|
return ;
|
|
}
|
|
|
|
// Make sure player hasn't alrady been added
|
|
|
|
if ( !needToAddPlayer( player ) )
|
|
return;
|
|
|
|
MultiplayerModeBase::AddPlayer(player);
|
|
|
|
// Add player to a team or make him a spectator
|
|
|
|
if ( playersLastTeam[ player->entnum ].length() )
|
|
{
|
|
addPlayerToTeam( player, getTeam( playersLastTeam[ player->entnum ] ) );
|
|
}
|
|
else if ( !multiplayerManager.checkFlag( MP_FLAG_NO_AUTO_JOIN_TEAM ) || multiplayerManager.checkFlag( MP_FLAG_AUTO_BALANCE_TEAMS ) || ( player->edict->svflags & SVF_BOT ) )
|
|
{
|
|
Team* pickedTeam = 0 ;
|
|
Team* team = 0 ;
|
|
int minimumPlayers = 0 ;
|
|
|
|
// Automatically add this player to one of the teams
|
|
|
|
for (int idx = 1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
team = _teamList.ObjectAt(idx);
|
|
|
|
assert(team);
|
|
if (!team)
|
|
{
|
|
continue ;
|
|
}
|
|
|
|
int players = team->getActivePlayers();
|
|
if ( (players < minimumPlayers) || (!pickedTeam) )
|
|
{
|
|
pickedTeam = team ;
|
|
minimumPlayers = players ;
|
|
}
|
|
}
|
|
|
|
if (pickedTeam)
|
|
{
|
|
addPlayerToTeam( player, pickedTeam );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Not force joining of teams, start as a spectator
|
|
|
|
addPlayerToTeam( player, NULL );
|
|
}
|
|
|
|
//if ( _playerGameData[ player->entnum ]._currentTeam )
|
|
// addPlayerToTeam( player, _playerGameData[ player->entnum ]._currentTeam );
|
|
|
|
// If the game hasn't started yet just make the player a spectator
|
|
|
|
if ( !_gameStarted )
|
|
{
|
|
multiplayerManager.makePlayerSpectator( player );
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::addPlayerToTeam( Player *player, Team *team )
|
|
{
|
|
Team *oldTeam;
|
|
Entity *spawnPoint;
|
|
|
|
|
|
MultiplayerModeBase::AddPlayer(player);
|
|
|
|
oldTeam = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team && ( oldTeam != team ) )
|
|
{
|
|
// Inform all of the players that the player has changed teams
|
|
|
|
multiplayerManager.HUDPrintAllClients(va("%s $$Joined$$ $$%s$$ $$Team$$.\n", player->client->pers.netname, team->getName().c_str() ) );
|
|
}
|
|
|
|
if ( oldTeam )
|
|
{
|
|
_playerGameData[ player->entnum ]._currentTeam = NULL;
|
|
|
|
player->SurfaceCommand( "all", "-skin1" );
|
|
player->SurfaceCommand( "all", "-skin2" );
|
|
|
|
oldTeam->RemovePlayer(player);
|
|
}
|
|
|
|
if ( team )
|
|
{
|
|
// Since the player is now on a team add him to the game
|
|
|
|
if ( _gameStarted )
|
|
multiplayerManager.playerEnterArena( player->entnum, player->health );
|
|
else
|
|
multiplayerManager.makePlayerSpectator( player );
|
|
|
|
// Add the player to the team
|
|
|
|
team->AddPlayer(player);
|
|
|
|
_playerGameData[ player->entnum ]._currentTeam = team;
|
|
|
|
updatePlayerSkin( player );
|
|
|
|
if ( team->getName() == "Red" )
|
|
{
|
|
if ( multiplayerManager.isPlayerSpectator( player ) )
|
|
multiplayerManager.setTeamHud( player, "mp_teamredspec" );
|
|
else
|
|
multiplayerManager.setTeamHud( player, "mp_teamred" );
|
|
}
|
|
else
|
|
{
|
|
if ( multiplayerManager.isPlayerSpectator( player ) )
|
|
multiplayerManager.setTeamHud( player, "mp_teambluespec" );
|
|
else
|
|
multiplayerManager.setTeamHud( player, "mp_teamblue" );
|
|
}
|
|
|
|
multiplayerManager.playerSpawned( player );
|
|
|
|
playersLastTeam[ player->entnum ] = team->getName();
|
|
}
|
|
else
|
|
{
|
|
// No team selected so make the player a spectator
|
|
|
|
multiplayerManager.makePlayerSpectator( player, SPECTATOR_TYPE_FOLLOW, true );
|
|
|
|
/* team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( !team )
|
|
multiplayerManager.setTeamHud( player, "mp_teamspec" );
|
|
else if ( team->getName() == "Red" )
|
|
multiplayerManager.setTeamHud( player, "mp_teamredspec" );
|
|
else
|
|
multiplayerManager.setTeamHud( player, "mp_teambluespec" ); */
|
|
}
|
|
|
|
// Warp player to a spawn point
|
|
|
|
spawnPoint = getSpawnPoint( player );
|
|
|
|
if ( spawnPoint )
|
|
{
|
|
player->WarpToPoint( spawnPoint );
|
|
}
|
|
|
|
if ( team && _gameStarted )
|
|
{
|
|
KillBox( player );
|
|
|
|
ActivatePlayer( player );
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::changeTeams( Player *player, Team *team )
|
|
{
|
|
RemovePlayer( player );
|
|
addPlayerToTeam( player, team );
|
|
}
|
|
|
|
void ModeTeamBase::respawnPlayer( Player *player )
|
|
{
|
|
Entity *spawnPoint;
|
|
|
|
if ( !player )
|
|
{
|
|
assert(player);
|
|
warning("ModeDeathmatch::respawnPlayer", "NULL player\n");
|
|
return;
|
|
}
|
|
|
|
// Make sure we are allowed to respawn the player
|
|
|
|
if ( !multiplayerManager.checkRule( "respawnPlayer", true, player ) )
|
|
{
|
|
if ( multiplayerManager.checkRule( "allowSpectator", true ) )
|
|
{
|
|
multiplayerManager.makePlayerSpectator( player );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
MultiplayerModeBase::respawnPlayer( player );
|
|
|
|
multiplayerManager.initPlayer( player );
|
|
|
|
spawnPoint = getSpawnPoint( player );
|
|
|
|
if ( spawnPoint )
|
|
{
|
|
player->WarpToPoint( spawnPoint );
|
|
}
|
|
|
|
KillBox( player );
|
|
|
|
ActivatePlayer( player );
|
|
}
|
|
|
|
Entity *ModeTeamBase::getSpawnPoint( Player *player )
|
|
{
|
|
Entity *spawnPoint = NULL;
|
|
int i;
|
|
int numSpawnPoints = 0;
|
|
str spawnpointName;
|
|
int randomStartingSpot;
|
|
int spawnPointIndex;
|
|
|
|
|
|
// Determine what kind of spawn point we want to use
|
|
|
|
if ( multiplayerManager.checkRule( "spawnpoints-special", false, player ) )
|
|
{
|
|
spawnpointName = multiplayerManager.getSpawnPointType( player );
|
|
|
|
numSpawnPoints = getNumNamedSpawnpoints( spawnpointName );
|
|
}
|
|
|
|
if ( !numSpawnPoints && multiplayerManager.checkRule( "spawnpoints-team", _useTeamSpawnpoints ) && _playerGameData[ player->entnum ]._currentTeam )
|
|
{
|
|
if ( stricmp( _playerGameData[ player->entnum ]._currentTeam->getName(), "red" ) == 0 )
|
|
spawnpointName = "red";
|
|
else
|
|
spawnpointName = "blue";
|
|
|
|
numSpawnPoints = getNumNamedSpawnpoints( spawnpointName );
|
|
}
|
|
|
|
if ( !numSpawnPoints )
|
|
{
|
|
spawnpointName = "";
|
|
|
|
numSpawnPoints = getNumNamedSpawnpoints( spawnpointName );
|
|
}
|
|
|
|
randomStartingSpot = ( (int)( G_Random() * numSpawnPoints ) );
|
|
|
|
for( i = 0 ; i < numSpawnPoints ; i++ )
|
|
{
|
|
spawnPointIndex = ( randomStartingSpot + i ) % numSpawnPoints;
|
|
|
|
spawnPoint = getNamedSpawnpointbyIndex( spawnpointName, spawnPointIndex );
|
|
|
|
// Make sure we don't telefrag someone on our team
|
|
|
|
if ( spawnPoint )
|
|
{
|
|
int j;
|
|
int num;
|
|
int touch[ MAX_GENTITIES ];
|
|
gentity_t *hit;
|
|
Vector min;
|
|
Vector max;
|
|
bool badSpot;
|
|
|
|
min = spawnPoint->origin + player->mins + Vector( 0, 0, 1 );
|
|
max = spawnPoint->origin + player->maxs + Vector( 0, 0, 1 );
|
|
|
|
num = gi.AreaEntities( min, max, touch, MAX_GENTITIES, qfalse );
|
|
|
|
badSpot = false;
|
|
|
|
for( j = 0 ; j < num ; j++ )
|
|
{
|
|
hit = &g_entities[ touch[ j ] ];
|
|
|
|
if ( !hit->inuse || ( hit->entity == player ) || !hit->entity || ( hit->entity == world ) || ( !hit->entity->edict->solid ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( hit->entity->isSubclassOf( Player ) )
|
|
{
|
|
badSpot = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( badSpot )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// This is a good spawn point so use it
|
|
|
|
return spawnPoint;
|
|
}
|
|
|
|
// Just return the last spawn point found
|
|
|
|
return spawnPoint;
|
|
}
|
|
|
|
//================================================================
|
|
// Name: AddTeam
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds a team to the arena. Checks to ensure that the
|
|
// max number of teams has not yet been exceeded.
|
|
//
|
|
// Parameters: const str& -- new name of team
|
|
//
|
|
// Returns: Team* -- Created team (NULL if failed to create)
|
|
//
|
|
//================================================================
|
|
Team* ModeTeamBase::AddTeam( const str& teamName )
|
|
{
|
|
Team* team = _findTeamByName(teamName);
|
|
|
|
if (team)
|
|
{
|
|
warning( "ModeTeamBase::AddTeam", va("Team %s already exists\n", teamName.c_str() ) );
|
|
return NULL ;
|
|
}
|
|
|
|
team = new Team(teamName);
|
|
team->setMaxPlayers(getMaxPlayers() / getMaxTeams());
|
|
_teamList.AddObject( team );
|
|
|
|
return team ;
|
|
}
|
|
|
|
Team *ModeTeamBase::getTeam( const str & teamName )
|
|
{
|
|
int i;
|
|
Team *team;
|
|
|
|
for ( i = 1 ; i <= _teamList.NumObjects() ; i++ )
|
|
{
|
|
team = _teamList.ObjectAt( i );
|
|
|
|
if ( team->getName() == teamName )
|
|
{
|
|
return team;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: RemoveTeam
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Removes and deletes the team specified by name from
|
|
// the arena. Calls _deleteTeam to do actual removal.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Returns:
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::RemoveTeam( const str& teamName )
|
|
{
|
|
Team* team = _findTeamByName(teamName);
|
|
_deleteTeam(team);
|
|
}
|
|
|
|
|
|
|
|
//================================================================
|
|
// Name: AddTeamStartingAmmo
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds team-specific ammo. This enables a particular
|
|
// team to receive a specific amount and/or type of ammo.
|
|
// Calls _addTeamStartingAmmo() to actually give it to the team.
|
|
//
|
|
// Parameters: const str& teamName -- team to receive the ammo
|
|
// const str& ammoName -- name of ammo to give
|
|
// int amount -- amount of ammo to give
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::AddTeamStartingAmmo( const str& teamName, const str& ammoName, int amount )
|
|
{
|
|
Team* team = _findTeamByName(teamName);
|
|
SimpleAmmoType ammoType(ammoName, amount);
|
|
_addTeamStartingAmmo(team, ammoType);
|
|
}
|
|
|
|
//================================================================
|
|
// Name: AddTeamStartingWeapon
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds team-specific weapon. This enables a particular
|
|
// team to receive a specific weapon. Calls _addTeamStartingWeapon()
|
|
// to actually give it to the team.
|
|
//
|
|
// Parameters: const str& teamName -- team to receive the ammo
|
|
// const str& weaponName -- name of weapon to give
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::AddTeamStartingWeapon( const str& teamName, const str& weaponName )
|
|
{
|
|
Team* team = _findTeamByName(teamName);
|
|
_addTeamStartingWeapon(team, weaponName);
|
|
}
|
|
|
|
//================================================================
|
|
// Name: setTeamStartingHealth
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Sets the starting health for the team. Calls
|
|
// _setTeamStartingHealth to do actual work.
|
|
//
|
|
// Parameters: const str& -- team name
|
|
// unsigned int -- amount of health
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::SetTeamStartingHealth( const str &teamName, unsigned int startingHealth )
|
|
{
|
|
Team* team = _findTeamByName(teamName);
|
|
_setTeamStartingHealth(team, startingHealth);
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
// P R O T E C T E D M E T H O D S
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
//================================================================
|
|
// Name: _addTeamStartingAmmo
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds the specified ammo to the specified team.
|
|
//
|
|
// Parameters: Team* -- team to receive the ammo
|
|
// SimpleAmmoType -- ammo to receive
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_addTeamStartingAmmo( Team* team, const SimpleAmmoType &ammo )
|
|
{
|
|
// Check for valid team
|
|
assert(team);
|
|
if (!team)
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingAmmo", "NULL team passed\n");
|
|
return ;
|
|
}
|
|
|
|
// Check for valid ammo type
|
|
assert(ammo.type.length());
|
|
if (!ammo.type.length())
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingAmmo", "No ammo type specified\n");
|
|
return ;
|
|
}
|
|
|
|
// Check for valid amount
|
|
assert(ammo.amount > 0);
|
|
if (ammo.amount < 0)
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingAmmo", "Negative ammo amount specified\n");
|
|
return ;
|
|
}
|
|
|
|
team->AddStartingAmmo(ammo);
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: _addTeamStartingWeapon
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Adds the specified weapon to the specified team.
|
|
//
|
|
// Parameters: Team* -- team to receive the ammo
|
|
// const str& -- weapon to receive
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_addTeamStartingWeapon( Team* team, const str& weaponName )
|
|
{
|
|
// Check for valid team
|
|
assert(team);
|
|
if (!team)
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingWeapon", "NULL team passed\n");
|
|
return ;
|
|
}
|
|
|
|
// Check for valid weaponName
|
|
assert(weaponName.length());
|
|
if (!weaponName.length())
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingWeapon", "No weapon specified\n");
|
|
return ;
|
|
}
|
|
|
|
team->AddStartingWeapon(weaponName);
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: _setTeamStartingHealth
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Sets the specified team's starting health to the
|
|
// specified value. A starting health of 0 means to
|
|
// use the arena's default value (typicaly 100).
|
|
//
|
|
// Parameters: Team* -- team to affect
|
|
// unsigned int -- amount of starting health (must be >= 0)
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_setTeamStartingHealth( Team* team, unsigned int startingHealth )
|
|
{
|
|
// Check for valid team
|
|
assert(team);
|
|
if (!team)
|
|
{
|
|
warning("ModeTeamBase::_addTeamStartingWeapon", "NULL team passed\n");
|
|
return ;
|
|
}
|
|
|
|
/* assert(startingHealth >= 0);
|
|
if (startingHealth < 0)
|
|
{
|
|
warning("ModeTeamBase::_setTeamStartingHealth", va("Cannot set health to %d\n", startingHealth));
|
|
return ;
|
|
} */
|
|
|
|
team->setStartingHealth(startingHealth);
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _deleteTeams
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Deletes all the teams currently in the arena.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_deleteTeams()
|
|
{
|
|
for (int idx = 1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
Team* team = _teamList.ObjectAt(idx);
|
|
_deleteTeam(team);
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _deleteTeam
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Removes the specified team from the arena and deletes it.
|
|
// Minimal error checking since it is an internal function.
|
|
//
|
|
// Parameters: Team* -- team to remove and delete
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_deleteTeam( Team* team )
|
|
{
|
|
assert(team);
|
|
if (!team)
|
|
{
|
|
warning("ModeTeamBase::_removeTeam", "NULL Team passed\n");
|
|
return ;
|
|
}
|
|
|
|
_teamList.RemoveObject(team);
|
|
delete team ;
|
|
}
|
|
|
|
|
|
|
|
//================================================================
|
|
// Name: _beginMatch
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Called when a match begins. Calls BeginMatch on
|
|
// every team in the arena. The teams are responsible
|
|
// for preparing the participants for battle.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_beginMatch()
|
|
{
|
|
for (int idx = 1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
Team* team = _teamList.ObjectAt(idx);
|
|
team->BeginMatch();
|
|
}
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: _endMatch
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Called when a match ends. Calls EndMatch on
|
|
// every team in the arena. The teams are responsible
|
|
// for removing the players from battle-readiness.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ModeTeamBase::_endMatch()
|
|
{
|
|
for (int idx = 1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
Team* team = _teamList.ObjectAt(idx);
|
|
team->EndMatch();
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::declareWinner( void )
|
|
{
|
|
int redPoints;
|
|
int bluePoints;
|
|
|
|
redPoints = getTeamPoints( "Red" );
|
|
bluePoints = getTeamPoints( "Blue" );
|
|
|
|
if ( redPoints > bluePoints )
|
|
{
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_rtwins.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, NULL, 1.5f );
|
|
}
|
|
else if ( bluePoints > redPoints )
|
|
{
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_btwins.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, NULL, 1.5f );
|
|
}
|
|
/* else
|
|
{
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_matover.mp3" );
|
|
} */
|
|
}
|
|
|
|
|
|
//================================================================
|
|
// Name: _findTeamByName
|
|
// Class: ModeTeamBase
|
|
//
|
|
// Description: Retrieves a pointer to the team having the specified name.
|
|
//
|
|
// Parameters: const str& -- name of the team to retrieve
|
|
//
|
|
// Returns: Team* -- pointer to team found (NULL if not found)
|
|
//
|
|
//================================================================
|
|
Team* ModeTeamBase::_findTeamByName( const str& teamName )
|
|
{
|
|
assert(teamName.length());
|
|
if (!teamName.length())
|
|
{
|
|
warning("ModeTeamBase::_findTeamByName", "Team name not specified\n");
|
|
return NULL ;
|
|
}
|
|
|
|
Team* team = NULL ;
|
|
for (int idx = 1; idx <= _teamList.NumObjects(); idx++)
|
|
{
|
|
team = _teamList.ObjectAt(idx);
|
|
if ( stricmp( team->getName().c_str(), teamName.c_str() ) == 0 )
|
|
{
|
|
return team ;
|
|
}
|
|
}
|
|
|
|
return NULL ;
|
|
}
|
|
|
|
int ModeTeamBase::getIcon( Player *player, int statNum, int value )
|
|
{
|
|
/* if ( statNum == STAT_MP_TEAMHUD_ICON )
|
|
{
|
|
Team *team;
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
{
|
|
// Player is on a team so return the appropriate team icon
|
|
|
|
if ( multiplayerManager.isPlayerSpectator( player ) )
|
|
{
|
|
if ( team->getName() == "Red" )
|
|
return _redTeamSpectatorHudIconIndex;
|
|
else if ( team->getName() == "Blue" )
|
|
return _blueTeamSpectatorHudIconIndex;
|
|
}
|
|
else
|
|
{
|
|
if ( team->getName() == "Red" )
|
|
return _redTeamHudIconIndex;
|
|
else if ( team->getName() == "Blue" )
|
|
return _blueTeamHudIconIndex;
|
|
}
|
|
}
|
|
}
|
|
else */ if ( statNum == STAT_MP_TEAM_ICON )
|
|
{
|
|
Team *team;
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
{
|
|
// Player is on a team so return the appropriate team icon
|
|
|
|
if ( team->getName() == "Red" )
|
|
return _redTeamIconIndex;
|
|
else if ( team->getName() == "Blue" )
|
|
return _blueTeamIconIndex;
|
|
}
|
|
}
|
|
else if ( statNum == STAT_MP_OTHERTEAM_ICON )
|
|
{
|
|
Team *team;
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
{
|
|
// Player is on a team so return the appropriate team icon
|
|
|
|
if ( team->getName() == "Red" )
|
|
return _blueTeamIconIndex;
|
|
else if ( team->getName() == "Blue" )
|
|
return _redTeamIconIndex;
|
|
}
|
|
}
|
|
|
|
// We didn't return an icon so let the base mode have a chance
|
|
|
|
return MultiplayerModeBase::getIcon( player, statNum, value );
|
|
}
|
|
|
|
int ModeTeamBase::getInfoIcon( Player *player )
|
|
{
|
|
Team *team;
|
|
|
|
// Make sure entity is not invisible
|
|
|
|
if ( player->_affectingViewModes & gi.GetViewModeMask( "forcevisible" ) )
|
|
return 0;
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
{
|
|
if ( team->getName() == "Red" )
|
|
return _redTeamIconIndex;
|
|
else if ( team->getName() == "Blue" )
|
|
return _blueTeamIconIndex;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool ModeTeamBase::canJoinTeam( Player *player, const str &teamName )
|
|
{
|
|
Team *team;
|
|
|
|
if ( multiplayerManager.checkFlag( MP_FLAG_AUTO_BALANCE_TEAMS ) )
|
|
{
|
|
Team *team;
|
|
Team *redTeam;
|
|
Team *blueTeam;
|
|
int redTeamPlayers;
|
|
int blueTeamPlayers;
|
|
|
|
// Get all of the teams
|
|
|
|
team = getTeam( teamName );
|
|
redTeam = getTeam( "Red" );
|
|
blueTeam = getTeam( "Blue" );
|
|
|
|
// Get the number of players
|
|
|
|
redTeamPlayers = redTeam->getActivePlayers();
|
|
blueTeamPlayers = blueTeam->getActivePlayers();
|
|
|
|
if ( _playerGameData[ player->entnum ]._currentTeam == redTeam )
|
|
redTeamPlayers -= 1;
|
|
else if ( _playerGameData[ player->entnum ]._currentTeam == blueTeam )
|
|
blueTeamPlayers -= 1;
|
|
|
|
// Don't allow switch unless it's to the team that has less people
|
|
|
|
if ( ( redTeamPlayers > blueTeamPlayers ) && ( team == redTeam ) )
|
|
{
|
|
multiplayerManager.centerPrint( player->entnum, "$$CannotJoinAutoBalanceRed$$", CENTERPRINT_IMPORTANCE_HIGH );
|
|
return false;
|
|
}
|
|
else if ( ( blueTeamPlayers > redTeamPlayers ) && ( team == blueTeam ) )
|
|
{
|
|
multiplayerManager.centerPrint( player->entnum, "$$CannotJoinAutoBalanceBlue$$", CENTERPRINT_IMPORTANCE_HIGH );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( !multiplayerManager.checkRule( "respawnPlayer", true, player ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
team = _findTeamByName( teamName );
|
|
|
|
if ( _playerGameData[ player->entnum ]._currentTeam == team )
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
void ModeTeamBase::joinTeam( Player *player, const str &teamName )
|
|
{
|
|
Team *team;
|
|
|
|
team = _findTeamByName( teamName );
|
|
|
|
changeTeams( player, team );
|
|
}
|
|
|
|
float ModeTeamBase::playerDamaged( Player *damagedPlayer, Player *attackingPlayer, float damage, int meansOfDeath )
|
|
{
|
|
// Always take telefrag damage
|
|
|
|
if ( meansOfDeath == MOD_TELEFRAG )
|
|
return damage;
|
|
|
|
// Player can always hurt himself
|
|
|
|
if ( damagedPlayer == attackingPlayer )
|
|
return damage;
|
|
|
|
// If on same team and not allowing team damage
|
|
|
|
if ( ( _playerGameData[ damagedPlayer->entnum ]._currentTeam == _playerGameData[ attackingPlayer->entnum ]._currentTeam ) &&
|
|
( !multiplayerManager.checkFlag( MP_FLAG_FRIENDLY_FIRE ) ) )
|
|
return 0;
|
|
else
|
|
return damage;
|
|
}
|
|
|
|
int ModeTeamBase::getTeamPoints( Player *player )
|
|
{
|
|
Team *team;
|
|
|
|
// Return the points for this team
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
return team->getPoints();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int ModeTeamBase::getTeamPoints( const str & teamName )
|
|
{
|
|
int i;
|
|
Team *team;
|
|
|
|
// Return the points for this team
|
|
|
|
for ( i = 1 ; i <= _teamList.NumObjects() ; i++ )
|
|
{
|
|
team = _teamList.ObjectAt( i );
|
|
|
|
if ( team->getName() == teamName )
|
|
{
|
|
return team->getPoints();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ModeTeamBase::addTeamPoints( const str & teamName, int points )
|
|
{
|
|
int i;
|
|
Team *team;
|
|
|
|
// Return the points for this team
|
|
|
|
for ( i = 1 ; i <= _teamList.NumObjects() ; i++ )
|
|
{
|
|
team = _teamList.ObjectAt( i );
|
|
|
|
if ( team->getName() == teamName )
|
|
{
|
|
team->addPoints( NULL, points );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::teamPointsChanged( Team *team, int oldPoints, int newPoints )
|
|
{
|
|
Team *otherTeam;
|
|
int otherTeamPoints;
|
|
|
|
if ( team->getName() == "Red" )
|
|
otherTeam = getTeam( "Blue" );
|
|
else
|
|
otherTeam = getTeam( "Red" );
|
|
|
|
otherTeamPoints = otherTeam->getPoints();
|
|
|
|
// Play a dialog for this team if necessary
|
|
|
|
if ( ( newPoints == otherTeamPoints ) && ( oldPoints != otherTeamPoints ) )
|
|
{
|
|
// Now tied for the lead
|
|
multiplayerManager.broadcastSound( "localization/sound/dialog/dm/comp_teamstied.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, NULL, 1.0f );
|
|
}
|
|
else if ( ( newPoints > otherTeamPoints ) && ( oldPoints <= otherTeamPoints ) )
|
|
{
|
|
// Now in first place
|
|
multiplayerManager.teamSound( team, "localization/sound/dialog/dm/comp_team1stplace.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, 1.0f );
|
|
|
|
// No longer in the lead
|
|
multiplayerManager.teamSound( otherTeam, "localization/sound/dialog/dm/comp_teamnolead.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, 1.0f );
|
|
}
|
|
else if ( ( newPoints < otherTeamPoints ) && ( oldPoints >= otherTeamPoints ) )
|
|
{
|
|
// No longer in the lead
|
|
multiplayerManager.teamSound( team, "localization/sound/dialog/dm/comp_teamnolead.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, 1.0f );
|
|
|
|
// Now in first place
|
|
multiplayerManager.teamSound( otherTeam, "localization/sound/dialog/dm/comp_team1stplace.mp3", CHAN_AUTO, DEFAULT_VOL, DEFAULT_MIN_DIST, 1.0f );
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::RemovePlayer( Player *player )
|
|
{
|
|
Team *team;
|
|
|
|
team = _playerGameData[ player->entnum ]._currentTeam;
|
|
|
|
if ( team )
|
|
{
|
|
team->RemovePlayer( player );
|
|
}
|
|
|
|
MultiplayerModeBase::RemovePlayer( player );
|
|
}
|
|
|
|
int ModeTeamBase::getHighestPoints( void )
|
|
{
|
|
int i;
|
|
int highestPoints = -999999999;
|
|
Team *team;
|
|
|
|
for ( i = 1 ; i <= _teamList.NumObjects() ; i++ )
|
|
{
|
|
team = _teamList.ObjectAt( i );
|
|
|
|
if ( team->getPoints() > highestPoints )
|
|
{
|
|
highestPoints = team->getPoints();
|
|
}
|
|
}
|
|
|
|
return highestPoints;
|
|
}
|
|
|
|
void ModeTeamBase::updatePlayerSkin( Player *player )
|
|
{
|
|
Team *team;
|
|
|
|
team = getPlayersTeam( player );
|
|
|
|
player->SurfaceCommand( "all", "-skin1" );
|
|
player->SurfaceCommand( "all", "-skin2" );
|
|
|
|
if ( !team )
|
|
return;
|
|
|
|
if ( team->getName() == "Red" )
|
|
{
|
|
player->SurfaceCommand( "all", "+skin1" );
|
|
}
|
|
else
|
|
{
|
|
player->SurfaceCommand( "all", "+skin2" );
|
|
}
|
|
}
|
|
|
|
void ModeTeamBase::playerChangedModel( Player *player )
|
|
{
|
|
updatePlayerSkin( player );
|
|
}
|
|
|