diff options
Diffstat (limited to 'src/game/g_main.c')
-rw-r--r-- | src/game/g_main.c | 108 |
1 files changed, 107 insertions, 1 deletions
diff --git a/src/game/g_main.c b/src/game/g_main.c index b2e329a..9316f06 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -284,6 +284,15 @@ vmCvar_t g_scrimMode; vmCvar_t g_revertCooldownTime; +vmCvar_t g_antistack; +vmCvar_t g_antistackBias; +vmCvar_t g_antistackTimeThreshold; +vmCvar_t g_antistackKillThreshold; +vmCvar_t g_antistackBiasThreshold; +vmCvar_t g_antistackHandicapMultiplier; +vmCvar_t g_antistackHandicapOffset; +vmCvar_t g_antistackInterval; + static cvarTable_t gameCvarTable[ ] = { // don't override the cheat state set by the system @@ -555,7 +564,15 @@ static cvarTable_t gameCvarTable[ ] = { &g_schachtmeisterAutobahnThreshold, "g_schachtmeisterAutobahnThreshold", "-30", CVAR_ARCHIVE, 0, qfalse }, { &g_schachtmeisterAutobahnMessage, "g_schachtmeisterAutobahnMessage", "Your host is blacklisted.", CVAR_ARCHIVE, 0, qfalse }, - { &g_revertCooldownTime, "g_revertCooldownTime", "30", CVAR_ARCHIVE, 0, qfalse } + { &g_revertCooldownTime, "g_revertCooldownTime", "30", CVAR_ARCHIVE, 0, qfalse }, + + { &g_antistack, "g_antistack", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackBias, "g_antistackBias", "1", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackTimeThreshold, "g_antistackTimeThreshold", "120", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackKillThreshold, "g_antistackKillThreshold", "10", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackBiasThreshold, "g_antistackBiasThreshold", "2", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackHandicapMultiplier, "g_antistackHandicapMultiplier", "1", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackInterval, "g_antistackInterval", "60", CVAR_ARCHIVE, 0, qfalse }, }; static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); @@ -997,6 +1014,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) level.humanTeamLocked=qtrue; trap_Cvar_Set( "g_lockTeamsAtStart", "0" ); } + + level.antistackNextCheck = g_antistackTimeThreshold.integer * 1000; } /* @@ -2662,6 +2681,90 @@ void CheckExitRules( void ) } } +/* +================= +AntistackHandicap +================= +*/ + +static qboolean AntistackHandicap(void) +{ + qboolean human_bias; + float bias, handicap; + + if (level.alienKills < g_antistackKillThreshold.integer && + level.humanKills < g_antistackKillThreshold.integer) + return qfalse; + + if (level.humanKills > level.alienKills) { + human_bias = qtrue; + bias = (float)level.humanKills / level.alienKills; + } else { + human_bias = qfalse; + bias = (float)level.alienKills / level.humanKills; + } + + bias *= g_antistackBias.value; + + if (bias < g_antistackBiasThreshold.value) + return qfalse; + + handicap = g_antistackHandicapMultiplier.value / (bias - 1.0f + 0.2f); + + if (human_bias) { + level.alienHandicap = 1.0f; + level.humanHandicap = handicap; + } else { + level.alienHandicap = handicap; + level.humanHandicap = 1.0f; + } + + G_LogPrintf("Antistack: %d %d %f %s %f", level.alienKills, level.humanKills, + bias, (human_bias ? "human" : "alien"), handicap); + if (g_antistack.integer > 0) + trap_SendServerCommand(-1, va("print \"^1Teams are uneven. %s income is decreased by %.0f percent.\"", + (human_bias ? "Human" : "Alien"), + (1.0f - handicap) * 100.0f)); + + level.antistackWasHandicapping = qtrue; + return qtrue; +} + +/* +================= +CheckAntistack +================= +*/ +static void CheckAntistack(void) +{ + if (!g_antistack.integer || level.intermissiontime) + return; + + if (level.time < level.antistackNextCheck) + return; + + if (!AntistackHandicap()) { + level.alienHandicap = 1.0f; + level.humanHandicap = 1.0f; + + if (level.antistackWasHandicapping) { + G_LogPrintf("Antistack: %d %d reset\n", + level.alienKills, level.humanKills); + if (g_antistack.integer > 0) + trap_SendServerCommand(-1, "^1Teams are no longer uneven."); + } + + level.antistackWasHandicapping = qfalse; + } + + // Negative g_antistack values cause a dry run and are for debugging. + if (g_antistack.integer < 0) { + level.alienHandicap = 1.0f; + level.humanHandicap = 1.0f; + } + + level.antistackNextCheck = level.time + g_antistackInterval.integer * 1000; +} /* @@ -3502,6 +3605,9 @@ void G_RunFrame( int levelTime ) // update to team status? CheckTeamStatus( ); + // anti-stacking + CheckAntistack( ); + // cancel vote if timed out CheckVote( ); |