diff options
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( ); } /* |