1497 lines
37 KiB
C++
1497 lines
37 KiB
C++
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#include "../precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "TeamManager.h"
|
||
|
#include "../structures/DeployRequest.h"
|
||
|
#include "../Player.h"
|
||
|
#include "../script/Script_Helper.h"
|
||
|
#include "../script/Script_ScriptObject.h"
|
||
|
#include "../rules/VoteManager.h"
|
||
|
#include "../roles/FireTeams.h"
|
||
|
|
||
|
#include "../botai/Bot.h" //mal: needed for the bots.
|
||
|
#include "../botai/BotThreadData.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdTeamManagerLocal
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerGameState::MakeDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerGameState::MakeDefault( void ) {
|
||
|
teamData.SetNum( sdTeamManager::GetInstance().GetNumTeams() );
|
||
|
for ( int i = 0; i < teamData.Num(); i++ ) {
|
||
|
teamData[ i ].MakeDefault();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerGameState::Write
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerGameState::Write( idFile* file ) const {
|
||
|
for ( int i = 0; i < teamData.Num(); i++ ) {
|
||
|
teamData[ i ].Write( file );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerGameState::Read
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerGameState::Read( idFile* file ) {
|
||
|
teamData.SetNum( sdTeamManager::GetInstance().GetNumTeams() );
|
||
|
for ( int i = 0; i < teamData.Num(); i++ ) {
|
||
|
teamData[ i ].Read( file );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::sdTeamManagerLocal
|
||
|
================
|
||
|
*/
|
||
|
sdTeamManagerLocal::sdTeamManagerLocal( void ) {
|
||
|
stateObject.Init( this );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::~sdTeamManagerLocal
|
||
|
================
|
||
|
*/
|
||
|
sdTeamManagerLocal::~sdTeamManagerLocal( void ) {
|
||
|
Shutdown();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::Think
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::Think( void ) {
|
||
|
int i;
|
||
|
for( i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->Think();
|
||
|
// Gordon: FIXME: This could be done better without polling.
|
||
|
if ( teamInfo[ i ]->GetBotTeam() == GDF ) {
|
||
|
botThreadData.GetGameWorldState()->gameLocalInfo.nextGDFRespawnTime = ( teamInfo[ i ]->GetTeamRespawnTime() - ( gameLocal.time / 1000 ));
|
||
|
} else if ( teamInfo[ i ]->GetBotTeam() == STROGG ) {
|
||
|
botThreadData.GetGameWorldState()->gameLocalInfo.nextStroggRespawnTime = ( teamInfo[ i ]->GetTeamRespawnTime() - ( gameLocal.time / 1000 ));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::Init
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::Init( void ) {
|
||
|
for( int i = 0; i < gameLocal.declTeamInfoType.Num(); i++ ) {
|
||
|
sdTeamInfo* newTeamInfo = new sdTeamInfo();
|
||
|
newTeamInfo->PreInit( i );
|
||
|
teamInfo.Alloc() = newTeamInfo;
|
||
|
}
|
||
|
teamBits = idMath::BitsForInteger( gameLocal.declTeamInfoType.Num() + 1 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::OnNewMapLoad
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::OnNewMapLoad( void ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->OnNewMapLoad();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::OnNewScriptLoad
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::OnNewScriptLoad( void ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->OnNewScriptLoad();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::OnMapStart
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::OnMapStart( void ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->OnMapStart();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::Shutdown
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::Shutdown( void ) {
|
||
|
teamInfo.DeleteContents( true );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::GetTeam
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo* sdTeamManagerLocal::GetTeamSafe( const char* name ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
if ( idStr::Icmp( teamInfo[ i ]->GetLookupName(), name ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
return teamInfo[ i ];
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamManagerLocal::GetIndexForTeam
|
||
|
============
|
||
|
*/
|
||
|
int sdTeamManagerLocal::GetIndexForTeam( const char* name ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
if ( idStr::Icmp( teamInfo[ i ]->GetLookupName(), name ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::GetTeam
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo& sdTeamManagerLocal::GetTeam( const char* name ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
if( !idStr::Icmp( teamInfo[ i ]->GetLookupName(), name ) ) {
|
||
|
return *teamInfo[ i ];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gameLocal.Error( "sdTeamManagerLocal::GetTeam Invalid Team Name '%s'", name );
|
||
|
|
||
|
return *( sdTeamInfo* )NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::GetTeamByIndex
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo& sdTeamManagerLocal::GetTeamByIndex( int index ) {
|
||
|
if( index < 0 || index >= teamInfo.Num() ) {
|
||
|
gameLocal.Warning( "sdTeamManagerLocal::GetTeamByIndex Index OOB %i", index );
|
||
|
return *teamInfo[ 0 ];
|
||
|
}
|
||
|
|
||
|
return *teamInfo[ index ];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::WriteTeamToStream
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::WriteTeamToStream( sdTeamInfo* newTeam, idFile* file ) const {
|
||
|
int newIndex = newTeam ? newTeam->GetIndex() + 1 : 0;
|
||
|
file->WriteInt( newIndex );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::WriteTeamToStream
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::WriteTeamToStream( sdTeamInfo* newTeam, idBitMsg& msg ) const {
|
||
|
int newIndex = newTeam ? newTeam->GetIndex() + 1 : 0;
|
||
|
msg.WriteBits( newIndex, teamBits );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::WriteTeamToStream
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::WriteTeamToStream( sdTeamInfo* oldTeam, sdTeamInfo* newTeam, idBitMsg& msg ) const {
|
||
|
int oldIndex = oldTeam ? oldTeam->GetIndex() + 1 : 0;
|
||
|
int newIndex = newTeam ? newTeam->GetIndex() + 1 : 0;
|
||
|
|
||
|
msg.WriteDelta( oldIndex, newIndex, teamBits );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::ReadTeamFromStream
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo* sdTeamManagerLocal::ReadTeamFromStream( idFile* file ) const {
|
||
|
int teamnum;
|
||
|
file->ReadInt( teamnum );
|
||
|
teamnum--;
|
||
|
|
||
|
if ( teamnum == -1 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return &sdTeamManager::GetInstance().GetTeamByIndex( teamnum );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::ReadTeamFromStream
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo* sdTeamManagerLocal::ReadTeamFromStream( const idBitMsg& msg ) const {
|
||
|
int teamnum = msg.ReadBits( teamBits ) - 1;
|
||
|
if ( teamnum == -1 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return &sdTeamManager::GetInstance().GetTeamByIndex( teamnum );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::ReadTeamFromStream
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo* sdTeamManagerLocal::ReadTeamFromStream( sdTeamInfo* oldTeam, const idBitMsg& msg ) const {
|
||
|
int oldIndex = oldTeam ? oldTeam->GetIndex() + 1 : 0;
|
||
|
|
||
|
int teamnum = msg.ReadDelta( oldIndex, teamBits ) - 1;
|
||
|
if ( teamnum == -1 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return &sdTeamManager::GetInstance().GetTeamByIndex( teamnum );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::OnScriptChange
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::OnScriptChange( void ) {
|
||
|
for( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->OnScriptChange();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::ApplyNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::ApplyNetworkState( const sdEntityStateNetworkData& newState ) {
|
||
|
NET_GET_NEW( sdTeamManagerGameState );
|
||
|
|
||
|
for ( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->ApplyNetworkState( newData.teamData[ i ] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::ReadNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::ReadNetworkState( const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, const idBitMsg& msg ) const {
|
||
|
NET_GET_STATES( sdTeamManagerGameState );
|
||
|
|
||
|
newData.teamData.SetNum( teamInfo.Num() );
|
||
|
for ( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->ReadNetworkState( baseData.teamData[ i ], newData.teamData[ i ], msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::WriteNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamManagerLocal::WriteNetworkState( const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, idBitMsg& msg ) const {
|
||
|
NET_GET_STATES( sdTeamManagerGameState );
|
||
|
|
||
|
newData.teamData.SetNum( teamInfo.Num() );
|
||
|
for ( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
teamInfo[ i ]->WriteNetworkState( baseData.teamData[ i ], newData.teamData[ i ], msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::CheckNetworkStateChanges
|
||
|
================
|
||
|
*/
|
||
|
bool sdTeamManagerLocal::CheckNetworkStateChanges( const sdEntityStateNetworkData& baseState ) const {
|
||
|
NET_GET_BASE( sdTeamManagerGameState );
|
||
|
|
||
|
for ( int i = 0; i < teamInfo.Num(); i++ ) {
|
||
|
if ( teamInfo[ i ]->CheckNetworkStateChanges( baseData.teamData[ i ] ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamManagerLocal::CreateNetworkStructure
|
||
|
================
|
||
|
*/
|
||
|
sdEntityStateNetworkData* sdTeamManagerLocal::CreateNetworkStructure( void ) const {
|
||
|
return new sdTeamManagerGameState();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdTeamInfo
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfoGameState::MakeDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfoGameState::MakeDefault( void ) {
|
||
|
wins = 0;
|
||
|
|
||
|
scriptData.MakeDefault();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfoGameState::MakeDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfoGameState::Write( idFile* file ) const {
|
||
|
file->WriteInt( wins );
|
||
|
|
||
|
scriptData.Write( file );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfoGameState::Read
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfoGameState::Read( idFile* file ) {
|
||
|
file->ReadInt( wins );
|
||
|
|
||
|
scriptData.Read( file );
|
||
|
}
|
||
|
|
||
|
extern const idEventDef EV_SyncScriptFieldBroadcast;
|
||
|
extern const idEventDef EV_SyncScriptFieldCallback;
|
||
|
extern const idEventDef EV_GetName;
|
||
|
|
||
|
const idEventDef EV_Team_GetTitle( "getTitle", 'h', DOC_TEXT( "Returns a handle to the localized name of the team." ), 0, NULL );
|
||
|
const idEventDef EV_Team_RegisterDeployable( "registerDeployable", '\0', DOC_TEXT( "Registers an entity as belonging to this team." ), 1, "See also $event:unRegisterDeployable$.", "e", "entity", "Entity to add to the list." );
|
||
|
const idEventDef EV_Team_UnRegisterDeployable( "unRegisterDeployable", '\0', DOC_TEXT( "Removes an entity from this team's list." ), 1, "See also $event:registerDeployable$.", "e", "entity", "Entity to remove from the list." );
|
||
|
const idEventDef EV_Team_RegisterSpawnPoint( "registerSpawnPoint", '\0', DOC_TEXT( "Registers an entity as an active spawn point for this team." ), 1, "See also $event:unRegisterSpawnPoint$.", "e", "entity", "Entity to add to the list." );
|
||
|
const idEventDef EV_Team_UnRegisterSpawnPoint( "unRegisterSpawnPoint", '\0', DOC_TEXT( "Removes an entity from thie team's active spawn points." ), 1, "See also $event:registerSpawnPoint$.", "e", "entity", "Entity to remove from the list." );
|
||
|
|
||
|
const idEventDef EV_Team_SetTeamRearSpawn( "setTeamRearSpawn", '\0', DOC_TEXT( "Marks this entity as the rear spawn for bots to use." ), 1, NULL, "E", "entity", "Entity to mark as the rear spawn." );
|
||
|
|
||
|
CLASS_DECLARATION( idClass, sdTeamInfo )
|
||
|
EVENT( EV_GetName, sdTeamInfo::Event_GetName )
|
||
|
EVENT( EV_Team_GetTitle, sdTeamInfo::Event_GetTitle )
|
||
|
EVENT( EV_Team_RegisterDeployable, sdTeamInfo::Event_RegisterDeployable )
|
||
|
EVENT( EV_Team_UnRegisterDeployable, sdTeamInfo::Event_UnRegisterDeployable )
|
||
|
EVENT( EV_Team_RegisterSpawnPoint, sdTeamInfo::Event_RegisterSpawnPoint )
|
||
|
EVENT( EV_Team_UnRegisterSpawnPoint, sdTeamInfo::Event_UnRegisterSpawnPoint )
|
||
|
EVENT( EV_SyncScriptFieldBroadcast, sdTeamInfo::Event_SyncScriptFieldBroadcast )
|
||
|
EVENT( EV_SyncScriptFieldCallback, sdTeamInfo::Event_SyncScriptFieldCallback )
|
||
|
|
||
|
EVENT( EV_GetKey, sdTeamInfo::Event_GetKey )
|
||
|
EVENT( EV_GetIntKey, sdTeamInfo::Event_GetIntKey )
|
||
|
EVENT( EV_GetFloatKey, sdTeamInfo::Event_GetFloatKey )
|
||
|
EVENT( EV_GetVectorKey, sdTeamInfo::Event_GetVectorKey )
|
||
|
EVENT( EV_GetKeyWithDefault, sdTeamInfo::Event_GetKeyWithDefault )
|
||
|
EVENT( EV_GetIntKeyWithDefault, sdTeamInfo::Event_GetIntKeyWithDefault )
|
||
|
EVENT( EV_GetFloatKeyWithDefault, sdTeamInfo::Event_GetFloatKeyWithDefault )
|
||
|
EVENT( EV_GetVectorKeyWithDefault, sdTeamInfo::Event_GetVectorKeyWithDefault )
|
||
|
|
||
|
EVENT( EV_Team_SetTeamRearSpawn, sdTeamInfo::Event_SetTeamRearSpawn )
|
||
|
END_CLASS
|
||
|
|
||
|
const char* fireTeamNames[ sdTeamInfo::MAX_FIRETEAMS ] = {
|
||
|
"Alpha",
|
||
|
"Beta",
|
||
|
"Gamma",
|
||
|
"Delta",
|
||
|
"Epsilon",
|
||
|
"Zeta",
|
||
|
"Eta",
|
||
|
"Theta"
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::sdTeamInfo
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo::sdTeamInfo( void ) : index( -1 ), info( NULL ), passwordCVar( NULL ), lifeStatTitle( NULL ) {
|
||
|
wins = 0;
|
||
|
|
||
|
info = NULL;
|
||
|
|
||
|
defaultClass = NULL;
|
||
|
scriptObject = NULL;
|
||
|
scriptThread = NULL;
|
||
|
allowRespawnFunc = NULL;
|
||
|
|
||
|
teamNextRespawnTimeFunc = NULL;
|
||
|
|
||
|
rearSpawnBase = NULL;
|
||
|
|
||
|
playZoneExitToolTip = NULL;
|
||
|
|
||
|
fireTeams = new sdFireTeam[ MAX_FIRETEAMS ];
|
||
|
for ( int i = 0; i < MAX_FIRETEAMS; i++ ) {
|
||
|
fireTeams[ i ].SetDefaultName( fireTeamNames[ i ] );
|
||
|
fireTeams[ i ].SetGameTeam( this );
|
||
|
}
|
||
|
|
||
|
ResetAll();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::sdTeamInfo
|
||
|
================
|
||
|
*/
|
||
|
sdTeamInfo::~sdTeamInfo( void ) {
|
||
|
delete[] fireTeams;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::GetFireTeam
|
||
|
================
|
||
|
*/
|
||
|
sdFireTeam& sdTeamInfo::GetFireTeam( int index ) {
|
||
|
return fireTeams[ index ];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::GetFireTeamIndex
|
||
|
================
|
||
|
*/
|
||
|
int sdTeamInfo::GetFireTeamIndex( sdFireTeam* fireTeam ) const {
|
||
|
if ( fireTeam == NULL ) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < MAX_FIRETEAMS; i++ ) {
|
||
|
if ( static_cast<const sdFireTeam*>( &fireTeams[ i ] ) == fireTeam ) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::GetDefaultFireTeamName
|
||
|
================
|
||
|
*/
|
||
|
const char* sdTeamInfo::GetDefaultFireTeamName( int index ) {
|
||
|
return fireTeamNames[ index ];
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::PreInit
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::PreInit( int _index ) {
|
||
|
index = _index;
|
||
|
|
||
|
const sdDeclStringMap* data = gameLocal.declTeamInfoType.LocalFindByIndex( index, false );
|
||
|
lookupname = data->GetName();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::OnScriptChange
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::OnScriptChange( void ) {
|
||
|
if ( scriptThread != NULL ) {
|
||
|
gameLocal.program->FreeThread( scriptThread );
|
||
|
scriptThread = NULL;
|
||
|
}
|
||
|
|
||
|
if ( scriptObject ) {
|
||
|
gameLocal.program->FreeScriptObject( scriptObject );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Reset
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Reset( void ) {
|
||
|
deployables.Clear();
|
||
|
spawnLocations.Clear();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::ResetAll
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::ResetAll( void ) {
|
||
|
Reset();
|
||
|
|
||
|
wins = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::AllowRespawn
|
||
|
================
|
||
|
*/
|
||
|
bool sdTeamInfo::AllowRespawn( idPlayer* player ) {
|
||
|
sdScriptHelper h1;
|
||
|
h1.Push( player->GetScriptObject() );
|
||
|
scriptObject->CallNonBlockingScriptEvent( allowRespawnFunc, h1 );
|
||
|
return gameLocal.program->GetReturnedInteger() != 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::GetTeamRespawnTime
|
||
|
================
|
||
|
*/
|
||
|
int sdTeamInfo::GetTeamRespawnTime( void ) {
|
||
|
sdScriptHelper h1;
|
||
|
scriptObject->CallNonBlockingScriptEvent( teamNextRespawnTimeFunc, h1 );
|
||
|
return idMath::Ftoi( gameLocal.program->GetReturnedFloat() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::OnCampaignChange
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::OnCampaignChange( void ) {
|
||
|
ResetAll();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Init
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Init( void ) {
|
||
|
info = gameLocal.declTeamInfoType[ index ];
|
||
|
|
||
|
const idDict& dict = info->GetDict();
|
||
|
|
||
|
title = declHolder.declLocStrType[ dict.GetString( "name" ) ];
|
||
|
if ( title == NULL ) {
|
||
|
gameLocal.Error( "sdTeamInfo::Init No Title Provided" );
|
||
|
}
|
||
|
|
||
|
winString = declHolder.declLocStrType[ dict.GetString( "match_win_string" ) ];
|
||
|
winStringSW_Speed = declHolder.declLocStrType[ dict.GetString( "match_win_sw_speed" ) ];
|
||
|
winStringSW_XP = declHolder.declLocStrType[ dict.GetString( "match_win_sw_xp" ) ];
|
||
|
|
||
|
winMusic = dict.GetString( "snd_music_won" );
|
||
|
|
||
|
spawnFxName = dict.GetString( "fx_spawn", "fx/teleporterplayer" );
|
||
|
|
||
|
allowRevive = dict.GetBool( "allow_revive" );
|
||
|
|
||
|
crashLandFxName = dict.GetString( "fx_crashland" );
|
||
|
crashLandThreshold = dict.GetFloat( "crashland_threshold" );
|
||
|
parachuteLandFxName = dict.GetString( "fx_parachuteland" );
|
||
|
parachuteLandThreshold = dict.GetFloat( "parachuteland_threshold" );
|
||
|
|
||
|
botTeam = ( playerTeamTypes_t )dict.GetInt( "bot_team" );
|
||
|
|
||
|
highCommandName = declHolder.declLocStrType[ dict.GetString( "high_command_name" ) ];
|
||
|
if ( highCommandName == NULL ) {
|
||
|
gameLocal.Warning( "sdTeamInfo::Init No High Command Name Provided" );
|
||
|
}
|
||
|
|
||
|
defaultClass = gameLocal.declPlayerClassType[ dict.GetString( "pc_default" ) ];
|
||
|
if( !defaultClass ) {
|
||
|
gameLocal.Error( "sdTeamInfo::Init No Default Class Supplied" );
|
||
|
}
|
||
|
|
||
|
proficiencyTypes.Clear();
|
||
|
const idKeyValue* kv = NULL;
|
||
|
while ( kv = dict.MatchPrefix( "proficiencyList", kv ) ) {
|
||
|
const sdDeclProficiencyType* pType = gameLocal.declProficiencyTypeType[ kv->GetValue() ];
|
||
|
if ( !pType ) {
|
||
|
gameLocal.Error( "sdTeamInfo::Init Invalid Proficiency Type '%s'", kv->GetValue().c_str() );
|
||
|
}
|
||
|
proficiencyTypes.Alloc() = pType;
|
||
|
}
|
||
|
|
||
|
const char* passwordCVarName = dict.GetString( "cvar_password" );
|
||
|
if ( *passwordCVarName ) {
|
||
|
passwordCVar = cvarSystem->Find( passwordCVarName );
|
||
|
if ( !passwordCVar ) {
|
||
|
cvarSystem->SetCVarString( passwordCVarName, "", CVAR_NOCHEAT );
|
||
|
passwordCVar = cvarSystem->Find( passwordCVarName );
|
||
|
|
||
|
assert( passwordCVar );
|
||
|
}
|
||
|
} else {
|
||
|
passwordCVar = NULL;
|
||
|
}
|
||
|
|
||
|
int count = dict.GetInt( "num_ratings" );
|
||
|
ratings.SetNum( count );
|
||
|
for ( int i = 0; i < count; i++ ) {
|
||
|
const char* ratingName = dict.GetString( va( "rating_%i", i + 1 ) );
|
||
|
|
||
|
const sdDeclRating* rating = gameLocal.declRatingType[ ratingName ];
|
||
|
if ( !rating ) {
|
||
|
gameLocal.Error( "sdTeamInfo::Init Failed to Load Rating '%s'", ratingName );
|
||
|
}
|
||
|
ratings[ i ] = rating;
|
||
|
}
|
||
|
|
||
|
playZoneExitToolTip = gameLocal.declToolTipType[ dict.GetString( "tt_leavingzone" ) ];
|
||
|
|
||
|
// load lifeStat titles
|
||
|
const char* lifeStatName = dict.GetString( "lifestat_title", "blank" );
|
||
|
lifeStatTitle = declHolder.declLocStrType.LocalFind( lifeStatName );
|
||
|
|
||
|
game->CacheDictionaryMedia( dict );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::SortPlayers
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::SortPlayers( idStaticList< idPlayer*, MAX_CLIENTS >& list, bool wantSpectators ) {
|
||
|
list.Clear();
|
||
|
|
||
|
idStaticList< idPlayer*, MAX_CLIENTS > specList;
|
||
|
|
||
|
int i;
|
||
|
for( i = 0; i < MAX_CLIENTS; i++ ) {
|
||
|
idPlayer* p = gameLocal.GetClient( i );
|
||
|
if( p == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
sdTeamInfo* team = p->GetGameTeam();
|
||
|
if( ( team == NULL || *team != *this ) ) {
|
||
|
if( !wantSpectators ) {
|
||
|
continue;
|
||
|
}
|
||
|
idPlayer* specClient = p->GetSpectateClient();
|
||
|
if( specClient == NULL || specClient == p ) {
|
||
|
continue;
|
||
|
}
|
||
|
sdTeamInfo* spectatingTeam = specClient->GetGameTeam();
|
||
|
if( spectatingTeam == NULL || *spectatingTeam != *this ) {
|
||
|
continue;
|
||
|
}
|
||
|
specList.Append( p );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
list.Append( p );
|
||
|
}
|
||
|
|
||
|
list.Sort( SortPlayersFunc );
|
||
|
|
||
|
// ensure that spectators always report last
|
||
|
specList.Sort( SortPlayersFunc );
|
||
|
list.Append( specList );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::SortPlayersFunc
|
||
|
================
|
||
|
*/
|
||
|
int sdTeamInfo::SortPlayersFunc( const playerPtr_t* a, const playerPtr_t* b ) {
|
||
|
return idMath::Ftoi( ( *b )->GetProficiencyTable().GetXP() ) - idMath::Ftoi( ( *a )->GetProficiencyTable().GetXP() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Think
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Think( void ) {
|
||
|
UpdateScript();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::UpdateScript
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::UpdateScript( void ) {
|
||
|
if ( !scriptThread || gameLocal.IsPaused() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// don't call script until it's done waiting
|
||
|
if ( scriptThread->IsWaiting() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
scriptThread->Execute();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::OnNewMapLoad
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::OnNewMapLoad( void ) {
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::PointInRadar
|
||
|
================
|
||
|
*/
|
||
|
idEntity* sdTeamInfo::PointInRadar( const idVec3& _target, radarMasks_t type, const idList< sdRadarLayer* >& list ) {
|
||
|
int worldZoneIndex = gameLocal.GetWorldPlayZoneIndex( _target );
|
||
|
idVec2 target = _target.ToVec2();
|
||
|
|
||
|
for ( int index = 0; index < list.Num(); index++ ) {
|
||
|
sdRadarLayer* layer = list[ index ];
|
||
|
|
||
|
idEntity* owner = layer->GetOwner();
|
||
|
if ( owner == NULL ) {
|
||
|
gameLocal.Warning( "sdTeamInfo::PointInRadar radar layer with NULL owner" );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( ( layer->GetMask() & type ) == 0 ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
const idVec2& layerOrigin = layer->GetOrigin();
|
||
|
|
||
|
idVec2 currentDir = target - layerOrigin;
|
||
|
|
||
|
float currentRange = currentDir.LengthSqr();
|
||
|
if ( currentRange > layer->GetRange() ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
float maxAngle = layer->GetMaxAngle();
|
||
|
if ( maxAngle < idMath::PI ) {
|
||
|
currentDir.NormalizeFast();
|
||
|
|
||
|
float angle = idMath::ACos( currentDir * layer->GetDirection() );
|
||
|
if ( angle > maxAngle ) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int radarZoneIndex = gameLocal.GetWorldPlayZoneIndex( idVec3( layerOrigin.x, layerOrigin.y, 0.f ) );
|
||
|
if ( radarZoneIndex != worldZoneIndex ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return owner;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::PointInJammer
|
||
|
================
|
||
|
*/
|
||
|
idEntity* sdTeamInfo::PointInJammer( const idVec3& target, radarMasks_t type ) {
|
||
|
return PointInRadar( target, type, jammerLayers );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::PointInRadar
|
||
|
================
|
||
|
*/
|
||
|
idEntity* sdTeamInfo::PointInRadar( const idVec3& target, radarMasks_t type ) {
|
||
|
return PointInRadar( target, type, radarLayers );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::RegisterDeployable
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::RegisterDeployable( idEntity* other ) {
|
||
|
AddEntityToList( deployables, other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::UnRegisterDeployable
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::UnRegisterDeployable( idEntity* other ) {
|
||
|
RemoveEntityFromList( deployables, other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::RegisterSpawnPoint
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::RegisterSpawnPoint( idEntity* other ) {
|
||
|
idEntity* oldDefault = spawnLocations.Num() ? spawnLocations[ 0 ].GetEntity() : NULL;
|
||
|
|
||
|
idStr priorityName = va( "spawn_priority_%s", lookupname.c_str() );
|
||
|
|
||
|
int otherPriority = other->spawnArgs.GetInt( priorityName );
|
||
|
|
||
|
int i;
|
||
|
for ( i = 0; i < spawnLocations.Num(); ) {
|
||
|
idEntity* loc = spawnLocations[ i ];
|
||
|
if ( !loc ) {
|
||
|
spawnLocations.RemoveIndex( i );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int locPriority = loc->spawnArgs.GetInt( priorityName );
|
||
|
if ( locPriority < otherPriority ) {
|
||
|
idEntityPtr< idEntity > temp = other;
|
||
|
spawnLocations.Insert( temp, i );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
if ( i == spawnLocations.Num() ) {
|
||
|
spawnLocations.Alloc() = other;
|
||
|
}
|
||
|
|
||
|
idEntity* newDefault = spawnLocations[ 0 ];
|
||
|
|
||
|
if ( oldDefault != newDefault ) {
|
||
|
gameLocal.localPlayerProperties.OnDefaultSpawnChanged( this, newDefault );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::UnRegisterSpawnPoint
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::UnRegisterSpawnPoint( idEntity* other ) {
|
||
|
idEntity* oldDefault = spawnLocations.Num() ? spawnLocations[ 0 ].GetEntity() : NULL;
|
||
|
|
||
|
RemoveEntityFromList( spawnLocations, other );
|
||
|
|
||
|
idEntity* newDefault = spawnLocations.Num() ? spawnLocations[ 0 ].GetEntity() : NULL;
|
||
|
|
||
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
||
|
idPlayer* player = gameLocal.GetClient( i );
|
||
|
if ( !player || !player->IsTeam( this ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( player->GetSpawnPoint() == other ) {
|
||
|
player->SetSpawnPoint( NULL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( oldDefault != newDefault ) {
|
||
|
gameLocal.localPlayerProperties.OnDefaultSpawnChanged( this, newDefault );
|
||
|
}
|
||
|
|
||
|
if ( other == rearSpawnBase.GetEntity() ) {
|
||
|
rearSpawnBase = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::ApplyNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::ApplyNetworkState( const sdTeamInfoGameState& newData ) {
|
||
|
// update state
|
||
|
wins = newData.wins;
|
||
|
|
||
|
scriptObject->ApplyNetworkState( NSM_BROADCAST, newData.scriptData );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::ReadNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::ReadNetworkState( const sdTeamInfoGameState& baseData, sdTeamInfoGameState& newData, const idBitMsg& msg ) const {
|
||
|
// read state
|
||
|
newData.wins = msg.ReadDeltaLong( baseData.wins );
|
||
|
|
||
|
scriptObject->ReadNetworkState( NSM_BROADCAST, baseData.scriptData, newData.scriptData, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::WriteNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::WriteNetworkState( const sdTeamInfoGameState& baseData, sdTeamInfoGameState& newData, idBitMsg& msg ) const {
|
||
|
// update state
|
||
|
newData.wins = wins;
|
||
|
|
||
|
// write state
|
||
|
msg.WriteDeltaLong( baseData.wins, newData.wins );
|
||
|
|
||
|
scriptObject->WriteNetworkState( NSM_BROADCAST, baseData.scriptData, newData.scriptData, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::CheckNetworkStateChanges
|
||
|
================
|
||
|
*/
|
||
|
bool sdTeamInfo::CheckNetworkStateChanges( const sdTeamInfoGameState& baseData ) const {
|
||
|
if ( scriptObject->CheckNetworkStateChanges( NSM_BROADCAST, baseData.scriptData ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return ( baseData.wins != wins );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::CanJoin
|
||
|
================
|
||
|
*/
|
||
|
bool sdTeamInfo::CanJoin( idPlayer* player, const char* password, const sdDeclLocStr*& reason ) const {
|
||
|
if ( player->IsType( idBot::Type ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( passwordCVar != NULL ) {
|
||
|
const char* passwordString = passwordCVar->GetString();
|
||
|
if ( *passwordString != '\0' ) {
|
||
|
if ( idStr::Cmp( passwordString, password ) ) {
|
||
|
reason = declHolder.declLocStrType[ "teams/messages/wrongpassword" ];
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::OnNewScriptLoad
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::OnNewScriptLoad( void ) {
|
||
|
const char* scriptObjectName = info->GetDict().GetString( "scriptObject", "default" );
|
||
|
scriptObject = gameLocal.program->AllocScriptObject( this, scriptObjectName );
|
||
|
allowRespawnFunc = scriptObject->GetFunction( "OnAllowRespawn" );
|
||
|
|
||
|
teamNextRespawnTimeFunc = scriptObject->GetFunction( "GetNextRespawnTime" );
|
||
|
|
||
|
sdScriptHelper h1;
|
||
|
scriptObject->CallNonBlockingScriptEvent( scriptObject->GetPreConstructor(), h1 );
|
||
|
|
||
|
sdScriptHelper h2;
|
||
|
scriptObject->CallNonBlockingScriptEvent( scriptObject->GetSyncFunc(), h2 );
|
||
|
|
||
|
const sdProgram::sdFunction* constructor = scriptObject->GetConstructor();
|
||
|
if ( constructor ) {
|
||
|
scriptThread = gameLocal.program->CreateThread();
|
||
|
scriptThread->SetName( "sdTeamInfo" );
|
||
|
scriptThread->CallFunction( scriptObject, constructor );
|
||
|
scriptThread->ManualControl();
|
||
|
scriptThread->ManualDelete();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::OnMapStart
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::OnMapStart( void ) {
|
||
|
assert( scriptObject );
|
||
|
|
||
|
sdScriptHelper h1;
|
||
|
scriptObject->CallNonBlockingScriptEvent( scriptObject->GetFunction( "OnMapStart" ), h1 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetName
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetName( void ) {
|
||
|
sdProgram::ReturnString( lookupname );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetTitle
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetTitle( void ) {
|
||
|
sdProgram::ReturnHandle( title->Index() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_RegisterDeployable
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_RegisterDeployable( idEntity* other ) {
|
||
|
RegisterDeployable( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_UnRegisterDeployable
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_UnRegisterDeployable( idEntity* other ) {
|
||
|
UnRegisterDeployable( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
sdTeamInfo::Event_RegisterSpawnPoint
|
||
|
===============
|
||
|
*/
|
||
|
void sdTeamInfo::Event_RegisterSpawnPoint( idEntity* other ) {
|
||
|
RegisterSpawnPoint( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
sdTeamInfo::Event_UnRegisterSpawnPoint
|
||
|
===============
|
||
|
*/
|
||
|
void sdTeamInfo::Event_UnRegisterSpawnPoint( idEntity* other ) {
|
||
|
UnRegisterSpawnPoint( other );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_SyncScriptFieldBroadcast
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_SyncScriptFieldBroadcast( const char* fieldName ) {
|
||
|
scriptObject->SetSynced( fieldName, true );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_SyncScriptFieldCallback
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_SyncScriptFieldCallback( const char* fieldName, const char* functionName ) {
|
||
|
scriptObject->SetSyncCallback( fieldName, functionName );
|
||
|
}
|
||
|
|
||
|
class sdFireTeam_InitialCreateFinaliser : public sdVoteFinalizer {
|
||
|
public:
|
||
|
sdFireTeam_InitialCreateFinaliser( idPlayer* player ) : _player( player ) {
|
||
|
}
|
||
|
|
||
|
virtual ~sdFireTeam_InitialCreateFinaliser( void ) {
|
||
|
}
|
||
|
|
||
|
virtual void OnVoteCompleted( bool passed ) const {
|
||
|
if ( passed ) {
|
||
|
idPlayer* player = _player;
|
||
|
if ( player ) {
|
||
|
sdTeamInfo* team = player->GetTeam();
|
||
|
if ( team ) {
|
||
|
team->CreatePublicFireTeam( player );
|
||
|
} else {
|
||
|
assert( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
idEntityPtr< idPlayer > _player;
|
||
|
};
|
||
|
|
||
|
class sdFireTeam_InitialJoinFinaliser : public sdVoteFinalizer {
|
||
|
public:
|
||
|
sdFireTeam_InitialJoinFinaliser( idPlayer* player, sdFireTeam* fireTeam ) : _fireTeam( fireTeam ), _player( player ) {
|
||
|
}
|
||
|
|
||
|
virtual ~sdFireTeam_InitialJoinFinaliser( void ) {
|
||
|
}
|
||
|
|
||
|
virtual void OnVoteCompleted( bool passed ) const {
|
||
|
if ( passed ) {
|
||
|
idPlayer* player = _player;
|
||
|
if ( player ) {
|
||
|
_fireTeam->AddMember( player->entityNumber );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
sdFireTeam* _fireTeam;
|
||
|
idEntityPtr< idPlayer > _player;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::CreatePrivateFireTeam
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::CreatePrivateFireTeam( idPlayer* player ) {
|
||
|
for ( int i = 0; i < MAX_FIRETEAMS; i++ ) {
|
||
|
if ( fireTeams[ i ].GetNumMembers() == 0 ) {
|
||
|
fireTeams[ i ].AddMember( player->entityNumber );
|
||
|
fireTeams[ i ].SetPrivate( true );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
player->SendLocalisedMessage( declHolder.declLocStrType[ "fireteam/messages/noneleft" ], idWStrList() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::CreatePublicFireTeam
|
||
|
================
|
||
|
*/
|
||
|
bool sdTeamInfo::CreatePublicFireTeam( idPlayer* player ) {
|
||
|
for ( int i = 0; i < MAX_FIRETEAMS; i++ ) {
|
||
|
if ( fireTeams[ i ].GetNumMembers() == 0 ) {
|
||
|
fireTeams[ i ].AddMember( player->entityNumber );
|
||
|
fireTeams[ i ].SetPrivate( false );
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::TryFindPrivateFireTeam
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::TryFindPrivateFireTeam( idPlayer* player ) {
|
||
|
for ( int i = 0; i < MAX_FIRETEAMS; i++ ) {
|
||
|
if ( fireTeams[ i ].GetNumMembers() == 0 ) {
|
||
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
||
|
if ( !vote ) {
|
||
|
return;
|
||
|
}
|
||
|
vote->DisableFinishMessage();
|
||
|
vote->MakePrivateVote( player );
|
||
|
vote->Tag( VI_FIRETEAM_CREATE, player );
|
||
|
vote->SetText( gameLocal.declToolTipType[ "fireteam_initial_create" ] );
|
||
|
vote->SetFinalizer( new sdFireTeam_InitialCreateFinaliser( player ) );
|
||
|
vote->Start();
|
||
|
return;
|
||
|
} else if ( !fireTeams[ i ].IsPrivate() && fireTeams[ i ].GetNumMembers() != sdFireTeam::MaxMembers() ) {
|
||
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
||
|
if ( !vote ) {
|
||
|
return;
|
||
|
}
|
||
|
vote->DisableFinishMessage();
|
||
|
vote->MakePrivateVote( player );
|
||
|
vote->Tag( VI_FIRETEAM_JOIN, player );
|
||
|
vote->SetText( gameLocal.declToolTipType[ "fireteam_initial_join" ] );
|
||
|
vote->SetFinalizer( new sdFireTeam_InitialJoinFinaliser( player, &fireTeams[ i ] ) );
|
||
|
vote->Start();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetKey
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetKey( const char *key ) {
|
||
|
sdProgram::ReturnString( GetDict().GetString( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetIntKey
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetIntKey( const char *key ) {
|
||
|
sdProgram::ReturnInteger( GetDict().GetInt( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetFloatKey
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetFloatKey( const char *key ) {
|
||
|
sdProgram::ReturnFloat( GetDict().GetFloat( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetVectorKey
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetVectorKey( const char *key ) {
|
||
|
sdProgram::ReturnVector( GetDict().GetVector( key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetKeyWithDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetKeyWithDefault( const char *key, const char* defaultvalue ) {
|
||
|
sdProgram::ReturnString( GetDict().GetString( key, defaultvalue ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetIntKeyWithDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetIntKeyWithDefault( const char *key, int defaultvalue ) {
|
||
|
sdProgram::ReturnFloat( GetDict().GetInt( key, va( "%i", defaultvalue ) ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetFloatKeyWithDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetFloatKeyWithDefault( const char *key, float defaultvalue ) {
|
||
|
sdProgram::ReturnFloat( GetDict().GetFloat( key, va( "%f", defaultvalue ) ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_GetVectorKeyWithDefault
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_GetVectorKeyWithDefault( const char *key, const idVec3& defaultvalue ) {
|
||
|
sdProgram::ReturnVector( GetDict().GetVector( key, defaultvalue.ToString() ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdTeamInfo::Event_SetTeamRearSpawn
|
||
|
================
|
||
|
*/
|
||
|
void sdTeamInfo::Event_SetTeamRearSpawn( idEntity* teamRearSpawnBase ) {
|
||
|
rearSpawnBase = teamRearSpawnBase;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetEquivalentClass
|
||
|
============
|
||
|
*/
|
||
|
const sdDeclPlayerClass* sdTeamInfo::GetEquivalentClass( const sdDeclPlayerClass& currentClass, const sdTeamInfo& desiredTeam ) const {
|
||
|
if( this == &desiredTeam ) {
|
||
|
return ¤tClass;
|
||
|
}
|
||
|
|
||
|
const idDict& dict = desiredTeam.GetDict();
|
||
|
idStr key = va( "pc_team_remap_%s_%s", GetLookupName(), currentClass.GetName() );
|
||
|
const char* remappedClass = dict.GetString( key, "" );
|
||
|
|
||
|
if( idStr::Length( remappedClass ) == 0 ) {
|
||
|
return ¤tClass;
|
||
|
}
|
||
|
return gameLocal.declPlayerClassType.LocalFind( remappedClass, false );
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::AllocRadarLayer
|
||
|
============
|
||
|
*/
|
||
|
sdTeamInfo::sdRadarLayer* sdTeamInfo::AllocRadarLayer( void ) {
|
||
|
sdRadarLayer* newLayer = radarAllocator.Alloc();
|
||
|
radarLayers.Alloc() = newLayer;
|
||
|
return newLayer;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::AllocJammerLayer
|
||
|
============
|
||
|
*/
|
||
|
sdTeamInfo::sdRadarLayer* sdTeamInfo::AllocJammerLayer( void ) {
|
||
|
sdRadarLayer* newLayer = radarAllocator.Alloc();
|
||
|
jammerLayers.Alloc() = newLayer;
|
||
|
return newLayer;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::FreeRadarLayer
|
||
|
============
|
||
|
*/
|
||
|
void sdTeamInfo::FreeRadarLayer( sdRadarLayer* layer ) {
|
||
|
int index;
|
||
|
|
||
|
index = radarLayers.FindIndex( layer );
|
||
|
if ( index != -1 ) {
|
||
|
radarLayers.RemoveIndexFast( index );
|
||
|
radarAllocator.Free( layer );
|
||
|
return;
|
||
|
}
|
||
|
index = jammerLayers.FindIndex( layer );
|
||
|
if ( index != -1 ) {
|
||
|
jammerLayers.RemoveIndexFast( index );
|
||
|
radarAllocator.Free( layer );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetRating
|
||
|
============
|
||
|
*/
|
||
|
const sdDeclRating* sdTeamInfo::GetRating( int index ) const {
|
||
|
if ( index < 0 || ratings.Num() <= 0 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if ( index >= ratings.Num() ) {
|
||
|
return ratings[ ratings.Num() - 1 ];
|
||
|
}
|
||
|
return ratings[ index ];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetNumPlayers
|
||
|
============
|
||
|
*/
|
||
|
int sdTeamInfo::GetNumPlayers( bool excludeBots ) const {
|
||
|
int count = 0;
|
||
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
||
|
idPlayer* player = gameLocal.GetClient( i );
|
||
|
if ( player == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( player->GetGameTeam() != this ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( excludeBots ) {
|
||
|
if ( player->IsType( idBot::Type ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetTotalXP
|
||
|
============
|
||
|
*/
|
||
|
float sdTeamInfo::GetTotalXP( void ) const {
|
||
|
float total = 0;
|
||
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
||
|
idPlayer* player = gameLocal.GetClient( i );
|
||
|
if ( player == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( player->GetGameTeam() != this ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
total += player->GetProficiencyTable().GetXP();
|
||
|
}
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetHomeBaseSpawn
|
||
|
============
|
||
|
*/
|
||
|
idEntity* sdTeamInfo::GetHomeBaseSpawn( void ) {
|
||
|
if ( rearSpawnBase == NULL ) { //mal: oops - someone didn't set us up!
|
||
|
if ( bot_debug.GetBool() ) {
|
||
|
gameLocal.DWarning("Bot Team %s has no valid Rear Spawn Set!", ( botTeam == GDF ) ? "GDF" : "STROGG" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rearSpawnBase;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdTeamInfo::GetLifeStatTitle
|
||
|
============
|
||
|
*/
|
||
|
const sdDeclLocStr* sdTeamInfo::GetLifeStatTitle( void ) const {
|
||
|
return lifeStatTitle;
|
||
|
}
|