1792 lines
48 KiB
C++
1792 lines
48 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 "VoteManager.h"
|
|
#include "../Player.h"
|
|
#include "../script/Script_Helper.h"
|
|
#include "../script/Script_ScriptObject.h"
|
|
#include "../rules/GameRules.h"
|
|
#include "../rules/AdminSystem.h"
|
|
#include "../guis/UserInterfaceLocal.h"
|
|
#include "../guis/UIList.h"
|
|
#include "../botai/Bot.h"
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
sdCallVote::AddVoteOption
|
|
================
|
|
*/
|
|
void sdCallVote::AddVoteOption( sdUIList* list, const wchar_t* text ) {
|
|
AddVoteOption( list, text, list->GetNumItems() );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdCallVote::AddVoteOption
|
|
================
|
|
*/
|
|
void sdCallVote::AddVoteOption( sdUIList* list, const wchar_t* text, int dataKey ) {
|
|
int index = sdUIList::InsertItem( list, text, -1, 0 );
|
|
list->SetItemDataInt( dataKey, index, 0 );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdCallVote::CreateCmdArgs
|
|
================
|
|
*/
|
|
void sdCallVote::CreateCmdArgs( idCmdArgs& args ) const {
|
|
args.AppendArg( "callvote" );
|
|
args.AppendArg( GetCommandName() );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class sdCallVoteAdminCommandFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdCallVoteAdminCommandFinalizer( const char* _command, const char* _suffix ) {
|
|
command = _command;
|
|
suffix = _suffix;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
args.AppendArg( "admin" );
|
|
args.AppendArg( command );
|
|
if ( suffix != NULL ) {
|
|
args.AppendArg( suffix );
|
|
}
|
|
sdAdminSystem::GetInstance().PerformCommand( args, NULL );
|
|
}
|
|
|
|
private:
|
|
const char* command;
|
|
const char* suffix;
|
|
};
|
|
|
|
/*
|
|
================
|
|
sdCallVoteAdminCommand::EnumerateOptions
|
|
================
|
|
*/
|
|
void sdCallVoteAdminCommand::EnumerateOptions( sdUIList* list ) const {
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdCallVoteAdminCommand::Execute
|
|
================
|
|
*/
|
|
void sdCallVoteAdminCommand::Execute( int dataKey ) const {
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdCallVoteAdminCommand::Execute
|
|
================
|
|
*/
|
|
sdPlayerVote* sdCallVoteAdminCommand::Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ GetVoteTextKey() ] );
|
|
vote->SetFinalizer( new sdCallVoteAdminCommandFinalizer( GetAdminCommand(), GetAdminCommandSuffix() ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
|
|
|
|
|
|
class sdCallVoteShuffleXP : public sdCallVoteAdminCommand {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/shuffleXP" ); }
|
|
virtual const char* GetCommandName( void ) const { return "shufflexp"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "shuffleteams"; }
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return "xp"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/shuffleXP/text"; }
|
|
};
|
|
|
|
class sdCallVoteShuffleRandom : public sdCallVoteAdminCommand {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/shuffleRandom" ); }
|
|
virtual const char* GetCommandName( void ) const { return "shufflerandom"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "shuffleteams"; }
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return "random"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/shuffleRandom/text"; }
|
|
};
|
|
|
|
class sdCallVoteSwapTeams : public sdCallVoteAdminCommand {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/swapTeams" ); }
|
|
virtual const char* GetCommandName( void ) const { return "swapteams"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "shuffleteams"; }
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return "swap"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/swapTeams/text"; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
class sdCallVoteRestartMap : public sdCallVoteAdminCommand {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/restartMap" ); }
|
|
virtual const char* GetCommandName( void ) const { return "restartmap"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "restartMap"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/restartMap/text"; }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class sdCallVoteCVar : public sdCallVote {
|
|
public:
|
|
struct data_t {
|
|
const char* text;
|
|
int i;
|
|
};
|
|
|
|
class sdCallVoteCVarFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdCallVoteCVarFinalizer( const char* _cvarName, data_t& _data ) {
|
|
cvarName = _cvarName;
|
|
data = _data;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
cvarSystem->SetCVarInteger( cvarName, data.i );
|
|
}
|
|
|
|
private:
|
|
const char* cvarName;
|
|
data_t data;
|
|
};
|
|
|
|
virtual void EnumerateOptions( sdUIList* list ) const {
|
|
for ( int i = 0; i < GetCount(); i++ ) {
|
|
AddVoteOption( list, common->LocalizeText( GetData()[ i ].text ).c_str() );
|
|
}
|
|
}
|
|
|
|
virtual void Execute( int dataKey ) const {
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
args.AppendArg( va( "%d", dataKey ) );
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
virtual sdPlayerVote* Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
if ( args.Argc() < 3 ) {
|
|
return NULL;
|
|
}
|
|
|
|
int value = atoi( args.Argv( 2 ) );
|
|
if ( value < 0 || value >= GetCount() ) {
|
|
return NULL;
|
|
}
|
|
|
|
data_t& data = GetData()[ value ];
|
|
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ GetVoteTextKey() ] );
|
|
vote->AddTextParm( declHolder.declLocStrType[ data.text ] );
|
|
vote->SetFinalizer( new sdCallVoteCVarFinalizer( GetCVarName(), data ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
virtual data_t* GetData( void ) const = 0;
|
|
virtual int GetCount( void ) const = 0;
|
|
|
|
virtual const char* GetCVarName( void ) const = 0;
|
|
virtual const char* GetVoteTextKey( void ) const = 0;
|
|
};
|
|
|
|
|
|
sdCallVoteCVar::data_t g_sdCallVoteCVarOnOff_Data[] = {
|
|
{ "votes/values/on", 1 },
|
|
{ "votes/values/off", 0 },
|
|
};
|
|
|
|
class sdCallVoteCVarOnOff : public sdCallVoteCVar {
|
|
public:
|
|
virtual data_t* GetData( void ) const { return g_sdCallVoteCVarOnOff_Data; }
|
|
virtual int GetCount( void ) const { return _arraycount( g_sdCallVoteCVarOnOff_Data ); }
|
|
};
|
|
|
|
class sdCallVoteBalancedTeams : public sdCallVoteCVarOnOff {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/balancedTeams" ); }
|
|
virtual const char* GetCommandName( void ) const { return "balancedteams"; }
|
|
virtual const char* GetCVarName( void ) const { return "si_teamForceBalance"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/balancedTeams/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
class sdCallVoteTeamDamage : public sdCallVoteCVarOnOff {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/teamDamage" ); }
|
|
virtual const char* GetCommandName( void ) const { return "teamdamage"; }
|
|
virtual const char* GetCVarName( void ) const { return "si_teamDamage"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/teamDamage/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
class sdCallVoteNoXP : public sdCallVoteCVarOnOff {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/noXP" ); }
|
|
virtual const char* GetCommandName( void ) const { return "noxp"; }
|
|
virtual const char* GetCVarName( void ) const { return "si_noProficiency"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/noXP/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
|
|
|
|
|
|
sdCallVoteCVar::data_t g_sdCallVoteTimeLimit_Data[] = {
|
|
{ "votes/values/5", 5 },
|
|
{ "votes/values/10", 10 },
|
|
{ "votes/values/15", 15 },
|
|
{ "votes/values/20", 20 },
|
|
{ "votes/values/25", 25 },
|
|
{ "votes/values/30", 30 },
|
|
};
|
|
|
|
class sdCallVoteTimeLimit : public sdCallVoteCVar {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/timelimit" ); }
|
|
virtual const char* GetCommandName( void ) const { return "timelimit"; }
|
|
virtual const char* GetCVarName( void ) const { return "si_timeLimit"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/timelimit/text"; }
|
|
|
|
virtual data_t* GetData( void ) const { return g_sdCallVoteTimeLimit_Data; }
|
|
virtual int GetCount( void ) const { return _arraycount( g_sdCallVoteTimeLimit_Data ); }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class sdCallVoteServerMode : public sdCallVote {
|
|
public:
|
|
class sdCallVoteServerModeFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdCallVoteServerModeFinalizer( const char* _config ) {
|
|
config = _config;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
args.AppendArg( "admin" );
|
|
args.AppendArg( "execConfig" );
|
|
args.AppendArg( config.c_str() );
|
|
sdAdminSystem::GetInstance().PerformCommand( args, NULL );
|
|
}
|
|
|
|
private:
|
|
idStr config;
|
|
};
|
|
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/serverMode" ); }
|
|
virtual const char* GetCommandName( void ) const { return "servermode"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ "votes/serverMode/text" ]; }
|
|
|
|
virtual void EnumerateOptions( sdUIList* list ) const {
|
|
const idDict& configs = sdUserGroupManager::GetInstance().GetConfigs();
|
|
for ( int i = 0; i < configs.GetNumKeyVals(); i++ ) {
|
|
AddVoteOption( list, va( L"%hs", configs.GetKeyVal( i )->GetKey().c_str() ) );
|
|
}
|
|
}
|
|
|
|
virtual void Execute( int dataKey ) const {
|
|
const idDict& configs = sdUserGroupManager::GetInstance().GetConfigs();
|
|
if ( dataKey < 0 || dataKey >= configs.GetNumKeyVals() ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
args.AppendArg( configs.GetKeyVal( dataKey )->GetKey().c_str() );
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
virtual sdPlayerVote* Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
if ( args.Argc() < 3 ) {
|
|
return NULL;
|
|
}
|
|
|
|
const char* configName = args.Argv( 2 );
|
|
|
|
const idDict& configs = sdUserGroupManager::GetInstance().GetConfigs();
|
|
if ( configs.FindKey( configName ) == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ "votes/serverMode/text" ] );
|
|
vote->AddTextParm( va( L"%hs", configName ) );
|
|
vote->SetFinalizer( new sdCallVoteServerModeFinalizer( configName ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
};
|
|
|
|
|
|
class sdPlayerCallVote : public sdCallVote {
|
|
public:
|
|
class sdPlayerCallVoteFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdPlayerCallVoteFinalizer( idPlayer* _player, const char* _command, const char* _suffix ) {
|
|
player = _player;
|
|
command = _command;
|
|
suffix = _suffix;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
if ( !player.IsValid() ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
args.AppendArg( "admin" );
|
|
args.AppendArg( command );
|
|
args.AppendArg( player->userInfo.cleanName.c_str() );
|
|
if ( suffix != NULL ) {
|
|
args.AppendArg( suffix );
|
|
}
|
|
sdAdminSystem::GetInstance().PerformCommand( args, NULL );
|
|
}
|
|
|
|
private:
|
|
idEntityPtr< idPlayer > player;
|
|
const char* command;
|
|
const char* suffix;
|
|
};
|
|
|
|
virtual void EnumerateOptions( sdUIList* list ) const {
|
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
|
idPlayer* player = gameLocal.GetClient( i );
|
|
if ( player == NULL || gameLocal.IsLocalPlayer( player ) ) {
|
|
continue;
|
|
}
|
|
|
|
AddVoteOption( list, va( L"%hs", player->userInfo.name.c_str() ), gameLocal.GetSpawnId( player ) );
|
|
}
|
|
}
|
|
|
|
virtual void Execute( int dataKey ) const {
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
args.AppendArg( va( "%d", dataKey ) );
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
virtual sdPlayerVote* Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
if ( args.Argc() < 3 ) {
|
|
return NULL;
|
|
}
|
|
|
|
int spawnId = atoi( args.Argv( 2 ) );
|
|
idPlayer* other = gameLocal.EntityForSpawnId( spawnId )->Cast< idPlayer >();
|
|
if ( other == NULL || other == player ) {
|
|
return NULL;
|
|
}
|
|
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ GetVoteTextKey() ] );
|
|
vote->AddTextParm( va( L"%hs", other->userInfo.name.c_str() ) );
|
|
vote->SetFinalizer( new sdPlayerCallVoteFinalizer( other, GetAdminCommand(), GetAdminCommandSuffix() ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
virtual const char* GetCommandName( void ) const = 0;
|
|
virtual const char* GetAdminCommand( void ) const = 0;
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return NULL; }
|
|
virtual const char* GetVoteTextKey( void ) const = 0;
|
|
};
|
|
|
|
class sdCallVoteKickPlayer : public sdPlayerCallVote {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/kickplayer" ); }
|
|
virtual const char* GetCommandName( void ) const { return "kickplayer"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "kick"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/kickplayer/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
};
|
|
|
|
class sdCallVoteMutePlayer : public sdPlayerCallVote {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/mute" ); }
|
|
virtual const char* GetCommandName( void ) const { return "muteplayer"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "playerMute"; }
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return "on"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/mute/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
};
|
|
|
|
class sdCallVoteMuteVoicePlayer : public sdPlayerCallVote {
|
|
public:
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/mutevoice" ); }
|
|
virtual const char* GetCommandName( void ) const { return "muteplayervoip"; }
|
|
virtual const char* GetAdminCommand( void ) const { return "playerVOIPMute"; }
|
|
virtual const char* GetAdminCommandSuffix( void ) const { return "on"; }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/mutevoice/text"; }
|
|
virtual void PreCache( void ) const { gameLocal.declToolTipType[ GetVoteTextKey() ]; }
|
|
};
|
|
|
|
class sdCallVoteMapChange : public sdCallVote {
|
|
public:
|
|
static const idDict* sdCallVoteMapChange::GetMapData( const char* name ) {
|
|
const metaDataContext_t* metaData = gameLocal.mapMetaDataList->FindMetaDataContext( name );
|
|
if ( metaData == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ( !gameLocal.IsMetaDataValidForPlay( *metaData, true ) ) {
|
|
return NULL;
|
|
}
|
|
|
|
return metaData->meta;
|
|
}
|
|
|
|
static const idDict* sdCallVoteMapChange::GetMapData( int index ) {
|
|
if( index < 0 || index > gameLocal.mapMetaDataList->GetNumMetaData() ) {
|
|
return NULL;
|
|
}
|
|
const metaDataContext_t& metaData = gameLocal.mapMetaDataList->GetMetaDataContext( index );
|
|
if ( !gameLocal.IsMetaDataValidForPlay( metaData, true ) ) {
|
|
return NULL;
|
|
}
|
|
|
|
return metaData.meta;
|
|
}
|
|
|
|
static const sdDeclMapInfo* sdCallVoteMapChange::GetMapInfo( const char* name ) {
|
|
const idDict* mapData = GetMapData( name );
|
|
if ( mapData == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
const char* mapInfoName = mapData->GetString( "mapinfo" );
|
|
if ( mapInfoName[ 0 ] == '\0' ) {
|
|
return NULL;
|
|
}
|
|
|
|
return gameLocal.declMapInfoType[ mapInfoName ];
|
|
}
|
|
|
|
static const sdDeclMapInfo* sdCallVoteMapChange::GetMapInfo( int index ) {
|
|
const idDict* mapData = GetMapData( index );
|
|
if ( mapData == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
const char* mapInfoName = mapData->GetString( "mapinfo" );
|
|
if ( mapInfoName[ 0 ] == '\0' ) {
|
|
return NULL;
|
|
}
|
|
|
|
return gameLocal.declMapInfoType[ mapInfoName ];
|
|
}
|
|
|
|
class sdCallVoteMapChangeFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdCallVoteMapChangeFinalizer( const char* _mapName, const char* _mode ) {
|
|
mapName = _mapName;
|
|
mode = _mode;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
args.AppendArg( "admin" );
|
|
args.AppendArg( mode );
|
|
args.AppendArg( mapName.c_str() );
|
|
sdAdminSystem::GetInstance().PerformCommand( args, NULL );
|
|
}
|
|
|
|
private:
|
|
idStr mapName;
|
|
const char* mode;
|
|
};
|
|
|
|
virtual void sdCallVoteMapChange::EnumerateOptions( sdUIList* list ) const {
|
|
for ( int i = 0; i < gameLocal.mapMetaDataList->GetNumMetaData(); i++ ) {
|
|
const idDict* mapInfo = GetMapData( i );
|
|
if ( mapInfo == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
const char* materialName = mapInfo->GetString( "server_shot_thumb", "levelshots/thumbs/generic.tga" );
|
|
AddVoteOption( list, va( L"%hs\t%hs\t1.7777", mapInfo->GetString( "pretty_name", "" ), materialName ), i );
|
|
}
|
|
}
|
|
|
|
virtual void sdCallVoteMapChange::Execute( int dataKey ) const {
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
|
|
const char* name = GetMapData( dataKey )->GetString( "metadata_name" );
|
|
|
|
args.AppendArg( name );
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
virtual sdPlayerVote* sdCallVoteMapChange::Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
if ( args.Argc() < 3 ) {
|
|
return NULL;
|
|
}
|
|
|
|
const char* metaDataName = args.Argv( 2 );
|
|
|
|
const idDict* mapData = GetMapData( metaDataName );
|
|
if ( mapData == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
const sdDeclMapInfo* mapInfo = GetMapInfo( metaDataName );
|
|
if ( mapInfo == NULL ) {
|
|
assert( false );
|
|
return NULL;
|
|
}
|
|
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ GetVoteTextKey() ] );
|
|
vote->AddTextParm( va( L"%hs", mapData->GetString( "pretty_name", "" ) ) );
|
|
vote->SetFinalizer( new sdCallVoteMapChangeFinalizer( mapData->GetString( "metadata_name" ), GetModeName() ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
virtual const char* GetVoteTextKey( void ) const = 0;
|
|
virtual const char* GetModeName( void ) const = 0;
|
|
|
|
virtual void PreCache( void ) const { PreCache( this ); }
|
|
|
|
protected:
|
|
static void PreCache( const sdCallVoteMapChange* command ) {
|
|
gameLocal.declToolTipType[ command->GetVoteTextKey() ];
|
|
}
|
|
};
|
|
|
|
class sdCallVoteObjectiveMap : public sdCallVoteMapChange {
|
|
public:
|
|
virtual const char* GetCommandName( void ) const { return "setobjectivemap"; }
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/setobjectivemap" ); }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/setobjectivemap/text"; }
|
|
virtual const char* GetModeName( void ) const { return "setObjectiveMap"; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
class sdCallVoteStopWatchMap : public sdCallVoteMapChange {
|
|
public:
|
|
virtual const char* GetCommandName( void ) const { return "setstopwatchmap"; }
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/setstopwatchmap" ); }
|
|
virtual const char* GetVoteTextKey( void ) const { return "votes/setstopwatchmap/text"; }
|
|
virtual const char* GetModeName( void ) const { return "setStopWatchMap"; }
|
|
virtual bool AllowedOnRankedServer( void ) const { return false; }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class sdCallVoteCampaignChange : public sdCallVote {
|
|
public:
|
|
virtual const char* GetCommandName( void ) const { return "setcampaign"; }
|
|
virtual void GetText( idWStr& out ) const { out = common->LocalizeText( "votes/setcampaign" ); }
|
|
|
|
class sdCallVoteCampaignChangeFinalizer : public sdVoteFinalizer {
|
|
public:
|
|
sdCallVoteCampaignChangeFinalizer( const char* _campaignName ) {
|
|
campaignName = _campaignName;
|
|
}
|
|
|
|
virtual void OnVoteCompleted( bool passed ) const {
|
|
if ( !passed ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
args.AppendArg( "admin" );
|
|
args.AppendArg( "setCampaign" );
|
|
args.AppendArg( campaignName.c_str() );
|
|
sdAdminSystem::GetInstance().PerformCommand( args, NULL );
|
|
}
|
|
|
|
private:
|
|
idStr campaignName;
|
|
};
|
|
|
|
virtual void EnumerateOptions( sdUIList* list ) const {
|
|
for( int i = 0; i < gameLocal.campaignMetaDataList->GetNumMetaData(); i++ ) {
|
|
const metaDataContext_t& metaData = gameLocal.campaignMetaDataList->GetMetaDataContext( i );
|
|
if ( !gameLocal.IsMetaDataValidForPlay( metaData, true ) ) {
|
|
continue;
|
|
}
|
|
const idDict& dict = *metaData.meta;
|
|
|
|
const char* materialName = dict.GetString( "server_shot_thumb" );
|
|
const char* prettyName = dict.GetString( "pretty_name" );
|
|
|
|
AddVoteOption( list, va( L"%hs\t%hs\t1.333", prettyName, materialName ), i );
|
|
}
|
|
}
|
|
|
|
virtual void Execute( int dataKey ) const {
|
|
if( dataKey < 0 || dataKey >= gameLocal.campaignMetaDataList->GetNumMetaData() ) {
|
|
gameLocal.Warning( "sdCallVoteCampaignChange: index '%i' out of range", dataKey );
|
|
return;
|
|
}
|
|
const metaDataContext_t& metaData = gameLocal.campaignMetaDataList->GetMetaDataContext( dataKey );
|
|
if ( !gameLocal.IsMetaDataValidForPlay( metaData, true ) ) {
|
|
return;
|
|
}
|
|
|
|
const idDict& dict = *metaData.meta;
|
|
const sdDeclCampaign* campaign = gameLocal.declCampaignType.LocalFind( dict.GetString( "metadata_name" ), false );
|
|
if ( campaign == NULL ) {
|
|
return;
|
|
}
|
|
|
|
idCmdArgs args;
|
|
CreateCmdArgs( args );
|
|
args.AppendArg( campaign->GetName() );
|
|
|
|
sdVoteManagerLocal::Callvote_f( args );
|
|
}
|
|
|
|
virtual sdPlayerVote* Execute( const idCmdArgs& args, idPlayer* player ) const {
|
|
if ( args.Argc() < 3 ) {
|
|
return NULL;
|
|
}
|
|
|
|
const char* campaignName = args.Argv( 2 );
|
|
|
|
const metaDataContext_t* metaData = gameLocal.campaignMetaDataList->FindMetaDataContext( campaignName );
|
|
if ( metaData == NULL ) {
|
|
return NULL;
|
|
}
|
|
if ( !gameLocal.IsMetaDataValidForPlay( *metaData, true ) ) {
|
|
return NULL;
|
|
}
|
|
|
|
const sdDeclCampaign* campaign = gameLocal.declCampaignType[ campaignName ];
|
|
if ( campaign == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
sdPlayerVote* vote = sdVoteManager::GetInstance().AllocVote();
|
|
if ( vote != NULL ) {
|
|
vote->MakeGlobalVote();
|
|
vote->SetText( gameLocal.declToolTipType[ "votes/setcampaign/text" ] );
|
|
const idDict* dict = gameLocal.campaignMetaDataList->FindMetaData( campaignName, &gameLocal.defaultMetaData );
|
|
vote->AddTextParm( va( L"%hs", dict->GetString( "pretty_name" ) ) );
|
|
vote->SetFinalizer( new sdCallVoteCampaignChangeFinalizer( campaignName ) );
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
virtual void PreCache( void ) const {
|
|
gameLocal.declToolTipType[ "votes/setcampaign/text" ];
|
|
}
|
|
};
|
|
|
|
/*
|
|
================
|
|
sdVoteModePrivate::sdVoteModePrivate
|
|
================
|
|
*/
|
|
sdVoteModePrivate::sdVoteModePrivate( idPlayer* other ) {
|
|
client = other;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteModePrivate::CanVote
|
|
================
|
|
*/
|
|
bool sdVoteModePrivate::CanVote( idPlayer* player ) const {
|
|
return client == player;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
sdVoteModeTeam::sdVoteModeTeam
|
|
================
|
|
*/
|
|
sdVoteModeTeam::sdVoteModeTeam( sdTeamInfo* _team ) {
|
|
team = _team;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteModeTeam::CanVote
|
|
================
|
|
*/
|
|
bool sdVoteModeTeam::CanVote( idPlayer* player ) const {
|
|
return player->GetTeam() == team;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
sdVoteModeGlobal::CanVote
|
|
================
|
|
*/
|
|
bool sdVoteModeGlobal::CanVote( idPlayer* player ) const {
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
sdVoteFinalizer_Script::sdVoteFinalizer_Script
|
|
================
|
|
*/
|
|
sdVoteFinalizer_Script::sdVoteFinalizer_Script( idScriptObject* object, const char* functionName ) : scriptObjectHandle( 0 ), function( NULL ) {
|
|
if ( !object ) {
|
|
gameLocal.Warning( "sdVoteFinalizer_Script::sdVoteFinalizer_Script No Scriptobject" );
|
|
return;
|
|
}
|
|
|
|
scriptObjectHandle = object->GetHandle();
|
|
function = object->GetFunction( functionName );
|
|
|
|
if ( !function ) {
|
|
gameLocal.Warning( "sdVoteFinalizer_Script::sdVoteFinalizer_Script Invalid Function '%s'", functionName );
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteFinalizer_Script::OnVoteCompleted
|
|
================
|
|
*/
|
|
void sdVoteFinalizer_Script::OnVoteCompleted( bool passed ) const {
|
|
idScriptObject* object = gameLocal.program->GetScriptObject( scriptObjectHandle );
|
|
if ( !object || !function ) {
|
|
return;
|
|
}
|
|
|
|
sdScriptHelper h1;
|
|
h1.Push( passed ? 1.f : 0.f );
|
|
object->CallNonBlockingScriptEvent( function, h1 );
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::sdPlayerVote
|
|
================
|
|
*/
|
|
sdPlayerVote::sdPlayerVote( void ) : index( -1 ), mode( NULL ), endTime( 0 ), finalizer( NULL ),
|
|
yesCount( 0 ), noCount( 0 ), totalCount( 0 ), text( NULL ), voteId( VI_NONE ), displayFinishedMessage( true ) {
|
|
|
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
|
votes[ i ] = VS_CANNOT_VOTE;
|
|
}
|
|
activeNode.SetOwner( this );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::~sdPlayerVote
|
|
================
|
|
*/
|
|
sdPlayerVote::~sdPlayerVote( void ) {
|
|
ClearMode();
|
|
ClearFinalizer();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::AddTextParm
|
|
================
|
|
*/
|
|
void sdPlayerVote::AddTextParm( const sdDeclLocStr* text ) {
|
|
textParm_t& parm = textParms.Alloc();
|
|
parm.locStr = text;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::AddTextParm
|
|
================
|
|
*/
|
|
void sdPlayerVote::AddTextParm( const wchar_t* text ) {
|
|
textParm_t& parm = textParms.Alloc();
|
|
parm.text = text;
|
|
parm.locStr = NULL;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::MakeTeamVote
|
|
================
|
|
*/
|
|
void sdPlayerVote::MakeTeamVote( sdTeamInfo* team ) {
|
|
ClearMode();
|
|
mode = new sdVoteModeTeam( team );
|
|
SetVoteFlags();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::MakePrivateVote
|
|
================
|
|
*/
|
|
void sdPlayerVote::MakePrivateVote( idPlayer* client ) {
|
|
ClearMode();
|
|
mode = new sdVoteModePrivate( client );
|
|
SetVoteFlags();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::MakeGlobalVote
|
|
================
|
|
*/
|
|
void sdPlayerVote::MakeGlobalVote( void ) {
|
|
ClearMode();
|
|
mode = new sdVoteModeGlobal();
|
|
SetVoteFlags();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::ClearMode
|
|
================
|
|
*/
|
|
void sdPlayerVote::ClearMode( void ) {
|
|
delete mode;
|
|
mode = NULL;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::ClearFinalizer
|
|
================
|
|
*/
|
|
void sdPlayerVote::ClearFinalizer( void ) {
|
|
delete finalizer;
|
|
finalizer = NULL;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::SetVoteFlags
|
|
================
|
|
*/
|
|
void sdPlayerVote::SetVoteFlags( void ) {
|
|
if ( gameLocal.isClient ) {
|
|
if ( voteCaller.IsValid() && gameLocal.IsLocalPlayer( voteCaller ) ) {
|
|
votes[ gameLocal.localClientNum ] = VS_YES;
|
|
} else {
|
|
votes[ gameLocal.localClientNum ] = VS_NOT_VOTED;
|
|
}
|
|
return;
|
|
}
|
|
|
|
assert( mode );
|
|
|
|
totalCount = 0;
|
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
|
idPlayer* player = gameLocal.GetClient( i );
|
|
if ( !player || player->GetType()->IsType( idBot::Type ) || !mode->CanVote( player ) ) {
|
|
votes[ i ] = VS_CANNOT_VOTE;
|
|
} else {
|
|
totalCount++;
|
|
votes[ i ] = VS_NOT_VOTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Start
|
|
================
|
|
*/
|
|
void sdPlayerVote::Start( idPlayer* player ) {
|
|
int length = text ? text->GetLength() : SEC2MS( 30.f );
|
|
endTime = gameLocal.ToGuiTime( gameLocal.time + length );
|
|
sdVoteManager::GetInstance().MakeActive( activeNode );
|
|
|
|
voteCaller = player;
|
|
|
|
if ( text ) {
|
|
finalText.Clear();
|
|
if ( player != NULL ) {
|
|
const sdDeclLocStr* locStr = declHolder.declLocStrType[ "votes/playercalled" ];
|
|
if ( locStr != NULL ) {
|
|
idWStrList parms( 1 ); parms.Append( va( L"%hs", player->GetUserInfo().name.c_str() ) );
|
|
finalText = common->LocalizeText( locStr, parms );
|
|
}
|
|
}
|
|
|
|
sdToolTipParms parms;
|
|
for ( int i = 0; i < textParms.Num(); i++ ) {
|
|
if ( textParms[ i ].locStr != NULL ) {
|
|
parms.Add( textParms[ i ].locStr->GetText() );
|
|
} else {
|
|
parms.Add( textParms[ i ].text.c_str() );
|
|
}
|
|
}
|
|
|
|
idWStr guiText;
|
|
text->GetMessage( &parms, guiText );
|
|
finalText.Append( guiText );
|
|
}
|
|
|
|
if ( gameLocal.isServer ) {
|
|
sdReliableServerMessage msg( GAME_RELIABLE_SMESSAGE_VOTE );
|
|
msg.WriteBits( sdVoteManagerLocal::VM_CREATE, idMath::BitsForInteger( sdVoteManagerLocal::VM_NUM ) );
|
|
msg.WriteBits( index, idMath::BitsForInteger( sdVoteManagerLocal::MAX_VOTES ) );
|
|
if ( player != NULL ) {
|
|
msg.WriteBits( 1, 1 );
|
|
msg.WriteByte( player->entityNumber );
|
|
} else {
|
|
msg.WriteBits( 0, 1 );
|
|
|
|
}
|
|
|
|
msg.WriteBits( text ? text->Index() + 1 : 0, idMath::BitsForInteger( gameLocal.declToolTipType.Num() + 1 ) );
|
|
msg.WriteLong( textParms.Num() );
|
|
for ( int i = 0; i < textParms.Num(); i++ ) {
|
|
if ( textParms[ i ].locStr != NULL ) {
|
|
msg.WriteBool( false );
|
|
msg.WriteLong( textParms[ i ].locStr->Index() );
|
|
} else {
|
|
msg.WriteBool( true );
|
|
msg.WriteString( textParms[ i ].text.c_str() );
|
|
}
|
|
}
|
|
|
|
msg.WriteLong( endTime );
|
|
SendMessage( msg );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Vote
|
|
================
|
|
*/
|
|
void sdPlayerVote::Vote( bool result ) {
|
|
if ( result ) {
|
|
yesCount++;
|
|
} else {
|
|
noCount++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Vote
|
|
================
|
|
*/
|
|
void sdPlayerVote::Vote( idPlayer* client, bool result ) {
|
|
int clientIndex = client->entityNumber;
|
|
|
|
if ( votes[ clientIndex ] != VS_NOT_VOTED ) {
|
|
// already voted or not eligible
|
|
// TODO: send message
|
|
return;
|
|
}
|
|
|
|
if ( result ) {
|
|
votes[ clientIndex ] = VS_YES;
|
|
yesCount++;
|
|
} else {
|
|
votes[ clientIndex ] = VS_NO;
|
|
noCount++;
|
|
}
|
|
|
|
if ( gameLocal.isServer ) {
|
|
sdReliableServerMessage msg( GAME_RELIABLE_SMESSAGE_VOTE );
|
|
msg.WriteBits( sdVoteManagerLocal::VM_VOTE, idMath::BitsForInteger( sdVoteManagerLocal::VM_NUM ) );
|
|
msg.WriteBits( index, idMath::BitsForInteger( sdVoteManagerLocal::MAX_VOTES ) );
|
|
msg.WriteBool( result );
|
|
SendMessage( msg );
|
|
}
|
|
|
|
// check if there are enough people left for it to be able to fail/pass
|
|
int votesLeft = totalCount - ( noCount + yesCount );
|
|
float minYesPcnt = ( yesCount ) / ( float )totalCount;
|
|
float maxYesPcnt = ( yesCount + votesLeft ) / ( float )totalCount;
|
|
float passPcnt = GetPassPercentage();
|
|
|
|
if ( minYesPcnt >= passPcnt || maxYesPcnt < passPcnt ) {
|
|
endTime = 0; // this will make us be marked as complete on next check
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::ClientVote
|
|
================
|
|
*/
|
|
void sdPlayerVote::ClientVote( bool result ) {
|
|
assert( gameLocal.isClient );
|
|
|
|
votes[ gameLocal.localClientNum ] = result ? VS_YES : VS_NO;
|
|
|
|
sdReliableClientMessage msg( GAME_RELIABLE_CMESSAGE_VOTE );
|
|
msg.WriteBits( GetIndex(), idMath::BitsForInteger( sdVoteManagerLocal::MAX_VOTES ) );
|
|
msg.WriteLong( GetEndTime() );
|
|
msg.WriteBool( result );
|
|
msg.Send();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::SendMessage
|
|
================
|
|
*/
|
|
void sdPlayerVote::SendMessage( sdReliableServerMessage& msg ) {
|
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
|
if ( votes[ i ] == VS_CANNOT_VOTE ) {
|
|
continue;
|
|
}
|
|
|
|
msg.Send( sdReliableMessageClientInfo( i ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Tag
|
|
================
|
|
*/
|
|
void sdPlayerVote::Tag( voteId_t id, idEntity* object ) {
|
|
voteId = id;
|
|
voteObject = object;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Match
|
|
================
|
|
*/
|
|
bool sdPlayerVote::Match( voteId_t id, idEntity* object ) {
|
|
return voteId == id && voteObject == object;
|
|
}
|
|
|
|
idCVar g_votePassPercentage( "g_votePassPercentage", "51", CVAR_GAME | CVAR_FLOAT | CVAR_ARCHIVE | CVAR_RANKLOCKED, "Percentage of yes votes required for a vote to pass", 0.f, 100.f );
|
|
idCVar g_minAutoVotePlayers( "g_minAutoVotePlayers", "0", CVAR_GAME | CVAR_INTEGER | CVAR_ARCHIVE, "If this number of players has voted, then the vote will be considered valid even if the required % of yes/no votes has not been met" );
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::GetPassPercentage
|
|
================
|
|
*/
|
|
float sdPlayerVote::GetPassPercentage( void ) const {
|
|
return g_votePassPercentage.GetFloat() / 100.f;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::Complete
|
|
================
|
|
*/
|
|
void sdPlayerVote::Complete( void ) {
|
|
bool passed;
|
|
if ( g_minAutoVotePlayers.GetInteger() > 0 && ( yesCount + noCount ) >= g_minAutoVotePlayers.GetInteger() ) {
|
|
passed = yesCount > noCount;
|
|
} else {
|
|
float frac = ( yesCount / ( float )totalCount );
|
|
passed = frac >= GetPassPercentage();
|
|
}
|
|
|
|
if ( displayFinishedMessage ) {
|
|
const sdDeclLocStr* finishedMessage = NULL;
|
|
if ( passed ) {
|
|
finishedMessage = declHolder.declLocStrType[ "votes/finished/success" ];
|
|
} else {
|
|
finishedMessage = declHolder.declLocStrType[ "votes/finished/failed" ];
|
|
}
|
|
|
|
if ( finishedMessage == NULL ) {
|
|
gameLocal.Warning( "sdPlayerVote::Complete Missing Vote Complete Mission" );
|
|
} else {
|
|
for ( int i = 0; i < MAX_CLIENTS; i++ ) {
|
|
if ( votes[ i ] == VS_CANNOT_VOTE ) {
|
|
continue;
|
|
}
|
|
|
|
idPlayer* player = gameLocal.GetClient( i );
|
|
if ( !player ) {
|
|
continue;
|
|
}
|
|
|
|
player->SendLocalisedMessage( finishedMessage, idWStrList() );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( finalizer == NULL ) {
|
|
gameLocal.Warning( "sdPlayerVote::Complete Vote completed with no Finalizer" );
|
|
return;
|
|
}
|
|
|
|
finalizer->OnVoteCompleted( passed );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPlayerVote::GetPlayerCanVote
|
|
================
|
|
*/
|
|
bool sdPlayerVote::GetPlayerCanVote( idPlayer* player ) const {
|
|
return votes[ player->entityNumber ] == VS_NOT_VOTED;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::sdVoteManagerLocal
|
|
================
|
|
*/
|
|
sdVoteManagerLocal::sdVoteManagerLocal( void ) {
|
|
memset( votes, 0, sizeof( votes ) );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::~sdVoteManagerLocal
|
|
================
|
|
*/
|
|
sdVoteManagerLocal::~sdVoteManagerLocal( void ) {
|
|
globalCallVotes.DeleteContents( true );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::AllocVote
|
|
================
|
|
*/
|
|
sdPlayerVote* sdVoteManagerLocal::AllocVote( int index ) {
|
|
if ( index == -1 ) {
|
|
if ( gameLocal.isClient ) {
|
|
gameLocal.Error( "sdVoteManagerLocal::AllocVote Tried to Create a Vote on a Network Client" );
|
|
return NULL;
|
|
}
|
|
|
|
for ( int i = 0; i < MAX_VOTES; i++ ) {
|
|
if ( votes[ i ] != NULL ) {
|
|
continue;
|
|
}
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( index == -1 ) {
|
|
gameLocal.Error( "sdVoteManagerLocal::AllocVote Max Votes Hit" );
|
|
return NULL;
|
|
}
|
|
|
|
votes[ index ] = new sdPlayerVote();
|
|
votes[ index ]->Init( index );
|
|
return votes[ index ];
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::Think
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::Think( void ) {
|
|
sdPlayerVote* next = activeVotes.Next();
|
|
for ( sdPlayerVote* vote = next; vote; vote = next ) {
|
|
next = vote->GetNextActiveVote();
|
|
|
|
int endTime = vote->GetEndTime();
|
|
if ( gameLocal.ToGuiTime( gameLocal.time ) < endTime ) {
|
|
continue;
|
|
}
|
|
|
|
int index = vote->GetIndex();
|
|
|
|
vote->Complete();
|
|
|
|
FreeVote( index );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::FreeVote
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::FreeVote( int index ) {
|
|
if ( index < 0 || index > MAX_VOTES ) {
|
|
assert( false );
|
|
return;
|
|
}
|
|
|
|
sdPlayerVote* vote = votes[ index ];
|
|
if( vote == NULL ) {
|
|
return;
|
|
}
|
|
|
|
if ( gameLocal.isServer ) {
|
|
sdReliableServerMessage msg( GAME_RELIABLE_SMESSAGE_VOTE );
|
|
msg.WriteBits( VM_FREE, idMath::BitsForInteger( VM_NUM ) );
|
|
msg.WriteBits( index, idMath::BitsForInteger( sdVoteManagerLocal::MAX_VOTES ) );
|
|
vote->SendMessage( msg );
|
|
}
|
|
|
|
delete votes[ index ];
|
|
votes[ index ] = NULL;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::AllocVote
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::FreeVotes( void ) {
|
|
for ( int i = 0; i < MAX_VOTES; i++ ) {
|
|
FreeVote( i );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::Init
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::Init( void ) {
|
|
globalCallVotes.Alloc() = new sdCallVoteObjectiveMap();
|
|
globalCallVotes.Alloc() = new sdCallVoteStopWatchMap();
|
|
globalCallVotes.Alloc() = new sdCallVoteCampaignChange();
|
|
globalCallVotes.Alloc() = new sdCallVoteShuffleXP();
|
|
globalCallVotes.Alloc() = new sdCallVoteShuffleRandom();
|
|
globalCallVotes.Alloc() = new sdCallVoteSwapTeams();
|
|
globalCallVotes.Alloc() = new sdCallVoteBalancedTeams();
|
|
globalCallVotes.Alloc() = new sdCallVoteTeamDamage();
|
|
globalCallVotes.Alloc() = new sdCallVoteNoXP();
|
|
globalCallVotes.Alloc() = new sdCallVoteTimeLimit();
|
|
globalCallVotes.Alloc() = new sdCallVoteServerMode();
|
|
globalCallVotes.Alloc() = new sdCallVoteKickPlayer();
|
|
globalCallVotes.Alloc() = new sdCallVoteMutePlayer();
|
|
globalCallVotes.Alloc() = new sdCallVoteMuteVoicePlayer();
|
|
for( int i = 0; i < globalCallVotes.Num(); i++ ) {
|
|
globalCallVotes[ i ]->PreCache();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::MakeActive
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::MakeActive( idLinkList< sdPlayerVote >& node ) {
|
|
node.AddToEnd( activeVotes );
|
|
}
|
|
|
|
idCVar g_voteKeepVote( "g_voteKeepVote", "1", CVAR_GAME | CVAR_BOOL | CVAR_ARCHIVE, "Keep vote on the HUD after having voted" );
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::GetActiveVote
|
|
================
|
|
*/
|
|
sdPlayerVote* sdVoteManagerLocal::GetActiveVote( idPlayer* p ) {
|
|
if ( p == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
// get first vote player hasn't voted on
|
|
for ( sdPlayerVote* vote = activeVotes.Next(); vote != NULL; vote = vote->GetNextActiveVote() ) {
|
|
if ( !vote->GetPlayerCanVote( p ) ) {
|
|
continue;
|
|
}
|
|
|
|
return vote;
|
|
}
|
|
|
|
// get first vote player is part of
|
|
if ( g_voteKeepVote.GetBool() ) {
|
|
for ( sdPlayerVote* vote = activeVotes.Next(); vote != NULL; vote = vote->GetNextActiveVote() ) {
|
|
if ( vote->GetVoteState( p ) != sdPlayerVote::VS_CANNOT_VOTE ) {
|
|
return vote;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::ClientReadNetworkMessage
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::ClientReadNetworkMessage( const idBitMsg& msg ) {
|
|
idPlayer* player = NULL;
|
|
|
|
voteMessage_t message = ( voteMessage_t )msg.ReadBits( idMath::BitsForInteger( VM_NUM ) );
|
|
switch ( message ) {
|
|
case VM_CREATE: {
|
|
int index = msg.ReadBits( idMath::BitsForInteger( MAX_VOTES ) );
|
|
FreeVote( index );
|
|
|
|
if ( msg.ReadBits( 1 ) != 0 ) {
|
|
int client = msg.ReadByte();
|
|
if ( client >= 0 || client < MAX_CLIENTS ) {
|
|
player = gameLocal.GetClient( client );
|
|
}
|
|
}
|
|
|
|
sdPlayerVote* vote = AllocVote( index );
|
|
|
|
int toolTipIndex = msg.ReadBits( idMath::BitsForInteger( gameLocal.declToolTipType.Num() ) );
|
|
const sdDeclToolTip* toolTip = toolTipIndex ? gameLocal.declToolTipType[ toolTipIndex - 1 ] : NULL;
|
|
vote->SetText( toolTip );
|
|
|
|
int textCount = msg.ReadLong();
|
|
for ( int i = 0; i < textCount; i++ ) {
|
|
if ( !msg.ReadBool() ) {
|
|
vote->AddTextParm( declHolder.declLocStrType.SafeIndex( msg.ReadLong() ) );
|
|
} else {
|
|
wchar_t buffer[ 128 ];
|
|
msg.ReadString( buffer, sizeof( buffer ) / sizeof( wchar_t ) );
|
|
vote->AddTextParm( buffer );
|
|
}
|
|
}
|
|
|
|
vote->Start( player );
|
|
vote->SetEndTime( msg.ReadLong() );
|
|
vote->SetVoteFlags();
|
|
|
|
break;
|
|
}
|
|
case VM_FREE: {
|
|
int index = msg.ReadBits( idMath::BitsForInteger( MAX_VOTES ) );
|
|
FreeVote( index );
|
|
break;
|
|
}
|
|
case VM_VOTE: {
|
|
int index = msg.ReadBits( idMath::BitsForInteger( MAX_VOTES ) );
|
|
sdPlayerVote* v = votes[ index ];
|
|
if ( v ) {
|
|
v->Vote( msg.ReadBool() );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdVoteManagerLocal::ServerReadNetworkMessage
|
|
================
|
|
*/
|
|
void sdVoteManagerLocal::ServerReadNetworkMessage( idPlayer* client, const idBitMsg& msg ) {
|
|
int index = msg.ReadBits( idMath::BitsForInteger( MAX_VOTES ) );
|
|
int endTime = msg.ReadLong();
|
|
bool result = msg.ReadBool();
|
|
|
|
sdPlayerVote* v = votes[ index ];
|
|
if ( !v ) {
|
|
return;
|
|
}
|
|
|
|
if ( v->GetEndTime() != endTime ) {
|
|
return; // try to make sure we are talking about the same vote
|
|
}
|
|
|
|
v->Vote( client, result );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::PerformCommand
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::PerformCommand( const idCmdArgs& args, idPlayer* player ) {
|
|
const char* cmd = args.Argv( 1 );
|
|
|
|
sdCallVote* vote = NULL;
|
|
|
|
for ( int i = 0; i < globalCallVotes.Num(); i++ ) {
|
|
if ( idStr::Icmp( globalCallVotes[ i ]->GetCommandName(), cmd ) != 0 ) {
|
|
continue;
|
|
}
|
|
|
|
vote = globalCallVotes[ i ];
|
|
break;
|
|
}
|
|
|
|
if ( vote == NULL && gameLocal.rules != NULL ) {
|
|
const idList< sdCallVote* >& ruleVotes = gameLocal.rules->GetCallVotes();
|
|
for ( int i = 0; i < ruleVotes.Num(); i++ ) {
|
|
if ( idStr::Icmp( ruleVotes[ i ]->GetCommandName(), cmd ) != 0 ) {
|
|
continue;
|
|
}
|
|
|
|
vote = ruleVotes[ i ];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( vote != NULL ) {
|
|
if ( !CanUseVote( vote, player ) ) {
|
|
return;
|
|
}
|
|
sdPlayerVote* playerVote = vote->Execute( args, player );
|
|
if ( playerVote == NULL ) {
|
|
return;
|
|
}
|
|
player->SetNextCallVoteTime( gameLocal.ToGuiTime( gameLocal.time + MINS2MS( g_voteWait.GetFloat() ) ) );
|
|
playerVote->Start( player );
|
|
if ( player != NULL ) {
|
|
playerVote->Vote( player, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CancelVote
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::CancelVote( voteId_t id, idEntity* object ) {
|
|
while ( sdPlayerVote* vote = FindVote( id, object ) ) {
|
|
FreeVote( vote->GetIndex() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CancelVote
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::CancelVote( sdPlayerVote* vote ) {
|
|
FreeVote( vote->GetIndex() );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CancelFireTeamVotesForPlayer
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::CancelFireTeamVotesForPlayer( idPlayer *player ) {
|
|
CancelVote( VI_FIRETEAM_CREATE, player );
|
|
CancelVote( VI_FIRETEAM_JOIN, player );
|
|
CancelVote( VI_FIRETEAM_REQUEST, player );
|
|
CancelVote( VI_FIRETEAM_PROPOSE, player );
|
|
CancelVote( VI_FIRETEAM_INVITE, player );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::FindVote
|
|
============
|
|
*/
|
|
sdPlayerVote* sdVoteManagerLocal::FindVote( voteId_t id ) {
|
|
for ( sdPlayerVote* vote = activeVotes.Next(); vote; vote = vote->GetNextActiveVote() ) {
|
|
if ( vote->GetVoteId() != id ) {
|
|
continue;
|
|
}
|
|
return vote;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::FindVote
|
|
============
|
|
*/
|
|
sdPlayerVote* sdVoteManagerLocal::FindVote( voteId_t id, idEntity* object ) {
|
|
for ( sdPlayerVote* vote = activeVotes.Next(); vote; vote = vote->GetNextActiveVote() ) {
|
|
if ( !vote->Match( id, object ) ) {
|
|
continue;
|
|
}
|
|
return vote;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CreateCallVoteList
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::CreateCallVoteList( sdUIList* list ) {
|
|
sdUIList::ClearItems( list );
|
|
|
|
sdVoteManagerLocal& manager = sdVoteManager::GetInstance();
|
|
manager.EnumerateCallVotes( list );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CreateCallVoteOptionList
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::CreateCallVoteOptionList( sdUIList* list ) {
|
|
sdUIList::ClearItems( list );
|
|
|
|
int index;
|
|
list->GetUI()->PopScriptVar( index );
|
|
|
|
sdCallVote* vote = sdVoteManager::GetInstance().CallVoteForIndex( index );
|
|
if ( vote == NULL ) {
|
|
return;
|
|
}
|
|
|
|
vote->EnumerateOptions( list );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::EnumerateCallVotes
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::EnumerateCallVotes( sdUIList* list ) {
|
|
idPlayer* localPlayer = gameLocal.GetLocalPlayer();
|
|
if ( localPlayer == NULL ) {
|
|
return;
|
|
}
|
|
|
|
int voteIndex = 0;
|
|
for ( int i = 0; i < globalCallVotes.Num(); i++, voteIndex++ ) {
|
|
if( !globalCallVotes[ i ]->AllowedOnRankedServer() && networkSystem->IsRankedServer() ) {
|
|
continue;
|
|
}
|
|
PushVoteItem( list, globalCallVotes[ i ], voteIndex );
|
|
}
|
|
|
|
if ( gameLocal.rules != NULL ) {
|
|
const idList< sdCallVote* >& ruleVotes = gameLocal.rules->GetCallVotes();
|
|
for ( int i = 0; i < ruleVotes.Num(); i++, voteIndex++ ) {
|
|
if( !globalCallVotes[ i ]->AllowedOnRankedServer() && networkSystem->IsRankedServer() ) {
|
|
continue;
|
|
}
|
|
PushVoteItem( list, ruleVotes[ i ], voteIndex );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::ExecVote
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::ExecVote( sdUserInterfaceLocal* ui ) {
|
|
int voteIndex;
|
|
ui->PopScriptVar( voteIndex );
|
|
|
|
int voteKey;
|
|
ui->PopScriptVar( voteKey );
|
|
|
|
sdCallVote* vote = CallVoteForIndex( voteIndex );
|
|
if ( vote == NULL ) {
|
|
return;
|
|
}
|
|
|
|
vote->Execute( voteKey );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CanUseVote
|
|
============
|
|
*/
|
|
bool sdVoteManagerLocal::CanUseVote( sdCallVote* vote, idPlayer* player ) {
|
|
if ( gameLocal.serverInfoData.votingDisabled ) {
|
|
return false;
|
|
}
|
|
|
|
if ( !vote->AllowedOnRankedServer() ) {
|
|
if ( networkSystem->IsRankedServer() ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if( player == NULL ) {
|
|
return false;
|
|
}
|
|
|
|
const sdUserGroup& group = sdUserGroupManager::GetInstance().GetGroup( player->GetUserGroup() );
|
|
int voteLevel = sdUserGroupManager::GetInstance().GetVoteLevel( vote->GetCommandName() );
|
|
return gameLocal.ToGuiTime( gameLocal.time ) > player->GetNextCallVoteTime() && group.CanCallVote( voteLevel );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::NumActiveVotes
|
|
============
|
|
*/
|
|
int sdVoteManagerLocal::NumActiveVotes( voteId_t id, idEntity* player ) const {
|
|
assert( gameLocal.isServer );
|
|
|
|
int count = 0;
|
|
|
|
sdPlayerVote* next = activeVotes.Next();
|
|
for ( sdPlayerVote* vote = next; vote; vote = next ) {
|
|
next = vote->GetNextActiveVote();
|
|
|
|
if ( vote->GetVoteCaller() == player && vote->GetVoteId() == id ) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::PushVoteItem
|
|
============
|
|
*/
|
|
void sdVoteManagerLocal::PushVoteItem( sdUIList* list, sdCallVote* vote, int voteIndex ) {
|
|
bool canUse = CanUseVote( vote, gameLocal.GetLocalPlayer() );
|
|
if( !canUse ) {
|
|
return;
|
|
}
|
|
|
|
idWStr temp;
|
|
vote->GetText( temp );
|
|
int index = sdUIList::InsertItem( list, temp.c_str(), -1, 0 );
|
|
list->SetItemDataInt( voteIndex, index, 0 );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdVoteManagerLocal::CallVoteForIndex
|
|
============
|
|
*/
|
|
sdCallVote* sdVoteManagerLocal::CallVoteForIndex( int index ) {
|
|
if ( index < 0 ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ( index < globalCallVotes.Num() ) {
|
|
return globalCallVotes[ index ];
|
|
}
|
|
index -= globalCallVotes.Num();
|
|
|
|
if ( gameLocal.rules != NULL ) {
|
|
const idList< sdCallVote* >& ruleVotes = gameLocal.rules->GetCallVotes();
|
|
if ( index < ruleVotes.Num() ) {
|
|
return ruleVotes[ index ];
|
|
}
|
|
index -= ruleVotes.Num();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
sdVoteManagerLocal::Callvote_f
|
|
==================
|
|
*/
|
|
void sdVoteManagerLocal::Callvote_f( const idCmdArgs &args ) {
|
|
if ( gameLocal.isClient ) {
|
|
sdReliableClientMessage msg( GAME_RELIABLE_CMESSAGE_CALLVOTE );
|
|
msg.WriteLong( args.Argc() - 1 );
|
|
for ( int i = 1; i < args.Argc(); i++ ) {
|
|
msg.WriteString( args.Argv( i ) );
|
|
}
|
|
msg.Send();
|
|
return;
|
|
}
|
|
|
|
sdVoteManager::GetInstance().PerformCommand( args, gameLocal.GetLocalPlayer() );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
sdVoteManagerLocal::ListVotes
|
|
==================
|
|
*/
|
|
void sdVoteManagerLocal::ListVotes( void ) {
|
|
int index = 0;
|
|
while ( true ) {
|
|
sdCallVote* vote = CallVoteForIndex( index++ );
|
|
if ( vote == NULL ) {
|
|
break;
|
|
}
|
|
|
|
const char* cmdName = vote->GetCommandName();
|
|
int voteLevel = sdUserGroupManager::GetInstance().GetVoteLevel( cmdName );
|
|
|
|
gameLocal.Printf( "\"%s\"\t\"%d\"\n", cmdName, voteLevel );
|
|
}
|
|
}
|