1 struct defendservmode : defendstate, servmode
2 {
3     int scoresec;
4     bool hasflaginfo;
5 
defendservmodedefendservmode6     defendservmode() : scoresec(0), hasflaginfo(false) {}
7 
resetdefendservmode8     void reset()
9     {
10         defendstate::reset();
11         scoresec = 0;
12         hasflaginfo = false;
13     }
14 
stealaffinitydefendservmode15     void stealaffinity(int n, int team)
16     {
17         flag &b = flags[n];
18         loopv(clients) if(AA(clients[i]->actortype, abilities)&(1<<A_A_AFFINITY))
19         {
20             server::clientinfo *ci = clients[i];
21             if(ci->state==CS_ALIVE && ci->team && ci->team == team && insideaffinity(b, ci->o))
22                 b.enter(ci->team);
23         }
24         sendaffinity(n);
25     }
26 
moveaffinitydefendservmode27     void moveaffinity(int team, const vec &oldpos, const vec &newpos)
28     {
29         if(!team) return;
30         loopv(flags)
31         {
32             flag &b = flags[i];
33             bool leave = insideaffinity(b, oldpos),
34                  enter = insideaffinity(b, newpos);
35             if(leave && !enter && b.leave(team)) sendaffinity(i);
36             else if(enter && !leave && b.enter(team)) sendaffinity(i);
37             else if(leave && enter && b.steal(team)) stealaffinity(i, team);
38         }
39     }
40 
leaveaffinitydefendservmode41     void leaveaffinity(int team, const vec &o)
42     {
43         moveaffinity(team, o, vec(-1e10f, -1e10f, -1e10f));
44     }
45 
enteraffinitydefendservmode46     void enteraffinity(int team, const vec &o)
47     {
48         moveaffinity(team, vec(-1e10f, -1e10f, -1e10f), o);
49     }
50 
addscoredefendservmode51     void addscore(int i, int team, int points)
52     {
53         if(!points) return;
54         flag &b = flags[i];
55         loopvk(clients) if(AA(clients[k]->actortype, abilities)&(1<<A_A_AFFINITY) && team == clients[k]->team && insideaffinity(b, clients[k]->o)) givepoints(clients[k], points, m_points(gamemode, mutators), false);
56         score &cs = teamscore(team);
57         cs.total += points;
58         sendf(-1, 1, "ri3", N_SCORE, team, cs.total);
59     }
60 
updatedefendservmode61     void update()
62     {
63         int t = (gamemillis/G(defendinterval))-((gamemillis-(curtime+scoresec))/G(defendinterval));
64         if(t < 1) { scoresec += curtime; return; }
65         else scoresec = 0;
66         loopv(flags)
67         {
68             flag &b = flags[i];
69             if(b.enemy)
70             {
71                 if(!b.owners || !b.enemies)
72                 {
73                     int pts = b.occupy(b.enemy, G(defendpoints)*(b.enemies ? b.enemies : -(1+b.owners))*t, defendcount, m_dac_quick(gamemode, mutators));
74                     if(pts > 0) loopvk(clients) if(AA(clients[k]->actortype, abilities)&(1<<A_A_AFFINITY) && b.owner == clients[k]->team && insideaffinity(b, clients[k]->o)) givepoints(clients[k], G(defendpoints), m_points(gamemode, mutators), false);
75                 }
76                 sendaffinity(i);
77             }
78             else if(b.owner)
79             {
80                 if(!m_dac_king(gamemode, mutators) || b.owners)
81                 {
82                     b.points += G(defendpoints)*t;
83                     int score = 0;
84                     while(b.points >= G(defendhold))
85                     {
86                         b.points -= G(defendhold);
87                         score++;
88                     }
89                     if(score) addscore(i, b.owner, score);
90                 }
91                 sendaffinity(i);
92             }
93         }
94     }
95 
96     void sendaffinity(int i, bool interim = false)
97     {
98         flag &b = flags[i];
99         sendf(-1, 1, "ri5", N_INFOAFFIN, i, interim ? -1 : (b.enemy ? b.converted : 0), b.owner, b.enemy);
100     }
101 
sendaffinitydefendservmode102     void sendaffinity()
103     {
104         packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE);
105         initclient(NULL, p, false);
106         sendpacket(-1, 1, p.finalize());
107     }
108 
initclientdefendservmode109     void initclient(clientinfo *ci, packetbuf &p, bool connecting)
110     {
111         if(!hasflaginfo) return;
112         putint(p, N_SETUPAFFIN);
113         putint(p, flags.length());
114         loopv(flags)
115         {
116             flag &b = flags[i];
117             putint(p, b.kinship);
118             putint(p, b.yaw);
119             putint(p, b.pitch);
120             putint(p, b.converted);
121             putint(p, b.owner);
122             putint(p, b.enemy);
123             loopj(3) putint(p, int(b.o[j]*DMF));
124             sendstring(b.name, p);
125         }
126         loopv(clients)
127         {
128             clientinfo *oi = clients[i];
129             if(!oi || !oi->connected || (ci && oi->clientnum == ci->clientnum) || !oi->lastbuff) continue;
130             putint(p, N_SPHY);
131             putint(p, oi->clientnum);
132             putint(p, SPHY_BUFF);
133             putint(p, 1);
134         }
135     }
136 
entergamedefendservmode137     void entergame(clientinfo *ci)
138     {
139         if(!canplay() || !hasflaginfo || ci->state != CS_ALIVE || !(AA(ci->actortype, abilities)&(1<<A_A_AFFINITY))) return;
140         enteraffinity(ci->team, ci->o);
141     }
142 
spawneddefendservmode143     void spawned(clientinfo *ci)
144     {
145         if(!canplay() || !hasflaginfo || !(AA(ci->actortype, abilities)&(1<<A_A_AFFINITY))) return;
146         enteraffinity(ci->team, ci->o);
147     }
148 
149     void leavegame(clientinfo *ci, bool disconnecting = false)
150     {
151         if(!canplay() || !hasflaginfo || ci->state != CS_ALIVE || !(AA(ci->actortype, abilities)&(1<<A_A_AFFINITY))) return;
152         leaveaffinity(ci->team, ci->o);
153     }
154 
dieddefendservmode155     void died(clientinfo *ci, clientinfo *v)
156     {
157         if(!canplay() || !hasflaginfo || !(AA(ci->actortype, abilities)&(1<<A_A_AFFINITY))) return;
158         leaveaffinity(ci->team, ci->o);
159     }
160 
moveddefendservmode161     void moved(clientinfo *ci, const vec &oldpos, const vec &newpos)
162     {
163         if(!canplay() || !hasflaginfo || !(AA(ci->actortype, abilities)&(1<<A_A_AFFINITY)) || ci->state != CS_ALIVE) return;
164         moveaffinity(ci->team, oldpos, newpos);
165     }
166 
regendefendservmode167     void regen(clientinfo *ci, int &total, int &amt, int &delay)
168     {
169         if(!canplay() || !hasflaginfo || !G(defendregenbuff) || !ci->lastbuff) return;
170         if(G(maxhealth)) total = max(m_maxhealth(gamemode, mutators, ci->actortype), total);
171         if(ci->lastregen && G(defendregendelay)) delay = G(defendregendelay);
172         if(G(defendregenextra)) amt += G(defendregenextra);
173     }
174 
checkclientdefendservmode175     void checkclient(clientinfo *ci)
176     {
177         if(!canplay() || !hasflaginfo || ci->state != CS_ALIVE || m_insta(gamemode, mutators)) return;
178         #define defendbuff4 (G(defendbuffing)&4 && b.occupied(m_dac_quick(gamemode, mutators), defendcount) >= G(defendbuffoccupy))
179         #define defendbuff1 (G(defendbuffing)&1 && b.owner == ci->team && (!b.enemy || defendbuff4))
180         #define defendbuff2 (G(defendbuffing)&2 && b.owner == T_NEUTRAL && (b.enemy == ci->team || defendbuff4))
181         if(G(defendbuffing)) loopv(flags)
182         {
183             flag &b = flags[i];
184             if((defendbuff1 || defendbuff2) && (G(defendbuffarea) ? insideaffinity(b, ci->o, G(defendbuffarea)) : true))
185             {
186                 if(!ci->lastbuff) sendf(-1, 1, "ri4", N_SPHY, ci->clientnum, SPHY_BUFF, 1);
187                 ci->lastbuff = gamemillis;
188                 return;
189             }
190         }
191         if(ci->lastbuff && (!G(defendbuffing) || gamemillis-ci->lastbuff >= G(defendbuffdelay)))
192         {
193             ci->lastbuff = 0;
194             sendf(-1, 1, "ri4", N_SPHY, ci->clientnum, SPHY_BUFF, 0);
195         }
196     }
197 
parseaffinitydefendservmode198     void parseaffinity(ucharbuf &p)
199     {
200         int numflags = getint(p);
201         if(numflags)
202         {
203             loopi(numflags)
204             {
205                 int kin = getint(p), yaw = getint(p), pitch = getint(p);
206                 vec o;
207                 loopj(3) o[j] = getint(p)/DMF;
208                 string name;
209                 getstring(name, p);
210                 if(p.overread()) break;
211                 if(!hasflaginfo && i < MAXPARAMS) addaffinity(o, kin, yaw, pitch, name);
212             }
213             if(!hasflaginfo)
214             {
215                 hasflaginfo = true;
216                 sendaffinity();
217                 loopv(clients) if(clients[i]->state == CS_ALIVE) entergame(clients[i]);
218             }
219         }
220     }
221 
pointsdefendservmode222     int points(clientinfo *m, clientinfo *v)
223     {
224         bool isteam = m==v || m->team == v->team;
225         int p = isteam ? -1 : 1, q = p;
226         loopv(flags) if(insideaffinity(flags[i], m->o)) p += q;
227         return p;
228     }
229 
balancedefendservmode230     void balance(int oldbalance)
231     {
232         static vector<int> owners[T_TOTAL], enemies[T_TOTAL], modified;
233         loopk(T_TOTAL)
234         {
235             owners[k].setsize(0);
236             enemies[k].setsize(0);
237         }
238         modified.setsize(0);
239         loopv(flags)
240         {
241             if(isteam(gamemode, mutators, flags[i].owner, T_FIRST))
242                 owners[flags[i].owner-T_FIRST].add(i);
243             if(isteam(gamemode, mutators, flags[i].enemy, T_FIRST))
244                 enemies[flags[i].enemy-T_FIRST].add(i);
245         }
246         loopk(numteams(gamemode, mutators))
247         {
248             int from = mapbals[oldbalance][k], fromt = from-T_FIRST, to = mapbals[curbalance][k];
249             loopv(owners[fromt])
250             {
251                 flags[owners[fromt][i]].owner = to;
252                 if(modified.find(owners[fromt][i]) < 0) modified.add(owners[fromt][i]);
253             }
254             loopv(enemies[fromt])
255             {
256                 flags[enemies[fromt][i]].enemy = to;
257                 if(modified.find(enemies[fromt][i]) < 0) modified.add(enemies[fromt][i]);
258             }
259         }
260         loopv(modified) sendaffinity(modified[i], true);
261     }
262 } defendmode;
263