summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2018-11-15 00:29:14 +0100
committerPaweł Redman <pawel.redman@gmail.com>2019-02-10 14:47:47 +0100
commita9346f74b2349ea1bd5d9506467f04da532c2646 (patch)
treeb6e1b3ac9b23b60b6dfb19f8908759998b191e61 /src
parent5db2c76bec75a3c1058ebecca64d5dea8ec5448e (diff)
Redo handicapping to include unbalanced teams.
Diffstat (limited to 'src')
-rw-r--r--src/game/g_local.h13
-rw-r--r--src/game/g_main.c193
2 files changed, 121 insertions, 85 deletions
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 342494d..d7c3860 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -1582,13 +1582,16 @@ extern vmCvar_t g_scrimMode;
extern vmCvar_t g_revertCooldownTime;
extern vmCvar_t g_antistack;
-extern vmCvar_t g_antistackBias;
extern vmCvar_t g_antistackTimeThreshold;
-extern vmCvar_t g_antistackKillThreshold;
-extern vmCvar_t g_antistackBiasThreshold;
-extern vmCvar_t g_antistackHandicapMultiplier;
-extern vmCvar_t g_antistackHandicapOffset;
extern vmCvar_t g_antistackInterval;
+extern vmCvar_t g_antistackPlayerThreshold;
+extern vmCvar_t g_antistackScoreThreshold;
+extern vmCvar_t g_antistackTeamBiasThreshold;
+extern vmCvar_t g_antistackTeamBiasFactor;
+extern vmCvar_t g_antistackScoreBias;
+extern vmCvar_t g_antistackScoreBiasThreshold;
+extern vmCvar_t g_antistackScoreBiasFactor;
+extern vmCvar_t g_antistackBiasThreshold;
void trap_Printf( const char *fmt );
void trap_Error( const char *fmt );
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;
}