summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/g_cmds.c44
-rw-r--r--src/game/g_local.h6
-rw-r--r--src/game/g_main.c115
3 files changed, 145 insertions, 20 deletions
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index befed91d..2a95ffa5 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -1035,6 +1035,8 @@ void Cmd_CallVote_f( gentity_t *ent )
trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) );
}
+ level.votePassThreshold = 50;
+
// detect clientNum for partial name match votes
if( !Q_stricmp( arg1, "kick" ) ||
!Q_stricmp( arg1, "mute" ) ||
@@ -1154,14 +1156,54 @@ void Cmd_CallVote_f( gentity_t *ent )
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ),
"End match in a draw" );
}
+ else if( !Q_stricmp( arg1, "sudden_death" ) ||
+ !Q_stricmp( arg1, "suddendeath" ) )
+ {
+ if(!g_suddenDeathVotePercent.integer)
+ {
+ trap_SendServerCommand( ent-g_entities,
+ "print \"Sudden Death votes have been disabled\n\"" );
+ return;
+ }
+ else if( g_suddenDeath.integer )
+ {
+ trap_SendServerCommand( ent - g_entities,
+ va( "print \"callvote: Sudden Death has already begun\n\"") );
+ return;
+ }
+ else if( G_TimeTilSuddenDeath() <= g_suddenDeathVoteDelay.integer * 1000 )
+ {
+ trap_SendServerCommand( ent - g_entities,
+ va( "print \"callvote: Sudden Death is already immenent\n\"") );
+ return;
+ }
+ else
+ {
+ level.votePassThreshold = g_suddenDeathVotePercent.integer;
+ Com_sprintf( level.voteString, sizeof( level.voteString ), "suddendeath" );
+ Com_sprintf( level.voteDisplayString,
+ sizeof( level.voteDisplayString ), "Begin sudden death" );
+
+ if( g_suddenDeathVoteDelay.integer )
+ Q_strcat( level.voteDisplayString, sizeof( level.voteDisplayString ),
+ va( " in %d seconds", g_suddenDeathVoteDelay.integer ) );
+
+ }
+ }
else
{
trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" );
trap_SendServerCommand( ent-g_entities, "print \"Valid vote commands are: "
- "map, map_restart, draw, kick, mute and unmute\n" );
+ "map, map_restart, sudden_death, draw, kick, mute and unmute\n" );
return;
}
+ if( level.votePassThreshold != 50 )
+ {
+ Q_strcat( level.voteDisplayString, sizeof( level.voteDisplayString ),
+ va( " (Needs > %d percent)", level.votePassThreshold ) );
+ }
+
trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE
" called a vote\n\"", ent->client->pers.netname ) );
G_Printf( "'%s' called a vote for '%s'\n", ent->client->pers.netname,
diff --git a/src/game/g_local.h b/src/game/g_local.h
index d74982c5..c6f0e876 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -537,6 +537,7 @@ typedef struct
char voteString[MAX_STRING_CHARS];
char voteDisplayString[MAX_STRING_CHARS];
int voteTime; // level.time vote was called
+ int votePassThreshold; // need at least this percent to pass
int voteExecuteTime; // time the vote is executed
int voteYes;
int voteNo;
@@ -608,6 +609,8 @@ typedef struct
team_t lastWin;
+ qboolean suddenDeath;
+ int suddenDeathBeginTime;
timeWarning_t suddenDeathWarning;
timeWarning_t timelimitWarning;
@@ -1088,6 +1091,7 @@ extern vmCvar_t g_maxNameChanges;
extern vmCvar_t g_timelimit;
extern vmCvar_t g_suddenDeathTime;
+extern vmCvar_t g_suddenDeath;
extern vmCvar_t g_friendlyFire;
extern vmCvar_t g_friendlyFireHumans;
extern vmCvar_t g_friendlyFireAliens;
@@ -1111,6 +1115,8 @@ extern vmCvar_t g_doWarmup;
extern vmCvar_t g_blood;
extern vmCvar_t g_allowVote;
extern vmCvar_t g_voteLimit;
+extern vmCvar_t g_suddenDeathVotePercent;
+extern vmCvar_t g_suddenDeathVoteDelay;
extern vmCvar_t g_teamAutoJoin;
extern vmCvar_t g_teamForceBalance;
extern vmCvar_t g_banIPs;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 6928973b..51899e0d 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -41,6 +41,7 @@ gclient_t g_clients[ MAX_CLIENTS ];
vmCvar_t g_fraglimit;
vmCvar_t g_timelimit;
vmCvar_t g_suddenDeathTime;
+vmCvar_t g_suddenDeath;
vmCvar_t g_capturelimit;
vmCvar_t g_friendlyFire;
vmCvar_t g_friendlyFireAliens;
@@ -74,6 +75,8 @@ vmCvar_t g_podiumDist;
vmCvar_t g_podiumDrop;
vmCvar_t g_allowVote;
vmCvar_t g_voteLimit;
+vmCvar_t g_suddenDeathVotePercent;
+vmCvar_t g_suddenDeathVoteDelay;
vmCvar_t g_teamAutoJoin;
vmCvar_t g_teamForceBalance;
vmCvar_t g_banIPs;
@@ -166,6 +169,7 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_suddenDeathTime, "g_suddenDeathTime", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
+ { &g_suddenDeath, "g_suddenDeath", "0", CVAR_SERVERINFO | CVAR_NORESTART, 0, qtrue },
{ &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse },
@@ -209,6 +213,8 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_allowVote, "g_allowVote", "1", CVAR_ARCHIVE, 0, qfalse },
{ &g_voteLimit, "g_voteLimit", "5", CVAR_ARCHIVE, 0, qfalse },
+ { &g_suddenDeathVotePercent, "g_suddenDeathVotePercent", "74", CVAR_ARCHIVE, 0, qfalse },
+ { &g_suddenDeathVoteDelay, "g_suddenDeathVoteDelay", "180", CVAR_ARCHIVE, 0, qfalse },
{ &g_listEntity, "g_listEntity", "0", 0, 0, qfalse },
{ &g_minCommandPeriod, "g_minCommandPeriod", "500", 0, 0, qfalse},
{ &g_minNameChangePeriod, "g_minNameChangePeriod", "5", 0, 0, qfalse},
@@ -637,6 +643,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
trap_Cvar_Set( "g_humanStage", va( "%d", S1 ) );
trap_Cvar_Set( "g_alienCredits", 0 );
trap_Cvar_Set( "g_humanCredits", 0 );
+ trap_Cvar_Set( "g_suddenDeath", 0 );
+ level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
G_Printf( "-----------------------------------\n" );
@@ -1045,11 +1053,11 @@ G_TimeTilSuddenDeath
*/
int G_TimeTilSuddenDeath( void )
{
- if( !g_suddenDeathTime.integer )
+ if( ( !g_suddenDeathTime.integer && level.suddenDeathBeginTime==0 ) ||
+ ( level.suddenDeathBeginTime < 0 ) )
return 1; // Always some time away
- return ( g_suddenDeathTime.integer * 60000 ) -
- ( level.time - level.startTime );
+ return ( ( level.suddenDeathBeginTime ) - ( level.time - level.startTime ) );
}
@@ -1070,6 +1078,7 @@ void G_CalculateBuildPoints( void )
int localHTP = level.humanBuildPoints = g_humanBuildPoints.integer,
localATP = level.alienBuildPoints = g_alienBuildPoints.integer;
+ // BP queue updates
while( level.alienBuildPointQueue > 0 &&
level.alienNextQueueTime < level.time )
{
@@ -1084,35 +1093,63 @@ void G_CalculateBuildPoints( void )
level.humanNextQueueTime += g_alienBuildQueueTime.integer;
}
- if( g_suddenDeathTime.integer && !level.warmupTime )
+ // Sudden Death checks
+
+ // Note: g_suddenDeath sets what is going on and level.suddenDeath
+ // trails it to run stuff here. They're only inconsistent for as long
+ // as it takes this function to run once and update
+
+ // reset if SD was on, but now it's off
+ if( !g_suddenDeath.integer && level.suddenDeath )
+ {
+ level.suddenDeath = qfalse;
+ level.suddenDeathWarning = 0;
+ level.suddenDeathBeginTime = -1;
+ if( ( level.time - level.startTime ) < ( g_suddenDeathTime.integer * 60000 ) )
+ level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
+ else
+ level.suddenDeathBeginTime = -1;
+ }
+
+ // SD checks and warnings
+ if( !level.suddenDeath )
{
- if( G_TimeTilSuddenDeath( ) <= 0 )
+ // check conditions to enter sudden death
+ if( !level.warmupTime &&
+ ( g_suddenDeath.integer || G_TimeTilSuddenDeath( ) <= 0 ) )
{
+ // begin sudden death
localHTP = 0;
localATP = 0;
- //warn about sudden death
if( level.suddenDeathWarning < TW_PASSED )
{
+ G_LogPrintf( "Beginning Sudden Death\n" );
trap_SendServerCommand( -1, "cp \"Sudden Death!\"" );
+
+ level.suddenDeathBeginTime = level.time;
+ level.suddenDeath=qtrue;
+ trap_Cvar_Set( "g_suddenDeath", "1" );
+
level.suddenDeathWarning = TW_PASSED;
}
}
else
{
- //warn about sudden death
+ // warn about sudden death
if( G_TimeTilSuddenDeath( ) <= 60000 &&
level.suddenDeathWarning < TW_IMMINENT )
{
- trap_SendServerCommand( -1, "cp \"Sudden Death in 1 minute!\"" );
+ trap_SendServerCommand( -1, va( "cp \"Sudden Death in %d seconds!\"",
+ (int)(G_TimeTilSuddenDeath() / 1000 ) ) );
level.suddenDeathWarning = TW_IMMINENT;
}
}
}
- else
+ else // it is SD already
{
- localHTP = g_humanBuildPoints.integer;
- localATP = g_alienBuildPoints.integer;
+ localHTP = 0;
+ localATP = 0;
}
level.humanBuildPoints = localHTP - level.humanBuildPointQueue;
@@ -2119,6 +2156,9 @@ CheckVote
*/
void CheckVote( void )
{
+ int votePassThreshold = level.votePassThreshold;
+ int voteYesPercent;
+
if( level.voteExecuteTime && level.voteExecuteTime < level.time )
{
level.voteExecuteTime = 0;
@@ -2129,37 +2169,63 @@ void CheckVote( void )
{
level.restarted = qtrue;
}
+
+ if( !Q_stricmp( level.voteString, "suddendeath" ) )
+ {
+ level.suddenDeathBeginTime = level.time +
+ ( 1000 * g_suddenDeathVoteDelay.integer ) - level.startTime;
+ level.voteString[0] = '\0';
+
+ if( g_suddenDeathVoteDelay.integer )
+ trap_SendServerCommand( -1, va("cp \"Sudden Death will begin in %d seconds\n\"", g_suddenDeathVoteDelay.integer ) );
+ }
}
if( !level.voteTime )
return;
- if( level.time - level.voteTime >= VOTE_TIME )
+ if( level.voteYes + level.voteNo > 0 )
+ voteYesPercent = (int)( 100 * ( level.voteYes ) / ( level.voteYes + level.voteNo ) );
+ else
+ voteYesPercent = 0;
+
+ if( ( level.time - level.voteTime >= VOTE_TIME ) ||
+ ( level.voteYes + level.voteNo == level.numConnectedClients ) )
{
- if( level.voteYes > level.voteNo )
+ if( voteYesPercent> votePassThreshold || level.voteNo == 0 )
{
// execute the command, then remove the vote
- trap_SendServerCommand( -1, "print \"Vote passed\n\"" );
+ trap_SendServerCommand( -1, va("print \"Vote passed (%d - %d)\n\"",
+ level.voteYes, level.voteNo ) );
+ G_LogPrintf( "Vote: Vote passed (%d-%d)\n", level.voteYes, level.voteNo );
level.voteExecuteTime = level.time + 3000;
}
else
{
// same behavior as a timeout
- trap_SendServerCommand( -1, "print \"Vote failed\n\"" );
+ trap_SendServerCommand( -1, va("print \"Vote failed (%d - %d)\n\"",
+ level.voteYes, level.voteNo ) );
+ G_LogPrintf( "Vote: Vote failed (%d - %d)\n", level.voteYes, level.voteNo );
}
}
else
{
- if( level.voteYes > level.numVotingClients / 2 )
+ if( level.voteYes > (int)( (double) level.numConnectedClients *
+ ( (double) votePassThreshold/100.0 ) ) )
{
// execute the command, then remove the vote
- trap_SendServerCommand( -1, "print \"Vote passed\n\"" );
+ trap_SendServerCommand( -1, va("print \"Vote passed (%d - %d)\n\"",
+ level.voteYes, level.voteNo ) );
+ G_LogPrintf( "Vote: Vote passed (%d - %d)\n", level.voteYes, level.voteNo );
level.voteExecuteTime = level.time + 3000;
}
- else if( level.voteNo >= ceil( (float)level.numVotingClients / 2 ) )
+ else if( level.voteNo > (int)( (double) level.numConnectedClients *
+ ( (double) ( 100.0-votePassThreshold )/ 100.0 ) ) )
{
// same behavior as a timeout
- trap_SendServerCommand( -1, "print \"Vote failed\n\"" );
+ trap_SendServerCommand( -1, va("print \"Vote failed (%d - %d)\n\"",
+ level.voteYes, level.voteNo ) );
+ G_LogPrintf("Vote failed\n");
}
else
{
@@ -2230,6 +2296,7 @@ void CheckCvars( void )
{
static int lastPasswordModCount = -1;
static int lastMarkDeconModCount = -1;
+ static int lastSDTimeModCount = -1;
if( g_password.modificationCount != lastPasswordModCount )
{
@@ -2261,6 +2328,16 @@ void CheckCvars( void )
ent->deconstruct = qfalse;
}
}
+
+ // If we change g_suddenDeathTime during a map, we need to update
+ // when sd will begin
+ if( g_suddenDeathTime.modificationCount != lastSDTimeModCount )
+ {
+ lastSDTimeModCount = g_suddenDeathTime.modificationCount;
+ level.suddenDeathBeginTime = g_suddenDeathTime.integer * 60000;
+ }
+
+ level.frameMsec = trap_Milliseconds( );
}
/*