From eb8c819eed3506deae8990a9c9841cc3679ea164 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Thu, 15 Nov 2018 00:29:14 +0100 Subject: Redo handicapping to include unbalanced teams. --- src/game/g_main.c | 193 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 113 insertions(+), 80 deletions(-) (limited to 'src/game/g_main.c') diff --git a/src/game/g_main.c b/src/game/g_main.c index d5f88ff..0d31c43 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -285,13 +285,16 @@ 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; +vmCvar_t g_antistackPlayerThreshold; +vmCvar_t g_antistackScoreThreshold; +vmCvar_t g_antistackTeamBiasThreshold; +vmCvar_t g_antistackTeamBiasFactor; +vmCvar_t g_antistackScoreBias; +vmCvar_t g_antistackScoreBiasThreshold; +vmCvar_t g_antistackScoreBiasFactor; +vmCvar_t g_antistackBiasThreshold; static cvarTable_t gameCvarTable[ ] = { @@ -567,12 +570,17 @@ static cvarTable_t gameCvarTable[ ] = { &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 }, + { &g_antistackPlayerThreshold, "g_antistackPlayerThreshold", "7", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackScoreThreshold, "g_antistackScoreThreshold", "15", CVAR_ARCHIVE, 0, qfalse }, + + { &g_antistackTeamBiasThreshold, "g_antistackTeamBiasThreshold", "2", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackTeamBiasFactor, "g_antistackTeamBiasFactor", "0.69314718", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackScoreBias, "g_antistackScoreBias", "1", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackScoreBiasThreshold, "g_antistackScoreBiasThreshold", "0.69314718", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackScoreBiasFactor, "g_antistackScoreBiasFactor", " 0.69314718", CVAR_ARCHIVE, 0, qfalse }, + { &g_antistackBiasThreshold, "g_antistackBiasThreshold", "0.1053605", CVAR_ARCHIVE, 0, qfalse }, }; static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); @@ -2685,19 +2693,45 @@ void CheckExitRules( void ) /* ================= -AntistackHandicap +CheckAntistack ================= */ -static void AntistackHandicap(void) +static float AntistackTeamBias(int aliens, int humans) +{ + if (abs(aliens - humans) < g_antistackTeamBiasThreshold.integer) + return 0.0f; + + return (aliens - humans) * g_antistackTeamBiasFactor.value; +} + +static float AntistackScoreBias(int alien_score, int human_score) { - int i, alienKills = 0, humanKills = 0; - qboolean human_bias; - float bias, handicap; + float bias; + + bias = log(alien_score / human_score * g_antistackScoreBias.value); + if (fabsf(bias) < g_antistackScoreBiasThreshold.value) + return 0.0f; - for (i = 0; i < level.maxclients; i++) { + return bias * g_antistackScoreBiasFactor.value; +} + +static void CheckAntistack(void) +{ + int aliens = 0, humans = 0, alien_score = 0, human_score = 0, + handicap_team = PTE_NONE; + const char *log_notice = ""; + float teambias = 0.0f, scorebias = 0.0f, bias, handicap = 0.0f; + + if (!g_antistack.integer || level.intermissiontime) + return; + + if (level.time < level.antistackNextCheck) + return; + + for (int i = 0; i < level.maxclients; i++) { gclient_t *client = level.clients + i; - int kills; + int score; if (client->pers.connected != CON_CONNECTED) continue; @@ -2705,87 +2739,86 @@ static void AntistackHandicap(void) if (client->ps.stats[STAT_PTEAM] == PTE_NONE) continue; - kills = client->ps.persistant[PERS_SCORE]; - if (kills < 0) - kills = 0; - - if (client->ps.stats[STAT_PTEAM] == PTE_ALIENS) - alienKills += kills; - else - humanKills += kills; + score = client->ps.persistant[PERS_SCORE]; + if (score < 0) + score = 0; + + if (client->ps.stats[STAT_PTEAM] == PTE_ALIENS) { + alien_score += score; + aliens++; + } else { + human_score += score; + humans++; + } } - if (alienKills < g_antistackKillThreshold.integer && - humanKills < g_antistackKillThreshold.integer) - goto no_handicap; + if (aliens + humans < g_antistackPlayerThreshold.integer) { + log_notice = " (too few players)"; + bias = 0.0f; + goto out; + } - if (humanKills > alienKills) { - human_bias = qtrue; - bias = (float)humanKills / alienKills; - } else { - human_bias = qfalse; - bias = (float)alienKills / humanKills; + if (alien_score < g_antistackScoreThreshold.integer && + human_score < g_antistackScoreThreshold.integer) { + log_notice = " (too little score)"; + bias = 0.0f; + goto out; } - bias *= g_antistackBias.value; + teambias = AntistackTeamBias(aliens, humans); + scorebias = AntistackScoreBias(alien_score, human_score); + bias = teambias + scorebias; - if (bias < g_antistackBiasThreshold.value) - goto no_handicap; + if (fabs(bias) < g_antistackBiasThreshold.value) { + log_notice = " (too little bias)"; + bias = 0.0f; - handicap = g_antistackHandicapMultiplier.value / (bias - 1.0f + 0.2f); + if (level.antistackWasHandicapping) { + if (g_antistack.integer > 0) + trap_SendServerCommand(-1, "print \"^1Teams are no longer uneven.\n\""); + else + G_LogPrintf("Antistack test message: Teams are no longer uneven."); + } - if (human_bias) { + level.alienHandicap = 0.0f; + level.humanHandicap = 0.0f; + goto out; + } + + // Negative g_antistack values cause a dry run and are for debugging. + if (g_antistack.integer < 0) { level.alienHandicap = 1.0f; - level.humanHandicap = handicap; - } else { - level.alienHandicap = handicap; level.humanHandicap = 1.0f; + goto out; } - G_LogPrintf("Antistack: %d %d %f %s %f\n", alienKills, 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.\n\"", - (human_bias ? "Human" : "Alien"), - (1.0f - handicap) * 100.0f)); - level.antistackWasHandicapping = qtrue; - return; - -no_handicap: - level.alienHandicap = 1.0f; - level.humanHandicap = 1.0f; - - G_LogPrintf("Antistack: %d %d n/a\n", - alienKills, humanKills); - if (level.antistackWasHandicapping && g_antistack.integer > 0) - trap_SendServerCommand(-1, "print \"^1Teams are no longer uneven.\n\""); - - level.antistackWasHandicapping = qfalse; -} - -/* -================= -CheckAntistack -================= -*/ -static void CheckAntistack(void) -{ - if (!g_antistack.integer || level.intermissiontime) - return; - - if (level.time < level.antistackNextCheck) - return; - - AntistackHandicap(); - - // Negative g_antistack values cause a dry run and are for debugging. - if (g_antistack.integer < 0) { - level.alienHandicap = 1.0f; + if (bias < 0.0f) { + handicap_team = PTE_ALIENS; + handicap = exp(bias); + level.alienHandicap = handicap; level.humanHandicap = 1.0f; + } else { + handicap_team = PTE_HUMANS; + handicap = exp(-bias); + level.alienHandicap = 1.0f; + level.humanHandicap = handicap; } + if (g_antistack.integer > 0) + trap_SendServerCommand(-1, va("print \"^1Teams are uneven. %s income is reduced by %.0f percent.\n\"", + (handicap_team == PTE_ALIENS ? "Alien" : "Human"), + (1.0f - handicap) * 100.0f)); + else + G_LogPrintf("Antistack test message: Teams are uneven. %s income is reduced by %.0f percent.\n", + (handicap_team == PTE_ALIENS ? "Alien" : "Human"), + (1.0f - handicap) * 100.0f); + +out: + G_LogPrintf("Antistack: %dv%d %d:%d %f %f %f %i %f%s\n", + aliens, humans, alien_score, human_score, teambias, + scorebias, bias, handicap_team, handicap, log_notice); level.antistackNextCheck = level.time + g_antistackInterval.integer * 1000; } -- cgit