-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathserverbotbalanceearly.patch
116 lines (109 loc) · 4.21 KB
/
serverbotbalanceearly.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
diff --git src/fpsgame/aiman.h src/fpsgame/aiman.h
index a36118c..897aefd 100644
--- src/fpsgame/aiman.h
+++ src/fpsgame/aiman.h
@@ -4,14 +4,15 @@ namespace aiman
bool dorefresh = false, botbalance = true;
VARN(serverbotlimit, botlimit, 0, 8, MAXBOTS);
VAR(serverbotbalance, 0, 1, 1);
+ MOD(VARF, serverbotbalanceearly, 0, 0, 1, { dorefresh = true; });
- void calcteams(vector<teamscore> &teams)
+ void calcteams(vector<teamscore> &teams, bool includebots)
{
static const char * const defaults[2] = { "good", "evil" };
loopv(clients)
{
clientinfo *ci = clients[i];
- if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue;
+ if(ci->state.state==CS_SPECTATOR || !ci->team[0] || (!includebots && ci->state.aitype!=AI_NONE)) continue;
teamscore *t = NULL;
loopvj(teams) if(!strcmp(teams[j].team, ci->team)) { t = &teams[j]; break; }
if(t) t->score++;
@@ -24,12 +25,32 @@ namespace aiman
}
}
+ clientinfo *addai(int skill, int limit);
+ void deleteai(clientinfo *ci);
+
void balanceteams()
{
vector<teamscore> teams;
- calcteams(teams);
+ calcteams(teams, false); // don't count bots yet
vector<clientinfo *> reassign;
loopv(bots) if(bots[i]) reassign.add(bots[i]);
+ if(serverbotbalanceearly)
+ {
+ int botsneeded = 0;
+ loopi(teams.length()-1) botsneeded += teams[0].score - teams[i+1].score;
+ if(botsneeded > reassign.length())
+ {
+ loopi(teams.length()-1) loopj(teams[i].score - teams[i+1].score)
+ {
+ clientinfo *bot = addai(-1, -1);
+ if(bot) reassign.add(bot);
+ }
+ }
+ else loopi(reassign.length() - botsneeded) deleteai(reassign.pop());
+ }
+ // add bots to team 'score' now
+ loopv(reassign) loopvj(teams) if(!strcmp(reassign[i]->team, teams[j].team)) { teams[j].score++; break; }
+ teams.sort(teamscore::compare);
while(reassign.length() && teams.length() && teams[0].score > teams.last().score + 1)
{
teamscore &t = teams.last();
@@ -59,7 +80,7 @@ namespace aiman
const char *chooseteam()
{
vector<teamscore> teams;
- calcteams(teams);
+ calcteams(teams, true);
return teams.length() ? teams.last().team : "";
}
@@ -80,7 +101,7 @@ namespace aiman
return least;
}
- bool addai(int skill, int limit)
+ clientinfo *addai(int skill, int limit)
{
int numai = 0, cn = -1, maxai = limit >= 0 ? min(limit, MAXBOTS) : MAXBOTS;
loopv(bots)
@@ -89,7 +110,7 @@ namespace aiman
if(!ci || ci->ownernum < 0) { if(cn < 0) cn = i; continue; }
numai++;
}
- if(numai >= maxai) return false;
+ if(numai >= maxai) return NULL;
if(bots.inrange(cn))
{
clientinfo *ci = bots[cn];
@@ -101,7 +122,7 @@ namespace aiman
if(owner) owner->bots.add(ci);
ci->aireinit = 2;
dorefresh = true;
- return true;
+ return owner ? ci : NULL;
}
}
else { cn = bots.length(); bots.add(NULL); }
@@ -123,7 +144,7 @@ namespace aiman
ci->aireinit = 2;
ci->connected = true;
dorefresh = true;
- return true;
+ return owner ? ci : NULL;
}
void deleteai(clientinfo *ci)
@@ -229,12 +250,14 @@ namespace aiman
void reqadd(clientinfo *ci, int skill)
{
if(!ci->local && !ci->privilege) return;
+ if(serverbotbalanceearly) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "bots are managed by the server (serverbotbalanceearly = 1)"); return; }
if(!addai(skill, !ci->local && ci->privilege < PRIV_ADMIN ? botlimit : -1)) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to create or assign bot");
}
void reqdel(clientinfo *ci)
{
if(!ci->local && !ci->privilege) return;
+ if(serverbotbalanceearly) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "bots are managed by the server (serverbotbalanceearly = 1)"); return; }
if(!deleteai()) sendf(ci->clientnum, 1, "ris", N_SERVMSG, "failed to remove any bots");
}