479 lines
11 KiB
C++
479 lines
11 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 "GameRules_Objective.h"
|
||
|
#include "../Player.h"
|
||
|
#include "../script/Script_Helper.h"
|
||
|
#include "../script/Script_ScriptObject.h"
|
||
|
#include "../guis/UserInterfaceLocal.h"
|
||
|
#include "../rules/VoteManager.h"
|
||
|
|
||
|
sdGameRulesObjectiveNetworkState::sdGameRulesObjectiveNetworkState( void ) {
|
||
|
}
|
||
|
|
||
|
void sdGameRulesObjectiveNetworkState::MakeDefault( void ) {
|
||
|
sdGameRulesNetworkState::MakeDefault();
|
||
|
|
||
|
winningTeam = NULL;
|
||
|
}
|
||
|
|
||
|
void sdGameRulesObjectiveNetworkState::Write( idFile* file ) const {
|
||
|
sdGameRulesNetworkState::Write( file );
|
||
|
|
||
|
file->WriteInt( winningTeam ? winningTeam->GetIndex() : -1 );
|
||
|
}
|
||
|
|
||
|
void sdGameRulesObjectiveNetworkState::Read( idFile* file ) {
|
||
|
sdGameRulesNetworkState::Read( file );
|
||
|
|
||
|
int winningTeamIndex;
|
||
|
file->ReadInt( winningTeamIndex );
|
||
|
winningTeam = winningTeamIndex == -1 ? NULL : &sdTeamManager::GetInstance().GetTeamByIndex( winningTeamIndex );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
sdGameRulesObjective
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
CLASS_DECLARATION( sdGameRules, sdGameRulesObjective )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::sdGameRulesObjective
|
||
|
================
|
||
|
*/
|
||
|
sdGameRulesObjective::sdGameRulesObjective( void ) : winningTeam( NULL ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::~sdGameRulesObjective
|
||
|
================
|
||
|
*/
|
||
|
sdGameRulesObjective::~sdGameRulesObjective( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_Review
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_Review( void ) {
|
||
|
if ( nextState != GS_INACTIVE ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( si_gameReviewReadyWait.GetBool() ) {
|
||
|
if ( ArePlayersReady() != RS_READY ) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NextStateDelayed( GS_NEXTMAP, MINS2MS( g_gameReviewPause.GetFloat() ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_NextGame
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_NextGame( void ) {
|
||
|
if ( nextState != GS_INACTIVE ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
NewState( GS_WARMUP );
|
||
|
|
||
|
// put everyone back in from endgame spectate
|
||
|
CheckRespawns( true );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_Warmup
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_Warmup( void ) {
|
||
|
if ( !CanStartMatch() ) {
|
||
|
needsRestart = true;
|
||
|
return;
|
||
|
}
|
||
|
StartMatch();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_Countdown
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_Countdown( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_GameOn
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_GameOn( void ) {
|
||
|
if ( gameLocal.GameState() == GAMESTATE_STARTUP || nextState != GS_INACTIVE ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int timeLimit = GetTimeLimit();
|
||
|
if ( timeLimit != 0 ) {
|
||
|
if ( gameLocal.time - matchStartedTime >= timeLimit ) {
|
||
|
OnTimeLimitHit();
|
||
|
EndGame();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GameState_NextMap
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::GameState_NextMap( void ) {
|
||
|
winningTeam = NULL;
|
||
|
|
||
|
BackupPlayerTeams();
|
||
|
|
||
|
if ( gameLocal.NextMap() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
gameLocal.LocalMapRestart();
|
||
|
|
||
|
sdTeamManagerLocal& manager = sdTeamManager::GetInstance();
|
||
|
|
||
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
||
|
idPlayer* player = gameLocal.GetClient( i );
|
||
|
if ( player == NULL ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
player->GetProficiencyTable().Clear( false );
|
||
|
player->Killed( NULL, NULL, 0, vec3_zero, -1, NULL );
|
||
|
player->ServerForceRespawn( true );
|
||
|
}
|
||
|
|
||
|
NewState( GS_NEXTGAME );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::OnGameState_Review
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::OnGameState_Review( void ) {
|
||
|
if ( !gameLocal.isClient ) {
|
||
|
nextState = GS_INACTIVE; // used to abort a game. cancel out any upcoming state change
|
||
|
ClearPlayerReadyFlags();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::OnGameState_Countdown
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::OnGameState_Countdown( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::OnGameState_GameOn
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::OnGameState_GameOn( void ) {
|
||
|
if ( !gameLocal.isClient ) {
|
||
|
if ( needsRestart ) {
|
||
|
needsRestart = false;
|
||
|
gameLocal.LocalMapRestart();
|
||
|
}
|
||
|
|
||
|
matchStartedTime = gameLocal.time;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::OnGameState_NextMap
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::OnGameState_NextMap( void ) {
|
||
|
ClearPlayerReadyFlags();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::EndGame
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::EndGame( void ) {
|
||
|
if ( IsWarmup() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
NextStateDelayed( GS_GAMEREVIEW, 1000 );
|
||
|
|
||
|
RecordWinningTeam( winningTeam, "maps", true );
|
||
|
|
||
|
CallScriptEndGame();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::ApplyNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::ApplyNetworkState( const sdEntityStateNetworkData& newState ) {
|
||
|
sdGameRules::ApplyNetworkState( newState );
|
||
|
|
||
|
NET_GET_NEW( sdGameRulesObjectiveNetworkState );
|
||
|
|
||
|
SetWinner( newData.winningTeam );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::ReadNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::ReadNetworkState( const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, const idBitMsg& msg ) const {
|
||
|
sdGameRules::ReadNetworkState( baseState, newState, msg );
|
||
|
|
||
|
NET_GET_STATES( sdGameRulesObjectiveNetworkState );
|
||
|
|
||
|
sdTeamManagerLocal& teamManager = sdTeamManager::GetInstance();
|
||
|
|
||
|
newData.winningTeam = teamManager.ReadTeamFromStream( baseData.winningTeam, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::WriteNetworkState
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::WriteNetworkState( const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, idBitMsg& msg ) const {
|
||
|
sdGameRules::WriteNetworkState( baseState, newState, msg );
|
||
|
|
||
|
NET_GET_STATES( sdGameRulesObjectiveNetworkState );
|
||
|
|
||
|
newData.winningTeam = GetWinningTeam();
|
||
|
|
||
|
sdTeamManagerLocal& teamManager = sdTeamManager::GetInstance();
|
||
|
|
||
|
teamManager.WriteTeamToStream( baseData.winningTeam, newData.winningTeam, msg );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::CheckNetworkStateChanges
|
||
|
================
|
||
|
*/
|
||
|
bool sdGameRulesObjective::CheckNetworkStateChanges( const sdEntityStateNetworkData& baseState ) const {
|
||
|
if ( sdGameRules::CheckNetworkStateChanges( baseState ) ) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
NET_GET_BASE( sdGameRulesObjectiveNetworkState );
|
||
|
|
||
|
NET_CHECK_FIELD( winningTeam, GetWinningTeam() );
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::CreateNetworkStructure
|
||
|
================
|
||
|
*/
|
||
|
sdEntityStateNetworkData* sdGameRulesObjective::CreateNetworkStructure( void ) const {
|
||
|
return new sdGameRulesObjectiveNetworkState();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::SetWinner
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::SetWinner( sdTeamInfo* team ) {
|
||
|
if ( !gameLocal.isClient && ( gameState == GS_GAMEREVIEW ) ) {
|
||
|
gameLocal.Warning( "Attempted to set winning team after game has ended" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( winningTeam == team ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
winningTeam = team;
|
||
|
if( gameLocal.DoClientSideStuff() ) {
|
||
|
UpdateClientFromServerInfo( gameLocal.serverInfo, false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::ChangeMap
|
||
|
================
|
||
|
*/
|
||
|
bool sdGameRulesObjective::ChangeMap( const char* mapName ) {
|
||
|
idStr cleanMapName = mapName;
|
||
|
sdGameRules_SingleMapHelper::SanitizeMapName( cleanMapName, true );
|
||
|
|
||
|
idStr sessionCommand = va( "usermap %s", cleanMapName.c_str() );
|
||
|
cmdSystem->PushFrameCommand( sessionCommand.c_str() );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::OnUserStartMap
|
||
|
================
|
||
|
*/
|
||
|
userMapChangeResult_e sdGameRulesObjective::OnUserStartMap( const char* text, idStr& reason, idStr& mapName ) {
|
||
|
return sdGameRules_SingleMapHelper::OnUserStartMap( text, reason, mapName );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GetGameTime
|
||
|
================
|
||
|
*/
|
||
|
int sdGameRulesObjective::GetGameTime( void ) const {
|
||
|
int ms;
|
||
|
|
||
|
if ( gameState == GS_WARMUP ) {
|
||
|
ms = 0;
|
||
|
} else if ( gameState == GS_COUNTDOWN ) {
|
||
|
ms = nextStateSwitch - gameLocal.time;
|
||
|
} else {
|
||
|
ms = GetTimeLimit() - ( gameLocal.time - matchStartedTime );
|
||
|
if ( ms < 0 ) {
|
||
|
ms = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ms;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::GetTypeText
|
||
|
================
|
||
|
*/
|
||
|
const sdDeclLocStr* sdGameRulesObjective::GetTypeText( void ) const {
|
||
|
return declHolder.declLocStrType[ "game/gametype/objective" ];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
sdGameRulesObjective::ArgCompletion_StartGame
|
||
|
================
|
||
|
*/
|
||
|
void sdGameRulesObjective::ArgCompletion_StartGame( const idCmdArgs& args, argCompletionCallback_t callback ) {
|
||
|
sdGameRules_SingleMapHelper::ArgCompletion_StartGame( args, callback );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdGameRulesObjective::UpdateClientFromServerInfo
|
||
|
============
|
||
|
*/
|
||
|
void sdGameRulesObjective::UpdateClientFromServerInfo( const idDict& serverInfo, bool allowMedia ) {
|
||
|
sdGameRules::UpdateClientFromServerInfo( serverInfo, allowMedia );
|
||
|
|
||
|
idStr mapName = serverInfo.GetString( "si_map" );
|
||
|
if( mapName.IsEmpty() ) {
|
||
|
return;
|
||
|
}
|
||
|
mapName.StripFileExtension();
|
||
|
|
||
|
using namespace sdProperties;
|
||
|
|
||
|
// update status
|
||
|
if ( sdUserInterfaceScope* scope = gameLocal.globalProperties.GetSubScope( "campaignInfo" ) ) {
|
||
|
const idDict* metaData = gameLocal.mapMetaDataList->FindMetaData( mapName, &gameLocal.defaultMetaData );
|
||
|
|
||
|
if( allowMedia ) {
|
||
|
const sdDeclMapInfo* mapInfo = gameLocal.declMapInfoType.LocalFind( metaData->GetString( "mapinfo", "_default" ) );
|
||
|
|
||
|
// setup the backdrop
|
||
|
if ( sdProperty* property = scope->GetProperty( "backdrop", PT_STRING ) ) {
|
||
|
const char* value = mapInfo->GetData().GetString( "mtr_backdrop", "guis/assets/black" );
|
||
|
*property->value.stringValue = value;
|
||
|
}
|
||
|
|
||
|
const char* status = "current";
|
||
|
if( winningTeam != NULL ) {
|
||
|
status = winningTeam->GetLookupName();
|
||
|
}
|
||
|
|
||
|
SetupLoadScreenUI( *scope, status, true, 1, *metaData, mapInfo );
|
||
|
}
|
||
|
|
||
|
// setup the name
|
||
|
if ( sdProperty* property = scope->GetProperty( "name", PT_WSTRING ) ) {
|
||
|
*property->value.wstringValue = va( L"%hs", metaData->GetString( "pretty_name" ) );
|
||
|
}
|
||
|
|
||
|
// setup the number of maps
|
||
|
if ( sdProperty* property = scope->GetProperty( "numMaps", PT_FLOAT ) ) {
|
||
|
*property->value.floatValue = 1.0f;
|
||
|
}
|
||
|
|
||
|
if ( sdProperty* property = scope->GetProperty( "currentMap", PT_FLOAT ) ) {
|
||
|
*property->value.floatValue = 1.0f;
|
||
|
}
|
||
|
|
||
|
// setup the status
|
||
|
if ( sdProperty* property = scope->GetProperty( "ruleStatus", PT_WSTRING ) ) {
|
||
|
*property->value.wstringValue = L"";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdGameRulesObjective::Clear
|
||
|
============
|
||
|
*/
|
||
|
void sdGameRulesObjective::Clear( void ) {
|
||
|
sdGameRules::Clear();
|
||
|
winningTeam = NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
sdGameRulesObjective::GetServerBrowserScore
|
||
|
============
|
||
|
*/
|
||
|
int sdGameRulesObjective::GetServerBrowserScore( const sdNetSession& session ) const {
|
||
|
int score = 0;
|
||
|
|
||
|
score += sdHotServerList::BROWSER_GOOD_BONUS - 1;
|
||
|
|
||
|
score += sdGameRules::GetServerBrowserScore( session );
|
||
|
|
||
|
return score;
|
||
|
}
|