diff options
author | Christopher Schwarz <lakitu7@gmail.com> | 2009-10-03 12:23:06 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:15:54 +0000 |
commit | df5c979a32fb978180f6793ebec42999748a146b (patch) | |
tree | 18b51a771e5a84f6e685b83494d5df3614698c22 /src | |
parent | 28caf713669a0608c15604fec2d084420fac4d4a (diff) |
* Add SD votes (closes #11)
* Add g_suddenDeath that can be changed back and forth (0 | 1) by console whenever. This is necessary to create the vote type.
* Votes require at least g_suddenDeathVotePercent percent to pass (default 74)
* Set g_suddenDeathVotePercent 0 to disable SD votes entirely
* g_suddenDeathVoteDelay (default 180) controls how much delay should occur between the vote's passing and entering SD. This is designed to make it harder to pass SD votes at opportune times.
Diffstat (limited to 'src')
-rw-r--r-- | src/game/g_cmds.c | 44 | ||||
-rw-r--r-- | src/game/g_local.h | 6 | ||||
-rw-r--r-- | src/game/g_main.c | 115 |
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( ); } /* |