is_lagging(client * cl)1 inline bool is_lagging(client *cl)
2 {
3     return ( cl->spj > 50 || cl->ping > 500 || cl->ldt > 80 ); // do not change this except if you really know what are you doing
4 }
5 
outside_border(vec & po)6 inline bool outside_border(vec &po)
7 {
8     return (po.x < 0 || po.y < 0 || po.x >= maplayoutssize || po.y >= maplayoutssize);
9 }
10 
checkclientpos(client * cl)11 inline void checkclientpos(client *cl)
12 {
13     vec &po = cl->state.o;
14     if( outside_border(po) || maplayout[((int) po.x) + (((int) po.y) << maplayout_factor)] > po.z + 3)
15     {
16         if(gamemillis > 10000 && (servmillis - cl->connectmillis) > 10000) cl->mapcollisions++;
17         if(cl->mapcollisions && !(cl->mapcollisions % 25))
18         {
19             logline(ACLOG_INFO, "[%s] %s is colliding with the map", cl->hostname, cl->name);
20         }
21     }
22 }
23 
24 #define POW2XY(A,B) (pow2(A.x-B.x)+pow2(A.y-B.y))
25 
26 extern inline void addban(client *cl, int reason, int type = BAN_AUTO);
27 
28 #ifdef ACAC
29 #include "anticheat.h"
30 #endif
31 
32 #define MINELINE 50
33 
34 //FIXME
35 /* There are smarter ways to implement this function, but most probably they will be very complex */
getmaxarea(int inversed_x,int inversed_y,int transposed,int ml_factor,char * ml)36 int getmaxarea(int inversed_x, int inversed_y, int transposed, int ml_factor, char *ml)
37 {
38     int ls = (1 << ml_factor);
39     int xi = 0, oxi = 0, xf = 0, oxf = 0, fx = 0, fy = 0;
40     int area = 0, maxarea = 0;
41     bool sav_x = false, sav_y = false;
42 
43     if (transposed) fx = ml_factor;
44     else fy = ml_factor;
45 
46     // walk on x for each y
47     for ( int y = (inversed_y ? ls-1 : 0); (inversed_y ? y >= 0 : y < ls); (inversed_y ? y-- : y++) ) {
48 
49     /* Analyzing each cube of the line */
50         for ( int x = (inversed_x ? ls-1 : 0); (inversed_x ? x >= 0 : x < ls); (inversed_x ? x-- : x++) ) {
51             if ( ml[ ( x << fx ) + ( y << fy ) ] != 127 ) {      // if it is not solid
52                 if ( sav_x ) {                                          // if the last cube was saved
53                     xf = x;                                             // new end for this line
54                 }
55                 else {
56                     xi = x;                                             // new begin of the line
57                     sav_x = true;                                       // accumulating cubes from now
58                 }
59             } else {                                    // solid
60                 if ( xf - xi > MINELINE ) break;                        // if the empty line is greater than a minimum, get out
61                 sav_x = false;                                          // stop the accumulation of cubes
62             }
63         }
64 
65     /* Analyzing this line with the previous one */
66         if ( xf - xi > MINELINE ) {                                     // if the line has the minimun threshold of emptiness
67             if ( sav_y ) {                                              // if the last line was saved
68                 if ( 2*oxi + MINELINE < 2*xf &&
69                      2*xi + MINELINE < 2*oxf ) {                        // if the last line intersect this one
70                     area += xf - xi;
71                 } else {
72                     oxi = xi;                                           // new area vertices
73                     oxf = xf;
74                 }
75             }
76             else {
77                 oxi = xi;
78                 oxf = xf;
79                 sav_y = true;                                           // accumulating lines from now
80             }
81         } else {
82             sav_y = false;                                              // stop the accumulation of lines
83             if (area > maxarea) maxarea = area;                         // new max area
84             area=0;
85         }
86 
87         sav_x = false;                                                  // reset x
88         xi = xf = 0;
89     }
90     return maxarea;
91 }
92 
checkarea(int maplayout_factor,char * maplayout)93 int checkarea(int maplayout_factor, char *maplayout)
94 {
95     int area = 0, maxarea = 0;
96     for (int i=0; i < 8; i++) {
97         area = getmaxarea((i & 1),(i & 2),(i & 4), maplayout_factor, maplayout);
98         if ( area > maxarea ) maxarea = area;
99     }
100     return maxarea;
101 }
102 
103 /**
104 This part is related to medals system. WIP
105  */
106 
107 const char * medal_messages[] = { "defended the flag", "covered the flag stealer", "defended the dropped flag", "covered the flag keeper", "covered teammate" };
108 enum { CTFLDEF, CTFLCOV, HTFLDEF, HTFLCOV, COVER, MEDALMESSAGENUM };
print_medal_messages(client * c,int n)109 inline void print_medal_messages(client *c, int n)
110 {
111     if (n<0 || n>=MEDALMESSAGENUM) return;
112     logline(ACLOG_VERBOSE, "[%s] %s %s", c->hostname, c->name, medal_messages[n]);
113 }
114 
115 inline void addpt(client *c, int points, int n = -1) {
116     c->state.points += points;
117     c->md.dpt += points;
118     c->md.updated = true;
119     c->md.upmillis = gamemillis + 240; // about 2 AR shots
120     print_medal_messages(c,n);
121 }
122 
123 /** cnumber is the number of players in the game, at a max value of 12 */
124 #define CTFPICKPT     cnumber                      // player picked the flag (ctf)
125 #define CTFDROPPT    -cnumber                      // player dropped the flag to other player (probably)
126 #define HTFLOSTPT  -2*cnumber                      // penalty
127 #define CTFLOSTPT     cnumber*distance/100         // bonus: 1/4 of the flag score bonus
128 #define CTFRETURNPT   cnumber                      // flag return
129 #define CTFSCOREPT   (cnumber*distance/25+10)      // flag score
130 #define HTFSCOREPT   (cnumber*4+10)
131 #define KTFSCOREPT   (cnumber*2+10)
132 #define COMBOPT       5                            // player frags with combo
133 #define REPLYPT       2                            // reply success
134 #define TWDONEPT      5                            // team work done
135 #define CTFLDEFPT     cnumber                      // player defended the flag in the base (ctf)
136 #define CTFLCOVPT     cnumber*2                    // player covered the flag stealer (ctf)
137 #define HTFLDEFPT     cnumber                      // player defended a droped flag (htf)
138 #define HTFLCOVPT     cnumber*3                    // player covered the flag keeper (htf)
139 #define COVERPT       cnumber*2                    // player covered teammate
140 #define DEATHPT      -4                            // player died
141 #define BONUSPT       target->state.points/400     // bonus (for killing high level enemies :: beware with exponential behavior!)
142 #define FLBONUSPT     target->state.points/300     // bonus if flag team mode
143 #define TMBONUSPT     target->state.points/200     // bonus if team mode (to give some extra reward for playing tdm modes)
144 #define HTFFRAGPT     cnumber/2                    // player frags while carrying the flag
145 #define CTFFRAGPT   2*cnumber                      // player frags the flag stealer
146 #define FRAGPT        10                           // player frags (normal)
147 #define HEADSHOTPT    15                           // player gibs with head shot
148 #define KNIFEPT       20                           // player gibs with the knife
149 #define SHOTGPT       12                           // player gibs with the shotgun
150 #define TKPT         -20                           // player tks
151 #define FLAGTKPT     -2*(10+cnumber)               // player tks the flag keeper/stealer
152 
flagpoints(client * c,int message)153 void flagpoints(client *c, int message)
154 {
155     float distance = 0;
156     int cnumber = totalclients < 13 ? totalclients : 12;
157     switch (message)
158     {
159         case FM_PICKUP:
160             c->md.flagpos.x = c->state.o.x;
161             c->md.flagpos.y = c->state.o.y;
162             c->md.flagmillis = servmillis;
163             if (m_ctf) addpt(c, CTFPICKPT);
164             break;
165         case FM_DROP:
166             if (m_ctf) addpt(c, CTFDROPPT);
167             break;
168         case FM_LOST:
169             if (m_htf) addpt(c, HTFLOSTPT);
170             else if (m_ctf) {
171                 distance = sqrt(POW2XY(c->state.o,c->md.flagpos));
172                 if (distance > 200) distance = 200;                   // ~200 is the distance between the flags in ac_depot
173                 addpt(c, CTFLOSTPT);
174             }
175             break;
176         case FM_RETURN:
177             addpt(c, CTFRETURNPT);
178             break;
179         case FM_SCORE:
180             if (m_ctf) {
181                 distance = sqrt(POW2XY(c->state.o,c->md.flagpos));
182                 if (distance > 200) distance = 200;
183 #ifdef ACAC
184                 if ( validflagscore(distance,c) )
185 #endif
186                     addpt(c, CTFSCOREPT);
187             } else addpt(c, HTFSCOREPT);
188             break;
189         case FM_KTFSCORE:
190             addpt(c, KTFSCOREPT);
191             break;
192         default:
193             break;
194     }
195 }
196 
197 
minhits2combo(int gun)198 inline int minhits2combo(int gun)
199 {
200     switch (gun)
201     {
202         case GUN_SUBGUN:
203         case GUN_AKIMBO:
204             return 4;
205         case GUN_GRENADE:
206         case GUN_ASSAULT:
207             return 3;
208         default:
209             return 2;
210     }
211 }
212 
checkcombo(client * target,client * actor,int damage,int gun)213 void checkcombo(client *target, client *actor, int damage, int gun)
214 {
215     int diffhittime = servmillis - actor->md.lasthit;
216     actor->md.lasthit = servmillis;
217     if ((gun == GUN_SHOTGUN || gun == GUN_GRENADE) && damage < 20)
218     {
219         actor->md.lastgun = gun;
220         return;
221     }
222 
223     if ( diffhittime < 750 ) {
224         if ( gun == actor->md.lastgun )
225         {
226             if ( diffhittime * 2 < guns[gun].attackdelay * 3 )
227             {
228                 actor->md.combohits++;
229                 actor->md.combotime+=diffhittime;
230                 actor->md.combodamage+=damage;
231                 int mh2c = minhits2combo(gun);
232                 if ( actor->md.combohits > mh2c && actor->md.combohits % mh2c == 1 )
233                 {
234                     if (actor->md.combo < 5) actor->md.combo++;
235                     actor->md.ncombos++;
236                 }
237             }
238         }
239         else
240         {
241             switch (gun)
242             {
243                 case GUN_KNIFE:
244                 case GUN_PISTOL:
245                     if ( guns[actor->md.lastgun].isauto ) break;
246                 case GUN_SNIPER:
247                     if ( actor->md.lastgun > GUN_PISTOL ) break;
248                 default:
249                     actor->md.combohits++;
250                     actor->md.combotime+=diffhittime;
251                     actor->md.combodamage+=damage;
252                     if (actor->md.combo < 5) actor->md.combo++;
253                     actor->md.ncombos++;
254                     break;
255             }
256         }
257     }
258     else
259     {
260         actor->md.combo = 0;
261         actor->md.combofrags = 0;
262         actor->md.combotime = 0;
263         actor->md.combodamage = 0;
264         actor->md.combohits = 0;
265     }
266     actor->md.lastgun = gun;
267 }
268 
269 #define COVERDIST 2000 // about 45 cubes
270 #define REPLYDIST 8000 // about 90 cubes
271 float coverdist = COVERDIST;
272 
checkteamrequests(int sender)273 int checkteamrequests(int sender)
274 {
275     int dtime, besttime = -1;
276     int bestid = -1;
277     client *ant = clients[sender];
278     loopv(clients) {
279         client *prot = clients[i];
280         if ( i!=sender && prot->type != ST_EMPTY && prot->team == ant->team &&
281              prot->state.state == CS_ALIVE && prot->md.askmillis > gamemillis && prot->md.ask >= 0 ) {
282             float dist = POW2XY(ant->state.o,prot->state.o);
283             if ( dist < REPLYDIST && (dtime=prot->md.askmillis-gamemillis) > besttime) {
284                 bestid = i;
285                 besttime = dtime;
286             }
287         }
288     }
289     if ( besttime >= 0 ) return bestid;
290     return -1;
291 }
292 
293 /** WIP */
checkteamplay(int s,int sender)294 void checkteamplay(int s, int sender)
295 {
296     client *actor = clients[sender];
297 
298     if ( actor->state.state != CS_ALIVE ) return;
299     switch(s){
300         case S_IMONDEFENSE: // informs
301             actor->md.linkmillis = gamemillis + 20000;
302             actor->md.linkreason = s;
303             break;
304         case S_COVERME: // demands
305         case S_STAYTOGETHER:
306         case S_STAYHERE:
307             actor->md.ask = s;
308             actor->md.askmillis = gamemillis + 5000;
309             break;
310         case S_AFFIRMATIVE: // replies
311         case S_ALLRIGHTSIR:
312         case S_YES:
313         {
314             int id = checkteamrequests(sender);
315             if ( id >= 0 ) {
316                 client *sgt = clients[id];
317                 actor->md.linked = id;
318                 if ( actor->md.linkmillis < gamemillis ) addpt(actor,REPLYPT);
319                 actor->md.linkmillis = gamemillis + 30000;
320                 actor->md.linkreason = sgt->md.ask;
321                 sendf(actor->clientnum, 1, "ri2", SV_HUDEXTRAS, HE_NUM+id);
322                 switch( actor->md.linkreason ) { // check demands
323                     case S_STAYHERE:
324                         actor->md.pos = sgt->state.o;
325                         addpt(sgt,REPLYPT);
326                         break;
327                 }
328             }
329             break;
330         }
331     }
332 }
333 
computeteamwork(int team,int exclude)334 void computeteamwork(int team, int exclude) // testing
335 {
336     loopv(clients)
337     {
338         client *actor = clients[i];
339         if ( i == exclude || actor->type == ST_EMPTY || actor->team != team || actor->state.state != CS_ALIVE || actor->md.linkmillis < gamemillis ) continue;
340         vec position;
341         bool teamworkdone = false;
342         switch( actor->md.linkreason )
343         {
344             case S_IMONDEFENSE:
345                 position = actor->spawnp;
346                 teamworkdone = true;
347                 break;
348             case S_STAYTOGETHER:
349                 if ( valid_client(actor->md.linked) ) position = clients[actor->md.linked]->state.o;
350                 teamworkdone = true;
351                 break;
352             case S_STAYHERE:
353                 position = actor->md.pos;
354                 teamworkdone = true;
355                 break;
356         }
357         if ( teamworkdone )
358         {
359             float dist = POW2XY(actor->state.o,position);
360             if (dist < COVERDIST)
361             {
362                 addpt(actor,TWDONEPT);
363                 sendf(actor->clientnum, 1, "ri2", SV_HUDEXTRAS, HE_TEAMWORK);
364             }
365         }
366     }
367 }
368 
369 float a2c = 0, c2t = 0, a2t = 0; // distances: actor to covered, covered to target and actor to target
370 
testcover(int msg,int factor,client * actor)371 inline bool testcover(int msg, int factor, client *actor)
372 {
373     if ( a2c < coverdist && c2t < coverdist && a2t < coverdist )
374     {
375         sendf(actor->clientnum, 1, "ri2", SV_HUDEXTRAS, msg);
376         addpt(actor, factor);
377         actor->md.ncovers++;
378         return true;
379     }
380     return false;
381 }
382 
383 #define CALCCOVER(C) \
384     a2c = POW2XY(actor->state.o,C);\
385     c2t = POW2XY(C,target->state.o);\
386     a2t = POW2XY(actor->state.o,target->state.o)
387 
validlink(client * actor,int cn)388 bool validlink(client *actor, int cn)
389 {
390     return actor->md.linked >= 0 && actor->md.linked == cn && gamemillis < actor->md.linkmillis && valid_client(actor->md.linked);
391 }
392 
393 /** WIP */
checkcover(client * target,client * actor)394 void checkcover(client *target, client *actor)
395 {
396     int team = actor->team;
397     int oteam = team_opposite(team);
398 
399     bool covered = false;
400     int coverid = -1;
401 
402     int cnumber = totalclients < 13 ? totalclients : 12;
403 
404     if ( m_flags ) {
405         sflaginfo &f = sflaginfos[team];
406         sflaginfo &of = sflaginfos[oteam];
407 
408         if ( m_ctf )
409         {
410             if ( f.state == CTFF_INBASE )
411             {
412                 CALCCOVER(f);
413                 if ( testcover(HE_FLAGDEFENDED, CTFLDEFPT, actor) ) print_medal_messages(actor,CTFLDEF);
414             }
415             if ( of.state == CTFF_STOLEN && actor->clientnum != of.actor_cn )
416             {
417                 covered = true; coverid = of.actor_cn;
418                 CALCCOVER(clients[of.actor_cn]->state.o);
419                 if ( testcover(HE_FLAGCOVERED, CTFLCOVPT, actor) ) print_medal_messages(actor,CTFLCOV);
420             }
421         }
422         else if ( m_htf )
423         {
424             if ( actor->clientnum != f.actor_cn )
425             {
426                 if ( f.state == CTFF_DROPPED )
427                 {
428                     struct { short x, y; } nf;
429                     nf.x = f.pos[0]; nf.y = f.pos[1];
430                     CALCCOVER(nf);
431                     if ( testcover(HE_FLAGDEFENDED, HTFLDEFPT, actor) ) print_medal_messages(actor,HTFLDEF);
432                 }
433                 if ( f.state == CTFF_STOLEN )
434                 {
435                     covered = true; coverid = f.actor_cn;
436                     CALCCOVER(clients[f.actor_cn]->state.o);
437                     if ( testcover(HE_FLAGCOVERED, HTFLCOVPT, actor) ) print_medal_messages(actor,HTFLCOV);
438                 }
439             }
440         }
441     }
442 
443     if ( !(covered && actor->md.linked==coverid) && validlink(actor,actor->md.linked) )
444     {
445         CALCCOVER(clients[actor->md.linked]->state.o);
446         if ( testcover(HE_COVER, COVERPT, actor) ) print_medal_messages(actor,COVER);
447     }
448 
449 }
450 
451 #undef CALCCOVER
452 
453 /** WiP */
checkfrag(client * target,client * actor,int gun,bool gib)454 void checkfrag(client *target, client *actor, int gun, bool gib)
455 {
456     int targethasflag = clienthasflag(target->clientnum);
457     int actorhasflag = clienthasflag(actor->clientnum);
458     int cnumber = totalclients < 13 ? totalclients : 12;
459     addpt(target,DEATHPT);
460     if(target!=actor) {
461         if(!isteam(target->team, actor->team)) {
462 
463             if (m_teammode) {
464                 if(!m_flags) addpt(actor, TMBONUSPT);
465                 else addpt(actor, FLBONUSPT);
466 
467                 checkcover (target, actor);
468                 if ( m_htf && actorhasflag >= 0 ) addpt(actor, HTFFRAGPT);
469 
470                 if ( m_ctf && targethasflag >= 0 ) {
471                     addpt(actor, CTFFRAGPT);
472                 }
473             }
474             else addpt(actor, BONUSPT);
475 
476             if (gib && gun != GUN_GRENADE) {
477                 if ( gun == GUN_SNIPER ) {
478                     addpt(actor, HEADSHOTPT);
479                     actor->md.nhs++;
480                 }
481                 else if ( gun == GUN_KNIFE ) addpt(actor, KNIFEPT);
482                 else if ( gun == GUN_SHOTGUN ) addpt(actor, SHOTGPT);
483             }
484             else addpt(actor, FRAGPT);
485 
486             if ( actor->md.combo ) {
487                 actor->md.combofrags++;
488                 addpt(actor,COMBOPT);
489                 actor->md.combosend = true;
490             }
491 
492         } else {
493 
494             if ( targethasflag >= 0 ) addpt(actor, FLAGTKPT);
495             else addpt(actor, TKPT);
496 
497         }
498     }
499 }
500 
501 int next_afk_check = 200;
502 
503 /* this function is managed to the PUBS, id est, many people playing in an open server */
check_afk()504 void check_afk()
505 {
506     next_afk_check = servmillis + 7 * 1000;
507     /* if we have few people (like 2x2), or it is not a teammode with the server not full: do nothing! */
508     if ( totalclients < 5 || ( totalclients < scl.maxclients && !m_teammode)  ) return;
509     loopv(clients)
510     {
511         client &c = *clients[i];
512         if ( c.type != ST_TCPIP || c.connectmillis + 60 * 1000 > servmillis ||
513              c.inputmillis + scl.afk_limit > servmillis || clienthasflag(c.clientnum) != -1 ) continue;
514         if ( ( c.state.state == CS_DEAD && !m_arena && c.state.lastdeath + 45 * 1000 < gamemillis) ||
515              ( c.state.state == CS_ALIVE && c.upspawnp ) /*||
516              ( c.state.state == CS_SPECTATE && totalclients >= scl.maxclients )  // only kick spectator if server is full - 2011oct16:flowtron: mmh, that seems reasonable enough .. still, kicking spectators for inactivity seems harsh! disabled ATM, kick them manually if you must.
517              */
518             )
519         {
520             logline(ACLOG_INFO, "[%s] %s %s", c.hostname, c.name, "is afk");
521             defformatstring(msg)("%s is afk", c.name);
522             sendservmsg(msg);
523             disconnect_client(c.clientnum, DISC_AFK);
524         }
525     }
526 }
527 
528 /** This function counts how much non-killing-damage the player does to any teammates
529     The damage limit is 100 hp per minute, which is about 2 tks per minute in a normal game
530     In normal games, the players go over 6 tks only in the worst cases */
check_ffire(client * target,client * actor,int damage)531 void check_ffire(client *target, client *actor, int damage)
532 {
533     if ( mastermode != MM_OPEN ) return;
534     actor->ffire += damage;
535     if ( actor->ffire > 300 && actor->ffire * 600 > gamemillis) {
536         logline(ACLOG_INFO, "[%s] %s %s", actor->hostname, actor->name, "kicked for excessive friendly fire");
537         defformatstring(msg)("%s %s", actor->name, "kicked for excessive friendly fire");
538         sendservmsg(msg);
539         disconnect_client(actor->clientnum, DISC_FFIRE);
540     }
541 }
542 
check_pdist(client * c,float & dist)543 inline int check_pdist(client *c, float & dist) // pick up distance
544 {
545     // ping 1000ms at max velocity can produce an error of 20 cubes
546     float delay = 9.0f + (float)c->ping * 0.02f + (float)c->spj * 0.025f; // at pj/ping 40/100, delay = 12
547     if ( dist > delay )
548     {
549         if ( dist < 1.5f * delay ) return 1;
550 #ifdef ACAC
551         pickup_checks(c,dist-delay);
552 #endif
553         return 2;
554     }
555     return 0;
556 }
557 
558 /**
559 If you read README.txt you must know that AC does not have cheat protection implemented.
560 However this file is the sketch to a very special kind of cheat detection tools in server side.
561 
562 This is not based in program tricks, i.e., encryption, secret bytes, nor monitoring/scanning tools.
563 
564 The idea behind these cheat detections is to check (or reproduce) the client data, and verify if
565 this data is expected or possible. Also, there is no need to check all clients all time, and
566 one coding this kind of check must pay a special attention to the lag effect and how it can
567 affect the data observed. This is not a trivial task, and probably it is the main reason why
568 such tools were never implemented.
569 
570 This part is here for compatibility purposes.
571 If you know nothing about these detections, please, just ignore it.
572 */
573 
checkmove(client * cl)574 inline void checkmove(client *cl)
575 {
576     cl->ldt = gamemillis - cl->lmillis;
577     cl->lmillis = gamemillis;
578     if ( cl->ldt < 40 ) cl->ldt = 40;
579     cl->t += cl->ldt;
580     cl->spj = (( 7 * cl->spj + cl->ldt ) >> 3);
581 
582     if ( cl->input != cl->f )
583     {
584         cl->input = cl->f;
585         cl->inputmillis = servmillis;
586     }
587 
588     if(maplayout) checkclientpos(cl);
589 
590 #ifdef ACAC
591     m_engine(cl);
592 #endif
593 
594     if ( !cl->upspawnp )
595     {
596         cl->spawnp = cl->state.o;
597         cl->upspawnp = true;
598         cl->spj = cl->ldt = 40;
599     }
600 
601     return;
602 }
603 
checkshoot(int & cn,gameevent & shot,int & hits,int & tcn)604 inline void checkshoot(int & cn, gameevent & shot, int & hits, int & tcn)
605 {
606 #ifdef ACAC
607     s_engine(cn, shot, hits, tcn);
608 #endif
609     return;
610 }
611 
checkweapon(int & type,int & var)612 inline void checkweapon(int & type, int & var)
613 {
614 #ifdef ACAC
615     w_engine(type,var);
616 #endif
617     return;
618 }
619 
validdamage(client * & target,client * & actor,int & damage,int & gun,bool & gib)620 bool validdamage(client *&target, client *&actor, int &damage, int &gun, bool &gib)
621 {
622 #ifdef ACAC
623     if (!d_engine(target, actor, damage, gun, gib)) return false;
624 #endif
625     return true;
626 }
627 
checkmessage(client * c,int type)628 inline int checkmessage(client *c, int type)
629 {
630 #ifdef ACAC
631     type = p_engine(c,type);
632 #endif
633     return type;
634 }
635 
636