vkQuake2 doxygen  1.0 dev
p_client.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 #include "g_local.h"
21 #include "m_player.h"
22 
23 void ClientUserinfoChanged (edict_t *ent, char *userinfo);
24 
26 
27 //
28 // Gross, ugly, disgustuing hack section
29 //
30 
31 // this function is an ugly as hell hack to fix some map flaws
32 //
33 // the coop spawn spots on some maps are SNAFU. There are coop spots
34 // with the wrong targetname as well as spots with no name at all
35 //
36 // we use carnal knowledge of the maps to fix the coop spot targetnames to match
37 // that of the nearest named single player spot
38 
39 static void SP_FixCoopSpots (edict_t *self)
40 {
41  edict_t *spot;
42  vec3_t d;
43 
44  spot = NULL;
45 
46  while(1)
47  {
48  spot = G_Find(spot, FOFS(classname), "info_player_start");
49  if (!spot)
50  return;
51  if (!spot->targetname)
52  continue;
53  VectorSubtract(self->s.origin, spot->s.origin, d);
54  if (VectorLength(d) < 384)
55  {
56  if ((!self->targetname) || Q_stricmp(self->targetname, spot->targetname) != 0)
57  {
58 // gi.dprintf("FixCoopSpots changed %s at %s targetname from %s to %s\n", self->classname, vtos(self->s.origin), self->targetname, spot->targetname);
59  self->targetname = spot->targetname;
60  }
61  return;
62  }
63  }
64 }
65 
66 // now if that one wasn't ugly enough for you then try this one on for size
67 // some maps don't have any coop spots at all, so we need to create them
68 // where they should have been
69 
70 static void SP_CreateCoopSpots (edict_t *self)
71 {
72  edict_t *spot;
73 
74  if(Q_stricmp(level.mapname, "security") == 0)
75  {
76  spot = G_Spawn();
77  spot->classname = "info_player_coop";
78  spot->s.origin[0] = 188 - 64;
79  spot->s.origin[1] = -164;
80  spot->s.origin[2] = 80;
81  spot->targetname = "jail3";
82  spot->s.angles[1] = 90;
83 
84  spot = G_Spawn();
85  spot->classname = "info_player_coop";
86  spot->s.origin[0] = 188 + 64;
87  spot->s.origin[1] = -164;
88  spot->s.origin[2] = 80;
89  spot->targetname = "jail3";
90  spot->s.angles[1] = 90;
91 
92  spot = G_Spawn();
93  spot->classname = "info_player_coop";
94  spot->s.origin[0] = 188 + 128;
95  spot->s.origin[1] = -164;
96  spot->s.origin[2] = 80;
97  spot->targetname = "jail3";
98  spot->s.angles[1] = 90;
99 
100  return;
101  }
102 }
103 
104 
105 /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32)
106 The normal starting point for a level.
107 */
109 {
110  if (!coop->value)
111  return;
112  if(Q_stricmp(level.mapname, "security") == 0)
113  {
114  // invoke one of our gross, ugly, disgusting hacks
115  self->think = SP_CreateCoopSpots;
116  self->nextthink = level.time + FRAMETIME;
117  }
118 }
119 
120 /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32)
121 potential spawning position for deathmatch games
122 */
124 {
125  if (!deathmatch->value)
126  {
127  G_FreeEdict (self);
128  return;
129  }
131 }
132 
133 /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32)
134 potential spawning position for coop games
135 */
136 
138 {
139  if (!coop->value)
140  {
141  G_FreeEdict (self);
142  return;
143  }
144 
145  if((Q_stricmp(level.mapname, "jail2") == 0) ||
146  (Q_stricmp(level.mapname, "jail4") == 0) ||
147  (Q_stricmp(level.mapname, "mine1") == 0) ||
148  (Q_stricmp(level.mapname, "mine2") == 0) ||
149  (Q_stricmp(level.mapname, "mine3") == 0) ||
150  (Q_stricmp(level.mapname, "mine4") == 0) ||
151  (Q_stricmp(level.mapname, "lab") == 0) ||
152  (Q_stricmp(level.mapname, "boss1") == 0) ||
153  (Q_stricmp(level.mapname, "fact3") == 0) ||
154  (Q_stricmp(level.mapname, "biggun") == 0) ||
155  (Q_stricmp(level.mapname, "space") == 0) ||
156  (Q_stricmp(level.mapname, "command") == 0) ||
157  (Q_stricmp(level.mapname, "power2") == 0) ||
158  (Q_stricmp(level.mapname, "strike") == 0))
159  {
160  // invoke one of our gross, ugly, disgusting hacks
161  self->think = SP_FixCoopSpots;
162  self->nextthink = level.time + FRAMETIME;
163  }
164 }
165 
166 
167 /*QUAKED info_player_intermission (1 0 1) (-16 -16 -24) (16 16 32)
168 The deathmatch intermission point will be at one of these
169 Use 'angles' instead of 'angle', so you can set pitch or roll as well as yaw. 'pitch yaw roll'
170 */
172 {
173 }
174 
175 
176 //=======================================================================
177 
178 
179 void player_pain (edict_t *self, edict_t *other, float kick, int damage)
180 {
181  // player pain is handled at the end of the frame in P_DamageFeedback
182 }
183 
184 
186 {
187  char *info;
188 
189  if (!ent->client)
190  return false;
191 
192  info = Info_ValueForKey (ent->client->pers.userinfo, "gender");
193  if (info[0] == 'f' || info[0] == 'F')
194  return true;
195  return false;
196 }
197 
199 {
200  char *info;
201 
202  if (!ent->client)
203  return false;
204 
205  info = Info_ValueForKey (ent->client->pers.userinfo, "gender");
206  if (info[0] != 'f' && info[0] != 'F' && info[0] != 'm' && info[0] != 'M')
207  return true;
208  return false;
209 }
210 
211 void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
212 {
213  int mod;
214  char *message;
215  char *message2;
216  qboolean ff;
217 
218  if (coop->value && attacker->client)
220 
221  if (deathmatch->value || coop->value)
222  {
225  message = NULL;
226  message2 = "";
227 
228  switch (mod)
229  {
230  case MOD_SUICIDE:
231  message = "suicides";
232  break;
233  case MOD_FALLING:
234  message = "cratered";
235  break;
236  case MOD_CRUSH:
237  message = "was squished";
238  break;
239  case MOD_WATER:
240  message = "sank like a rock";
241  break;
242  case MOD_SLIME:
243  message = "melted";
244  break;
245  case MOD_LAVA:
246  message = "does a back flip into the lava";
247  break;
248  case MOD_EXPLOSIVE:
249  case MOD_BARREL:
250  message = "blew up";
251  break;
252  case MOD_EXIT:
253  message = "found a way out";
254  break;
255  case MOD_TARGET_LASER:
256  message = "saw the light";
257  break;
258  case MOD_TARGET_BLASTER:
259  message = "got blasted";
260  break;
261  case MOD_BOMB:
262  case MOD_SPLASH:
263  case MOD_TRIGGER_HURT:
264  message = "was in the wrong place";
265  break;
266  }
267  if (attacker == self)
268  {
269  switch (mod)
270  {
271  case MOD_HELD_GRENADE:
272  message = "tried to put the pin back in";
273  break;
274  case MOD_HG_SPLASH:
275  case MOD_G_SPLASH:
276  if (IsNeutral(self))
277  message = "tripped on its own grenade";
278  else if (IsFemale(self))
279  message = "tripped on her own grenade";
280  else
281  message = "tripped on his own grenade";
282  break;
283  case MOD_R_SPLASH:
284  if (IsNeutral(self))
285  message = "blew itself up";
286  else if (IsFemale(self))
287  message = "blew herself up";
288  else
289  message = "blew himself up";
290  break;
291  case MOD_BFG_BLAST:
292  message = "should have used a smaller gun";
293  break;
294  default:
295  if (IsNeutral(self))
296  message = "killed itself";
297  else if (IsFemale(self))
298  message = "killed herself";
299  else
300  message = "killed himself";
301  break;
302  }
303  }
304  if (message)
305  {
306  gi.bprintf (PRINT_MEDIUM, "%s %s.\n", self->client->pers.netname, message);
307  if (deathmatch->value)
308  self->client->resp.score--;
309  self->enemy = NULL;
310  return;
311  }
312 
313  self->enemy = attacker;
314  if (attacker && attacker->client)
315  {
316  switch (mod)
317  {
318  case MOD_BLASTER:
319  message = "was blasted by";
320  break;
321  case MOD_SHOTGUN:
322  message = "was gunned down by";
323  break;
324  case MOD_SSHOTGUN:
325  message = "was blown away by";
326  message2 = "'s super shotgun";
327  break;
328  case MOD_MACHINEGUN:
329  message = "was machinegunned by";
330  break;
331  case MOD_CHAINGUN:
332  message = "was cut in half by";
333  message2 = "'s chaingun";
334  break;
335  case MOD_GRENADE:
336  message = "was popped by";
337  message2 = "'s grenade";
338  break;
339  case MOD_G_SPLASH:
340  message = "was shredded by";
341  message2 = "'s shrapnel";
342  break;
343  case MOD_ROCKET:
344  message = "ate";
345  message2 = "'s rocket";
346  break;
347  case MOD_R_SPLASH:
348  message = "almost dodged";
349  message2 = "'s rocket";
350  break;
351  case MOD_HYPERBLASTER:
352  message = "was melted by";
353  message2 = "'s hyperblaster";
354  break;
355  case MOD_RAILGUN:
356  message = "was railed by";
357  break;
358  case MOD_BFG_LASER:
359  message = "saw the pretty lights from";
360  message2 = "'s BFG";
361  break;
362  case MOD_BFG_BLAST:
363  message = "was disintegrated by";
364  message2 = "'s BFG blast";
365  break;
366  case MOD_BFG_EFFECT:
367  message = "couldn't hide from";
368  message2 = "'s BFG";
369  break;
370  case MOD_HANDGRENADE:
371  message = "caught";
372  message2 = "'s handgrenade";
373  break;
374  case MOD_HG_SPLASH:
375  message = "didn't see";
376  message2 = "'s handgrenade";
377  break;
378  case MOD_HELD_GRENADE:
379  message = "feels";
380  message2 = "'s pain";
381  break;
382  case MOD_TELEFRAG:
383  message = "tried to invade";
384  message2 = "'s personal space";
385  break;
386  }
387  if (message)
388  {
389  gi.bprintf (PRINT_MEDIUM,"%s %s %s%s\n", self->client->pers.netname, message, attacker->client->pers.netname, message2);
390  if (deathmatch->value)
391  {
392  if (ff)
393  attacker->client->resp.score--;
394  else
395  attacker->client->resp.score++;
396  }
397  return;
398  }
399  }
400  }
401 
402  gi.bprintf (PRINT_MEDIUM,"%s died.\n", self->client->pers.netname);
403  if (deathmatch->value)
404  self->client->resp.score--;
405 }
406 
407 
408 void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
409 
411 {
412  gitem_t *item;
413  edict_t *drop;
414  qboolean quad;
415  float spread;
416 
417  if (!deathmatch->value)
418  return;
419 
420  item = self->client->pers.weapon;
421  if (! self->client->pers.inventory[self->client->ammo_index] )
422  item = NULL;
423  if (item && (strcmp (item->pickup_name, "Blaster") == 0))
424  item = NULL;
425 
426  if (!((int)(dmflags->value) & DF_QUAD_DROP))
427  quad = false;
428  else
429  quad = (self->client->quad_framenum > (level.framenum + 10));
430 
431  if (item && quad)
432  spread = 22.5;
433  else
434  spread = 0.0;
435 
436  if (item)
437  {
438  self->client->v_angle[YAW] -= spread;
439  drop = Drop_Item (self, item);
440  self->client->v_angle[YAW] += spread;
442  }
443 
444  if (quad)
445  {
446  self->client->v_angle[YAW] += spread;
447  drop = Drop_Item (self, FindItemByClassname ("item_quad"));
448  self->client->v_angle[YAW] -= spread;
450 
451  drop->touch = Touch_Item;
452  drop->nextthink = level.time + (self->client->quad_framenum - level.framenum) * FRAMETIME;
453  drop->think = G_FreeEdict;
454  }
455 }
456 
457 
458 /*
459 ==================
460 LookAtKiller
461 ==================
462 */
463 void LookAtKiller (edict_t *self, edict_t *inflictor, edict_t *attacker)
464 {
465  vec3_t dir;
466 
467  if (attacker && attacker != world && attacker != self)
468  {
469  VectorSubtract (attacker->s.origin, self->s.origin, dir);
470  }
471  else if (inflictor && inflictor != world && inflictor != self)
472  {
473  VectorSubtract (inflictor->s.origin, self->s.origin, dir);
474  }
475  else
476  {
477  self->client->killer_yaw = self->s.angles[YAW];
478  return;
479  }
480 
481  if (dir[0])
482  self->client->killer_yaw = 180/M_PI*atan2(dir[1], dir[0]);
483  else {
484  self->client->killer_yaw = 0;
485  if (dir[1] > 0)
486  self->client->killer_yaw = 90;
487  else if (dir[1] < 0)
488  self->client->killer_yaw = -90;
489  }
490  if (self->client->killer_yaw < 0)
491  self->client->killer_yaw += 360;
492 
493 
494 }
495 
496 /*
497 ==================
498 player_die
499 ==================
500 */
501 void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
502 {
503  int n;
504 
505  VectorClear (self->avelocity);
506 
507  self->takedamage = DAMAGE_YES;
508  self->movetype = MOVETYPE_TOSS;
509 
510  self->s.modelindex2 = 0; // remove linked weapon model
511 
512  self->s.angles[0] = 0;
513  self->s.angles[2] = 0;
514 
515  self->s.sound = 0;
516  self->client->weapon_sound = 0;
517 
518  self->maxs[2] = -8;
519 
520 // self->solid = SOLID_NOT;
521  self->svflags |= SVF_DEADMONSTER;
522 
523  if (!self->deadflag)
524  {
525  self->client->respawn_time = level.time + 1.0;
526  LookAtKiller (self, inflictor, attacker);
527  self->client->ps.pmove.pm_type = PM_DEAD;
528  ClientObituary (self, inflictor, attacker);
529  TossClientWeapon (self);
530  if (deathmatch->value)
531  Cmd_Help_f (self); // show scores
532 
533  // clear inventory
534  // this is kind of ugly, but it's how we want to handle keys in coop
535  for (n = 0; n < game.num_items; n++)
536  {
537  if (coop->value && itemlist[n].flags & IT_KEY)
538  self->client->resp.coop_respawn.inventory[n] = self->client->pers.inventory[n];
539  self->client->pers.inventory[n] = 0;
540  }
541  }
542 
543  // remove powerups
544  self->client->quad_framenum = 0;
545  self->client->invincible_framenum = 0;
546  self->client->breather_framenum = 0;
547  self->client->enviro_framenum = 0;
548  self->flags &= ~FL_POWER_ARMOR;
549 
550  if (self->health < -40)
551  { // gib
552  gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
553  for (n= 0; n < 4; n++)
554  ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
555  ThrowClientHead (self, damage);
556 
557  self->takedamage = DAMAGE_NO;
558  }
559  else
560  { // normal death
561  if (!self->deadflag)
562  {
563  static int i;
564 
565  i = (i+1)%3;
566  // start a death animation
567  self->client->anim_priority = ANIM_DEATH;
568  if (self->client->ps.pmove.pm_flags & PMF_DUCKED)
569  {
570  self->s.frame = FRAME_crdeath1-1;
571  self->client->anim_end = FRAME_crdeath5;
572  }
573  else switch (i)
574  {
575  case 0:
576  self->s.frame = FRAME_death101-1;
577  self->client->anim_end = FRAME_death106;
578  break;
579  case 1:
580  self->s.frame = FRAME_death201-1;
581  self->client->anim_end = FRAME_death206;
582  break;
583  case 2:
584  self->s.frame = FRAME_death301-1;
585  self->client->anim_end = FRAME_death308;
586  break;
587  }
588  gi.sound (self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", (rand()%4)+1)), 1, ATTN_NORM, 0);
589  }
590  }
591 
592  self->deadflag = DEAD_DEAD;
593 
594  gi.linkentity (self);
595 }
596 
597 //=======================================================================
598 
599 /*
600 ==============
601 InitClientPersistant
602 
603 This is only called when the game first initializes in single player,
604 but is called after each death and level change in deathmatch
605 ==============
606 */
608 {
609  gitem_t *item;
610 
611  memset (&client->pers, 0, sizeof(client->pers));
612 
613  item = FindItem("Blaster");
616 
617  client->pers.weapon = item;
618 
619  client->pers.health = 100;
620  client->pers.max_health = 100;
621 
622  client->pers.max_bullets = 200;
623  client->pers.max_shells = 100;
624  client->pers.max_rockets = 50;
625  client->pers.max_grenades = 50;
626  client->pers.max_cells = 200;
627  client->pers.max_slugs = 50;
628 
629  client->pers.connected = true;
630 }
631 
632 
634 {
635  memset (&client->resp, 0, sizeof(client->resp));
636  client->resp.enterframe = level.framenum;
638 }
639 
640 /*
641 ==================
642 SaveClientData
643 
644 Some information that should be persistant, like health,
645 is still stored in the edict structure, so it needs to
646 be mirrored out to the client structure before all the
647 edicts are wiped.
648 ==================
649 */
650 void SaveClientData (void)
651 {
652  int i;
653  edict_t *ent;
654 
655  for (i=0 ; i<game.maxclients ; i++)
656  {
657  ent = &g_edicts[1+i];
658  if (!ent->inuse)
659  continue;
660  game.clients[i].pers.health = ent->health;
663  if (coop->value)
664  game.clients[i].pers.score = ent->client->resp.score;
665  }
666 }
667 
669 {
670  ent->health = ent->client->pers.health;
671  ent->max_health = ent->client->pers.max_health;
672  ent->flags |= ent->client->pers.savedFlags;
673  if (coop->value)
674  ent->client->resp.score = ent->client->pers.score;
675 }
676 
677 
678 
679 /*
680 =======================================================================
681 
682  SelectSpawnPoint
683 
684 =======================================================================
685 */
686 
687 /*
688 ================
689 PlayersRangeFromSpot
690 
691 Returns the distance to the nearest player from the given spot
692 ================
693 */
695 {
696  edict_t *player;
697  float bestplayerdistance;
698  vec3_t v;
699  int n;
700  float playerdistance;
701 
702 
703  bestplayerdistance = 9999999;
704 
705  for (n = 1; n <= maxclients->value; n++)
706  {
707  player = &g_edicts[n];
708 
709  if (!player->inuse)
710  continue;
711 
712  if (player->health <= 0)
713  continue;
714 
715  VectorSubtract (spot->s.origin, player->s.origin, v);
716  playerdistance = VectorLength (v);
717 
718  if (playerdistance < bestplayerdistance)
719  bestplayerdistance = playerdistance;
720  }
721 
722  return bestplayerdistance;
723 }
724 
725 /*
726 ================
727 SelectRandomDeathmatchSpawnPoint
728 
729 go to a random point, but NOT the two points closest
730 to other players
731 ================
732 */
734 {
735  edict_t *spot, *spot1, *spot2;
736  int count = 0;
737  int selection;
738  float range, range1, range2;
739 
740  spot = NULL;
741  range1 = range2 = 99999;
742  spot1 = spot2 = NULL;
743 
744  while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
745  {
746  count++;
747  range = PlayersRangeFromSpot(spot);
748  if (range < range1)
749  {
750  range1 = range;
751  spot1 = spot;
752  }
753  else if (range < range2)
754  {
755  range2 = range;
756  spot2 = spot;
757  }
758  }
759 
760  if (!count)
761  return NULL;
762 
763  if (count <= 2)
764  {
765  spot1 = spot2 = NULL;
766  }
767  else
768  count -= 2;
769 
770  selection = rand() % count;
771 
772  spot = NULL;
773  do
774  {
775  spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");
776  if (spot == spot1 || spot == spot2)
777  selection++;
778  } while(selection--);
779 
780  return spot;
781 }
782 
783 /*
784 ================
785 SelectFarthestDeathmatchSpawnPoint
786 
787 ================
788 */
790 {
791  edict_t *bestspot;
792  float bestdistance, bestplayerdistance;
793  edict_t *spot;
794 
795 
796  spot = NULL;
797  bestspot = NULL;
798  bestdistance = 0;
799  while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
800  {
801  bestplayerdistance = PlayersRangeFromSpot (spot);
802 
803  if (bestplayerdistance > bestdistance)
804  {
805  bestspot = spot;
806  bestdistance = bestplayerdistance;
807  }
808  }
809 
810  if (bestspot)
811  {
812  return bestspot;
813  }
814 
815  // if there is a player just spawned on each and every start spot
816  // we have no choice to turn one into a telefrag meltdown
817  spot = G_Find (NULL, FOFS(classname), "info_player_deathmatch");
818 
819  return spot;
820 }
821 
823 {
824  if ( (int)(dmflags->value) & DF_SPAWN_FARTHEST)
826  else
828 }
829 
830 
832 {
833  int index;
834  edict_t *spot = NULL;
835  char *target;
836 
837  index = ent->client - game.clients;
838 
839  // player 0 starts in normal player spawn point
840  if (!index)
841  return NULL;
842 
843  spot = NULL;
844 
845  // assume there are four coop spots at each spawnpoint
846  while (1)
847  {
848  spot = G_Find (spot, FOFS(classname), "info_player_coop");
849  if (!spot)
850  return NULL; // we didn't have enough...
851 
852  target = spot->targetname;
853  if (!target)
854  target = "";
855  if ( Q_stricmp(game.spawnpoint, target) == 0 )
856  { // this is a coop spawn point for one of the clients here
857  index--;
858  if (!index)
859  return spot; // this is it
860  }
861  }
862 
863 
864  return spot;
865 }
866 
867 
868 /*
869 ===========
870 SelectSpawnPoint
871 
872 Chooses a player start, deathmatch start, coop start, etc
873 ============
874 */
875 void SelectSpawnPoint (edict_t *ent, vec3_t origin, vec3_t angles)
876 {
877  edict_t *spot = NULL;
878 
879  if (deathmatch->value)
880  spot = SelectDeathmatchSpawnPoint ();
881  else if (coop->value)
882  spot = SelectCoopSpawnPoint (ent);
883 
884  // find a single player start spot
885  if (!spot)
886  {
887  while ((spot = G_Find (spot, FOFS(classname), "info_player_start")) != NULL)
888  {
889  if (!game.spawnpoint[0] && !spot->targetname)
890  break;
891 
892  if (!game.spawnpoint[0] || !spot->targetname)
893  continue;
894 
895  if (Q_stricmp(game.spawnpoint, spot->targetname) == 0)
896  break;
897  }
898 
899  if (!spot)
900  {
901  if (!game.spawnpoint[0])
902  { // there wasn't a spawnpoint without a target, so use any
903  spot = G_Find (spot, FOFS(classname), "info_player_start");
904  }
905  if (!spot)
906  gi.error ("Couldn't find spawn point %s\n", game.spawnpoint);
907  }
908  }
909 
910  VectorCopy (spot->s.origin, origin);
911  origin[2] += 9;
912  VectorCopy (spot->s.angles, angles);
913 }
914 
915 //======================================================================
916 
917 
918 void InitBodyQue (void)
919 {
920  int i;
921  edict_t *ent;
922 
923  level.body_que = 0;
924  for (i=0; i<BODY_QUEUE_SIZE ; i++)
925  {
926  ent = G_Spawn();
927  ent->classname = "bodyque";
928  }
929 }
930 
931 void body_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
932 {
933  int n;
934 
935  if (self->health < -40)
936  {
937  gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
938  for (n= 0; n < 4; n++)
939  ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
940  self->s.origin[2] -= 48;
941  ThrowClientHead (self, damage);
942  self->takedamage = DAMAGE_NO;
943  }
944 }
945 
947 {
948  edict_t *body;
949 
950  // grab a body que and cycle to the next one
951  body = &g_edicts[(int)maxclients->value + level.body_que + 1];
952  level.body_que = (level.body_que + 1) % BODY_QUEUE_SIZE;
953 
954  // FIXME: send an effect on the removed body
955 
956  gi.unlinkentity (ent);
957 
958  gi.unlinkentity (body);
959  body->s = ent->s;
960  body->s.number = body - g_edicts;
961 
962  body->svflags = ent->svflags;
963  VectorCopy (ent->mins, body->mins);
964  VectorCopy (ent->maxs, body->maxs);
965  VectorCopy (ent->absmin, body->absmin);
966  VectorCopy (ent->absmax, body->absmax);
967  VectorCopy (ent->size, body->size);
968  body->solid = ent->solid;
969  body->clipmask = ent->clipmask;
970  body->owner = ent->owner;
971  body->movetype = ent->movetype;
972 
973  body->die = body_die;
974  body->takedamage = DAMAGE_YES;
975 
976  gi.linkentity (body);
977 }
978 
979 
980 void respawn (edict_t *self)
981 {
982  if (deathmatch->value || coop->value)
983  {
984  // spectator's don't leave bodies
985  if (self->movetype != MOVETYPE_NOCLIP)
986  CopyToBodyQue (self);
987  self->svflags &= ~SVF_NOCLIENT;
988  PutClientInServer (self);
989 
990  // add a teleportation effect
991  self->s.event = EV_PLAYER_TELEPORT;
992 
993  // hold in place briefly
994  self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
995  self->client->ps.pmove.pm_time = 14;
996 
997  self->client->respawn_time = level.time;
998 
999  return;
1000  }
1001 
1002  // restart the entire server
1003  gi.AddCommandString ("menu_loadgame\n");
1004 }
1005 
1006 /*
1007  * only called when pers.spectator changes
1008  * note that resp.spectator should be the opposite of pers.spectator here
1009  */
1011 {
1012  int i, numspec;
1013 
1014  // if the user wants to become a spectator, make sure he doesn't
1015  // exceed max_spectators
1016 
1017  if (ent->client->pers.spectator) {
1018  char *value = Info_ValueForKey (ent->client->pers.userinfo, "spectator");
1019  if (*spectator_password->string &&
1020  strcmp(spectator_password->string, "none") &&
1021  strcmp(spectator_password->string, value)) {
1022  gi.cprintf(ent, PRINT_HIGH, "Spectator password incorrect.\n");
1023  ent->client->pers.spectator = false;
1025  gi.WriteString ("spectator 0\n");
1026  gi.unicast(ent, true);
1027  return;
1028  }
1029 
1030  // count spectators
1031  for (i = 1, numspec = 0; i <= maxclients->value; i++)
1033  numspec++;
1034 
1035  if (numspec >= maxspectators->value) {
1036  gi.cprintf(ent, PRINT_HIGH, "Server spectator limit is full.");
1037  ent->client->pers.spectator = false;
1038  // reset his spectator var
1040  gi.WriteString ("spectator 0\n");
1041  gi.unicast(ent, true);
1042  return;
1043  }
1044  } else {
1045  // he was a spectator and wants to join the game
1046  // he must have the right password
1047  char *value = Info_ValueForKey (ent->client->pers.userinfo, "password");
1048  if (*password->string && strcmp(password->string, "none") &&
1049  strcmp(password->string, value)) {
1050  gi.cprintf(ent, PRINT_HIGH, "Password incorrect.\n");
1051  ent->client->pers.spectator = true;
1053  gi.WriteString ("spectator 1\n");
1054  gi.unicast(ent, true);
1055  return;
1056  }
1057  }
1058 
1059  // clear client on respawn
1060  ent->client->resp.score = ent->client->pers.score = 0;
1061 
1062  ent->svflags &= ~SVF_NOCLIENT;
1063  PutClientInServer (ent);
1064 
1065  // add a teleportation effect
1066  if (!ent->client->pers.spectator) {
1067  // send effect
1069  gi.WriteShort (ent-g_edicts);
1070  gi.WriteByte (MZ_LOGIN);
1071  gi.multicast (ent->s.origin, MULTICAST_PVS);
1072 
1073  // hold in place briefly
1075  ent->client->ps.pmove.pm_time = 14;
1076  }
1077 
1078  ent->client->respawn_time = level.time;
1079 
1080  if (ent->client->pers.spectator)
1081  gi.bprintf (PRINT_HIGH, "%s has moved to the sidelines\n", ent->client->pers.netname);
1082  else
1083  gi.bprintf (PRINT_HIGH, "%s joined the game\n", ent->client->pers.netname);
1084 }
1085 
1086 //==============================================================
1087 
1088 
1089 /*
1090 ===========
1091 PutClientInServer
1092 
1093 Called when a player connects to a server or respawns in
1094 a deathmatch.
1095 ============
1096 */
1098 {
1099  vec3_t mins = {-16, -16, -24};
1100  vec3_t maxs = {16, 16, 32};
1101  int index;
1102  vec3_t spawn_origin, spawn_angles;
1103  gclient_t *client;
1104  int i;
1105  client_persistant_t saved;
1106  client_respawn_t resp;
1107 
1108  // find a spawn point
1109  // do it before setting health back up, so farthest
1110  // ranging doesn't count this client
1111  SelectSpawnPoint (ent, spawn_origin, spawn_angles);
1112 
1113  index = ent-g_edicts-1;
1114  client = ent->client;
1115 
1116  // deathmatch wipes most client data every spawn
1117  if (deathmatch->value)
1118  {
1119  char userinfo[MAX_INFO_STRING];
1120 
1121  resp = client->resp;
1122  memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
1124  ClientUserinfoChanged (ent, userinfo);
1125  }
1126  else if (coop->value)
1127  {
1128 // int n;
1129  char userinfo[MAX_INFO_STRING];
1130 
1131  resp = client->resp;
1132  memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
1133  // this is kind of ugly, but it's how we want to handle keys in coop
1134 // for (n = 0; n < game.num_items; n++)
1135 // {
1136 // if (itemlist[n].flags & IT_KEY)
1137 // resp.coop_respawn.inventory[n] = client->pers.inventory[n];
1138 // }
1141  client->pers = resp.coop_respawn;
1142  ClientUserinfoChanged (ent, userinfo);
1143  if (resp.score > client->pers.score)
1144  client->pers.score = resp.score;
1145  }
1146  else
1147  {
1148  memset (&resp, 0, sizeof(resp));
1149  }
1150 
1151  // clear everything but the persistant data
1152  saved = client->pers;
1153  memset (client, 0, sizeof(*client));
1154  client->pers = saved;
1155  if (client->pers.health <= 0)
1157  client->resp = resp;
1158 
1159  // copy some data from the client to the entity
1160  FetchClientEntData (ent);
1161 
1162  // clear entity values
1163  ent->groundentity = NULL;
1164  ent->client = &game.clients[index];
1165  ent->takedamage = DAMAGE_AIM;
1166  ent->movetype = MOVETYPE_WALK;
1167  ent->viewheight = 22;
1168  ent->inuse = true;
1169  ent->classname = "player";
1170  ent->mass = 200;
1171  ent->solid = SOLID_BBOX;
1172  ent->deadflag = DEAD_NO;
1173  ent->air_finished = level.time + 12;
1174  ent->clipmask = MASK_PLAYERSOLID;
1175  ent->model = "players/male/tris.md2";
1176  ent->pain = player_pain;
1177  ent->die = player_die;
1178  ent->waterlevel = 0;
1179  ent->watertype = 0;
1180  ent->flags &= ~FL_NO_KNOCKBACK;
1181  ent->svflags &= ~SVF_DEADMONSTER;
1182 
1183  VectorCopy (mins, ent->mins);
1184  VectorCopy (maxs, ent->maxs);
1185  VectorClear (ent->velocity);
1186 
1187  // clear playerstate values
1188  memset (&ent->client->ps, 0, sizeof(client->ps));
1189 
1190  client->ps.pmove.origin[0] = spawn_origin[0]*8;
1191  client->ps.pmove.origin[1] = spawn_origin[1]*8;
1192  client->ps.pmove.origin[2] = spawn_origin[2]*8;
1193 
1194  if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV))
1195  {
1196  client->ps.fov = 90;
1197  }
1198  else
1199  {
1200  client->ps.fov = atoi(Info_ValueForKey(client->pers.userinfo, "fov"));
1201  if (client->ps.fov < 1)
1202  client->ps.fov = 90;
1203  else if (client->ps.fov > 160)
1204  client->ps.fov = 160;
1205  }
1206 
1208 
1209  // clear entity state values
1210  ent->s.effects = 0;
1211  ent->s.modelindex = 255; // will use the skin specified model
1212  ent->s.modelindex2 = 255; // custom gun model
1213  // sknum is player num and weapon number
1214  // weapon number will be added in changeweapon
1215  ent->s.skinnum = ent - g_edicts - 1;
1216 
1217  ent->s.frame = 0;
1218  VectorCopy (spawn_origin, ent->s.origin);
1219  ent->s.origin[2] += 1; // make sure off ground
1220  VectorCopy (ent->s.origin, ent->s.old_origin);
1221 
1222  // set the delta angle
1223  for (i=0 ; i<3 ; i++)
1224  {
1225  client->ps.pmove.delta_angles[i] = ANGLE2SHORT(spawn_angles[i] - client->resp.cmd_angles[i]);
1226  }
1227 
1228  ent->s.angles[PITCH] = 0;
1229  ent->s.angles[YAW] = spawn_angles[YAW];
1230  ent->s.angles[ROLL] = 0;
1232  VectorCopy (ent->s.angles, client->v_angle);
1233 
1234  // spawn a spectator
1235  if (client->pers.spectator) {
1237 
1238  client->resp.spectator = true;
1239 
1240  ent->movetype = MOVETYPE_NOCLIP;
1241  ent->solid = SOLID_NOT;
1242  ent->svflags |= SVF_NOCLIENT;
1243  ent->client->ps.gunindex = 0;
1244  gi.linkentity (ent);
1245  return;
1246  } else
1247  client->resp.spectator = false;
1248 
1249  if (!KillBox (ent))
1250  { // could't spawn in?
1251  }
1252 
1253  gi.linkentity (ent);
1254 
1255  // force the current weapon up
1257  ChangeWeapon (ent);
1258 }
1259 
1260 /*
1261 =====================
1262 ClientBeginDeathmatch
1263 
1264 A client has just connected to the server in
1265 deathmatch mode, so clear everything out before starting them.
1266 =====================
1267 */
1269 {
1270  G_InitEdict (ent);
1271 
1272  InitClientResp (ent->client);
1273 
1274  // locate ent at a spawn point
1275  PutClientInServer (ent);
1276 
1277  if (level.intermissiontime)
1278  {
1280  }
1281  else
1282  {
1283  // send effect
1285  gi.WriteShort (ent-g_edicts);
1286  gi.WriteByte (MZ_LOGIN);
1287  gi.multicast (ent->s.origin, MULTICAST_PVS);
1288  }
1289 
1290  gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
1291 
1292  // make sure all view stuff is valid
1293  ClientEndServerFrame (ent);
1294 }
1295 
1296 
1297 /*
1298 ===========
1299 ClientBegin
1300 
1301 called when a client has finished connecting, and is ready
1302 to be placed into the game. This will happen every level load.
1303 ============
1304 */
1306 {
1307  int i;
1308 
1309  ent->client = game.clients + (ent - g_edicts - 1);
1310 
1311  if (deathmatch->value)
1312  {
1313  ClientBeginDeathmatch (ent);
1314  return;
1315  }
1316 
1317  // if there is already a body waiting for us (a loadgame), just
1318  // take it, otherwise spawn one from scratch
1319  if (ent->inuse == true)
1320  {
1321  // the client has cleared the client side viewangles upon
1322  // connecting to the server, which is different than the
1323  // state when the game is saved, so we need to compensate
1324  // with deltaangles
1325  for (i=0 ; i<3 ; i++)
1327  }
1328  else
1329  {
1330  // a spawn point will completely reinitialize the entity
1331  // except for the persistant data that was initialized at
1332  // ClientConnect() time
1333  G_InitEdict (ent);
1334  ent->classname = "player";
1335  InitClientResp (ent->client);
1336  PutClientInServer (ent);
1337  }
1338 
1339  if (level.intermissiontime)
1340  {
1342  }
1343  else
1344  {
1345  // send effect if in a multiplayer game
1346  if (game.maxclients > 1)
1347  {
1349  gi.WriteShort (ent-g_edicts);
1350  gi.WriteByte (MZ_LOGIN);
1351  gi.multicast (ent->s.origin, MULTICAST_PVS);
1352 
1353  gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
1354  }
1355  }
1356 
1357  // make sure all view stuff is valid
1358  ClientEndServerFrame (ent);
1359 }
1360 
1361 /*
1362 ===========
1363 ClientUserInfoChanged
1364 
1365 called whenever the player updates a userinfo variable.
1366 
1367 The game can override any of the settings in place
1368 (forcing skins or names, etc) before copying it off.
1369 ============
1370 */
1371 void ClientUserinfoChanged (edict_t *ent, char *userinfo)
1372 {
1373  char *s;
1374  int playernum;
1375 
1376  // check for malformed or illegal info strings
1377  if (!Info_Validate(userinfo))
1378  {
1379  strcpy (userinfo, "\\name\\badinfo\\skin\\male/grunt");
1380  }
1381 
1382  // set name
1383  s = Info_ValueForKey (userinfo, "name");
1384  strncpy (ent->client->pers.netname, s, sizeof(ent->client->pers.netname)-1);
1385 
1386  // set spectator
1387  s = Info_ValueForKey (userinfo, "spectator");
1388  // spectators are only supported in deathmatch
1389  if (deathmatch->value && *s && strcmp(s, "0"))
1390  ent->client->pers.spectator = true;
1391  else
1392  ent->client->pers.spectator = false;
1393 
1394  // set skin
1395  s = Info_ValueForKey (userinfo, "skin");
1396 
1397  playernum = ent-g_edicts-1;
1398 
1399  // combine name and skin into a configstring
1400  gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s", ent->client->pers.netname, s) );
1401 
1402  // fov
1403  if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV))
1404  {
1405  ent->client->ps.fov = 90;
1406  }
1407  else
1408  {
1409  ent->client->ps.fov = atoi(Info_ValueForKey(userinfo, "fov"));
1410  if (ent->client->ps.fov < 1)
1411  ent->client->ps.fov = 90;
1412  else if (ent->client->ps.fov > 160)
1413  ent->client->ps.fov = 160;
1414  }
1415 
1416  // handedness
1417  s = Info_ValueForKey (userinfo, "hand");
1418  if (strlen(s))
1419  {
1420  ent->client->pers.hand = atoi(s);
1421  }
1422 
1423  // save off the userinfo in case we want to check something later
1424  strncpy (ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo)-1);
1425 }
1426 
1427 
1428 /*
1429 ===========
1430 ClientConnect
1431 
1432 Called when a player begins connecting to the server.
1433 The game can refuse entrance to a client by returning false.
1434 If the client is allowed, the connection process will continue
1435 and eventually get to ClientBegin()
1436 Changing levels will NOT cause this to be called again, but
1437 loadgames will.
1438 ============
1439 */
1440 qboolean ClientConnect (edict_t *ent, char *userinfo)
1441 {
1442  char *value;
1443 
1444  // check to see if they are on the banned IP list
1445  value = Info_ValueForKey (userinfo, "ip");
1446  if (SV_FilterPacket(value)) {
1447  Info_SetValueForKey(userinfo, "rejmsg", "Banned.");
1448  return false;
1449  }
1450 
1451  // check for a spectator
1452  value = Info_ValueForKey (userinfo, "spectator");
1453  if (deathmatch->value && *value && strcmp(value, "0")) {
1454  int i, numspec;
1455 
1456  if (*spectator_password->string &&
1457  strcmp(spectator_password->string, "none") &&
1458  strcmp(spectator_password->string, value)) {
1459  Info_SetValueForKey(userinfo, "rejmsg", "Spectator password required or incorrect.");
1460  return false;
1461  }
1462 
1463  // count spectators
1464  for (i = numspec = 0; i < maxclients->value; i++)
1465  if (g_edicts[i+1].inuse && g_edicts[i+1].client->pers.spectator)
1466  numspec++;
1467 
1468  if (numspec >= maxspectators->value) {
1469  Info_SetValueForKey(userinfo, "rejmsg", "Server spectator limit is full.");
1470  return false;
1471  }
1472  } else {
1473  // check for a password
1474  value = Info_ValueForKey (userinfo, "password");
1475  if (*password->string && strcmp(password->string, "none") &&
1476  strcmp(password->string, value)) {
1477  Info_SetValueForKey(userinfo, "rejmsg", "Password required or incorrect.");
1478  return false;
1479  }
1480  }
1481 
1482 
1483  // they can connect
1484  ent->client = game.clients + (ent - g_edicts - 1);
1485 
1486  // if there is already a body waiting for us (a loadgame), just
1487  // take it, otherwise spawn one from scratch
1488  if (ent->inuse == false)
1489  {
1490  // clear the respawning variables
1491  InitClientResp (ent->client);
1492  if (!game.autosaved || !ent->client->pers.weapon)
1494  }
1495 
1496  ClientUserinfoChanged (ent, userinfo);
1497 
1498  if (game.maxclients > 1)
1499  gi.dprintf ("%s connected\n", ent->client->pers.netname);
1500 
1501  ent->svflags = 0; // make sure we start with known default
1502  ent->client->pers.connected = true;
1503  return true;
1504 }
1505 
1506 /*
1507 ===========
1508 ClientDisconnect
1509 
1510 Called when a player drops from the server.
1511 Will not be called between levels.
1512 ============
1513 */
1515 {
1516  int playernum;
1517 
1518  if (!ent->client)
1519  return;
1520 
1521  gi.bprintf (PRINT_HIGH, "%s disconnected\n", ent->client->pers.netname);
1522 
1523  // send effect
1525  gi.WriteShort (ent-g_edicts);
1527  gi.multicast (ent->s.origin, MULTICAST_PVS);
1528 
1529  gi.unlinkentity (ent);
1530  ent->s.modelindex = 0;
1531  ent->solid = SOLID_NOT;
1532  ent->inuse = false;
1533  ent->classname = "disconnected";
1534  ent->client->pers.connected = false;
1535 
1536  playernum = ent-g_edicts-1;
1537  gi.configstring (CS_PLAYERSKINS+playernum, "");
1538 }
1539 
1540 
1541 //==============================================================
1542 
1543 
1545 
1546 // pmove doesn't need to know about passent and contentmask
1548 {
1549  if (pm_passent->health > 0)
1550  return gi.trace (start, mins, maxs, end, pm_passent, MASK_PLAYERSOLID);
1551  else
1552  return gi.trace (start, mins, maxs, end, pm_passent, MASK_DEADSOLID);
1553 }
1554 
1555 unsigned CheckBlock (void *b, int c)
1556 {
1557  int v,i;
1558  v = 0;
1559  for (i=0 ; i<c ; i++)
1560  v+= ((byte *)b)[i];
1561  return v;
1562 }
1564 {
1565  unsigned c1, c2;
1566 
1567  c1 = CheckBlock (&pm->s, sizeof(pm->s));
1568  c2 = CheckBlock (&pm->cmd, sizeof(pm->cmd));
1569  Com_Printf ("sv %3i:%i %i\n", pm->cmd.impulse, c1, c2);
1570 }
1571 
1572 /*
1573 ==============
1574 ClientThink
1575 
1576 This will be called once for each client frame, which will
1577 usually be a couple times for each server frame.
1578 ==============
1579 */
1580 void ClientThink (edict_t *ent, usercmd_t *ucmd)
1581 {
1582  gclient_t *client;
1583  edict_t *other;
1584  int i, j;
1585  pmove_t pm;
1586 
1587  level.current_entity = ent;
1588  client = ent->client;
1589 
1590  if (level.intermissiontime)
1591  {
1593  // can exit intermission after five seconds
1594  if (level.time > level.intermissiontime + 5.0
1595  && (ucmd->buttons & BUTTON_ANY) )
1596  level.exitintermission = true;
1597  return;
1598  }
1599 
1600  pm_passent = ent;
1601 
1602  if (ent->client->chase_target) {
1603 
1604  client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
1605  client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
1606  client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);
1607 
1608  } else {
1609 
1610  // set up for pmove
1611  memset (&pm, 0, sizeof(pm));
1612 
1613  if (ent->movetype == MOVETYPE_NOCLIP)
1615  else if (ent->s.modelindex != 255)
1617  else if (ent->deadflag)
1619  else
1621 
1623  pm.s = client->ps.pmove;
1624 
1625  for (i=0 ; i<3 ; i++)
1626  {
1627  pm.s.origin[i] = ent->s.origin[i]*8;
1628  pm.s.velocity[i] = ent->velocity[i]*8;
1629  }
1630 
1631  if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s)))
1632  {
1633  pm.snapinitial = true;
1634  // gi.dprintf ("pmove changed!\n");
1635  }
1636 
1637  pm.cmd = *ucmd;
1638 
1639  pm.trace = PM_trace; // adds default parms
1641 
1642  // perform a pmove
1643  gi.Pmove (&pm);
1644 
1645  // save results of pmove
1646  client->ps.pmove = pm.s;
1647  client->old_pmove = pm.s;
1648 
1649  for (i=0 ; i<3 ; i++)
1650  {
1651  ent->s.origin[i] = pm.s.origin[i]*0.125;
1652  ent->velocity[i] = pm.s.velocity[i]*0.125;
1653  }
1654 
1655  VectorCopy (pm.mins, ent->mins);
1656  VectorCopy (pm.maxs, ent->maxs);
1657 
1658  client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
1659  client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
1660  client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);
1661 
1662  if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0))
1663  {
1664  gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
1665  PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
1666  }
1667 
1668  ent->viewheight = pm.viewheight;
1669  ent->waterlevel = pm.waterlevel;
1670  ent->watertype = pm.watertype;
1671  ent->groundentity = pm.groundentity;
1672  if (pm.groundentity)
1674 
1675  if (ent->deadflag)
1676  {
1677  client->ps.viewangles[ROLL] = 40;
1678  client->ps.viewangles[PITCH] = -15;
1680  }
1681  else
1682  {
1685  }
1686 
1687  gi.linkentity (ent);
1688 
1689  if (ent->movetype != MOVETYPE_NOCLIP)
1690  G_TouchTriggers (ent);
1691 
1692  // touch other objects
1693  for (i=0 ; i<pm.numtouch ; i++)
1694  {
1695  other = pm.touchents[i];
1696  for (j=0 ; j<i ; j++)
1697  if (pm.touchents[j] == other)
1698  break;
1699  if (j != i)
1700  continue; // duplicated
1701  if (!other->touch)
1702  continue;
1703  other->touch (other, ent, NULL, NULL);
1704  }
1705 
1706  }
1707 
1709  client->buttons = ucmd->buttons;
1711 
1712  // save light level the player is standing on for
1713  // monster sighting AI
1714  ent->light_level = ucmd->lightlevel;
1715 
1716  // fire weapon from final position if needed
1718  {
1719  if (client->resp.spectator) {
1720 
1721  client->latched_buttons = 0;
1722 
1723  if (client->chase_target) {
1726  } else
1727  GetChaseTarget(ent);
1728 
1729  } else if (!client->weapon_thunk) {
1730  client->weapon_thunk = true;
1731  Think_Weapon (ent);
1732  }
1733  }
1734 
1735  if (client->resp.spectator) {
1736  if (ucmd->upmove >= 10) {
1737  if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) {
1739  if (client->chase_target)
1740  ChaseNext(ent);
1741  else
1742  GetChaseTarget(ent);
1743  }
1744  } else
1746  }
1747 
1748  // update chase cam if being followed
1749  for (i = 1; i <= maxclients->value; i++) {
1750  other = g_edicts + i;
1751  if (other->inuse && other->client->chase_target == ent)
1752  UpdateChaseCam(other);
1753  }
1754 }
1755 
1756 
1757 /*
1758 ==============
1759 ClientBeginServerFrame
1760 
1761 This will be called once for each server frame, before running
1762 any other entities in the world.
1763 ==============
1764 */
1766 {
1767  gclient_t *client;
1768  int buttonMask;
1769 
1770  if (level.intermissiontime)
1771  return;
1772 
1773  client = ent->client;
1774 
1775  if (deathmatch->value &&
1777  (level.time - client->respawn_time) >= 5) {
1778  spectator_respawn(ent);
1779  return;
1780  }
1781 
1782  // run weapon animations if it hasn't been done by a ucmd_t
1784  Think_Weapon (ent);
1785  else
1786  client->weapon_thunk = false;
1787 
1788  if (ent->deadflag)
1789  {
1790  // wait for any button just going down
1791  if ( level.time > client->respawn_time)
1792  {
1793  // in deathmatch, only wait for attack button
1794  if (deathmatch->value)
1795  buttonMask = BUTTON_ATTACK;
1796  else
1797  buttonMask = -1;
1798 
1799  if ( ( client->latched_buttons & buttonMask ) ||
1800  (deathmatch->value && ((int)dmflags->value & DF_FORCE_RESPAWN) ) )
1801  {
1802  respawn(ent);
1803  client->latched_buttons = 0;
1804  }
1805  }
1806  return;
1807  }
1808 
1809  // add player trail so monsters can follow
1810  if (!deathmatch->value)
1811  if (!visible (ent, PlayerTrail_LastSpot() ) )
1812  PlayerTrail_Add (ent->s.old_origin);
1813 
1814  client->latched_buttons = 0;
1815 }
FindItem
gitem_t * FindItem(char *pickup_name)
Definition: g_items.c:100
entity_state_s::old_origin
vec3_t old_origin
Definition: q_shared.h:1151
gi
game_import_t gi
Definition: g_main.c:25
UpdateChaseCam
void UpdateChaseCam(edict_t *ent)
Definition: g_chase.c:22
MZ_LOGIN
#define MZ_LOGIN
Definition: q_shared.h:641
game_import_t::dprintf
void(* dprintf)(char *fmt,...)
Definition: game.h:106
edict_s::s
entity_state_t s
Definition: g_local.h:970
spectator_respawn
void spectator_respawn(edict_t *ent)
Definition: p_client.c:1010
usercmd_s::lightlevel
byte lightlevel
Definition: q_shared.h:524
edict_s::groundentity
edict_t * groundentity
Definition: g_local.h:1079
SelectRandomDeathmatchSpawnPoint
edict_t * SelectRandomDeathmatchSpawnPoint(void)
Definition: p_client.c:733
MOD_TARGET_BLASTER
#define MOD_TARGET_BLASTER
Definition: g_local.h:502
FRAME_death201
#define FRAME_death201
Definition: m_actor.h:35
deathmatch
cvar_t * deathmatch
Definition: g_main.c:35
MoveClientToIntermission
void MoveClientToIntermission(edict_t *client)
Definition: p_hud.c:33
usercmd_s::impulse
byte impulse
Definition: q_shared.h:523
client_persistant_t::spectator
qboolean spectator
Definition: g_local.h:867
ClientConnect
qboolean ClientConnect(edict_t *ent, char *userinfo)
Definition: p_client.c:1440
client_persistant_t::selected_item
int selected_item
Definition: g_local.h:847
client_persistant_t::max_grenades
int max_grenades
Definition: g_local.h:854
value
GLfloat value
Definition: qgl_win.c:63
YAW
#define YAW
Definition: q_shared.h:73
DEAD_DEAD
#define DEAD_DEAD
Definition: g_local.h:115
Info_Validate
qboolean Info_Validate(char *s)
Definition: q_shared.c:1353
gclient_s::v_angle
vec3_t v_angle
Definition: g_local.h:927
game_import_t::trace
trace_t(* trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask)
Definition: game.h:128
edict_s::model
char * model
Definition: g_local.h:1004
MOD_BFG_BLAST
#define MOD_BFG_BLAST
Definition: g_local.h:482
G_Spawn
edict_t * G_Spawn(void)
Definition: g_utils.c:420
pm
pmove_t * pm
Definition: pmove.c:48
pmove_t::watertype
int watertype
Definition: q_shared.h:548
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
ThrowGib
void ThrowGib(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:135
VectorSubtract
#define VectorSubtract(a, b, c)
Definition: q_shared.h:163
SP_info_player_deathmatch
void SP_info_player_deathmatch(edict_t *self)
Definition: p_client.c:123
svc_muzzleflash
@ svc_muzzleflash
Definition: qcommon.h:225
entity_state_s::frame
int frame
Definition: q_shared.h:1154
ANIM_DEATH
#define ANIM_DEATH
Definition: g_local.h:828
edict_s::absmax
vec3_t absmax
Definition: g_local.h:991
EV_PLAYER_TELEPORT
@ EV_PLAYER_TELEPORT
Definition: q_shared.h:1137
Touch_Item
void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_items.c:761
FindItemByClassname
gitem_t * FindItemByClassname(char *classname)
Definition: g_items.c:77
game_import_t::multicast
void(* multicast)(vec3_t origin, multicast_t to)
Definition: game.h:144
maxclients
cvar_t * maxclients
Definition: g_main.c:44
SOLID_BBOX
@ SOLID_BBOX
Definition: game.h:37
m_player.h
MOD_GRENADE
#define MOD_GRENADE
Definition: g_local.h:475
client_persistant_t::connected
qboolean connected
Definition: g_local.h:839
BODY_QUEUE_SIZE
#define BODY_QUEUE_SIZE
Definition: g_local.h:84
FRAMETIME
#define FRAMETIME
Definition: g_local.h:75
client_persistant_t::helpchanged
int helpchanged
Definition: g_local.h:865
MOD_BOMB
#define MOD_BOMB
Definition: g_local.h:496
pmove_t::viewheight
float viewheight
Definition: q_shared.h:543
MOD_CHAINGUN
#define MOD_CHAINGUN
Definition: g_local.h:474
PMF_NO_PREDICTION
#define PMF_NO_PREDICTION
Definition: q_shared.h:487
PM_FREEZE
@ PM_FREEZE
Definition: q_shared.h:477
v
GLdouble v
Definition: qgl_win.c:143
gclient_s::buttons
int buttons
Definition: g_local.h:901
password
cvar_t * password
Definition: g_main.c:41
MOVETYPE_NOCLIP
@ MOVETYPE_NOCLIP
Definition: g_local.h:191
SP_misc_teleporter_dest
void SP_misc_teleporter_dest(edict_t *ent)
Definition: g_misc.c:1868
FRAME_crdeath5
#define FRAME_crdeath5
Definition: m_player.h:201
entity_state_s::origin
vec3_t origin
Definition: q_shared.h:1149
SP_info_player_start
void SP_info_player_start(edict_t *self)
Definition: p_client.c:108
client_respawn_t::coop_respawn
client_persistant_t coop_respawn
Definition: g_local.h:873
edict_s::linkcount
int linkcount
Definition: g_local.h:977
SVF_NOCLIENT
#define SVF_NOCLIENT
Definition: game.h:27
MOD_TRIGGER_HURT
#define MOD_TRIGGER_HURT
Definition: g_local.h:500
edict_s::air_finished
float air_finished
Definition: g_local.h:1033
MOD_FALLING
#define MOD_FALLING
Definition: g_local.h:491
FRAME_death101
#define FRAME_death101
Definition: m_actor.h:28
ITEM_INDEX
#define ITEM_INDEX(x)
Definition: g_local.h:616
MOD_SPLASH
#define MOD_SPLASH
Definition: g_local.h:498
SP_info_player_intermission
void SP_info_player_intermission(void)
Definition: p_client.c:171
FL_POWER_ARMOR
#define FL_POWER_ARMOR
Definition: g_local.h:71
MOD_TARGET_LASER
#define MOD_TARGET_LASER
Definition: g_local.h:499
cvar_s::string
char * string
Definition: q_shared.h:327
qboolean
qboolean
Definition: q_shared.h:63
edict_s::inuse
qboolean inuse
Definition: g_local.h:976
edict_s::targetname
char * targetname
Definition: g_local.h:1018
IsNeutral
qboolean IsNeutral(edict_t *ent)
Definition: p_client.c:198
trace_t
Definition: q_shared.h:453
pmove_state_t::gravity
short gravity
Definition: q_shared.h:502
VectorClear
#define VectorClear(a)
Definition: q_shared.h:166
i
int i
Definition: q_shared.c:305
G_TouchTriggers
void G_TouchTriggers(edict_t *ent)
Definition: g_utils.c:475
MOD_RAILGUN
#define MOD_RAILGUN
Definition: g_local.h:480
MOD_TELEFRAG
#define MOD_TELEFRAG
Definition: g_local.h:490
edict_s::max_health
int max_health
Definition: g_local.h:1058
G_Find
edict_t * G_Find(edict_t *from, int fieldofs, char *match)
Definition: g_utils.c:45
pmove_t::waterlevel
int waterlevel
Definition: q_shared.h:549
SV_FilterPacket
qboolean SV_FilterPacket(char *from)
Definition: g_svcmds.c:123
maxspectators
cvar_t * maxspectators
Definition: g_main.c:45
DAMAGE_YES
@ DAMAGE_YES
Definition: g_local.h:89
edict_s::client
struct gclient_s * client
Definition: g_local.h:971
game_import_t::sound
void(* sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs)
Definition: game.h:109
MASK_DEADSOLID
#define MASK_DEADSOLID
Definition: q_shared.h:397
SelectDeathmatchSpawnPoint
edict_t * SelectDeathmatchSpawnPoint(void)
Definition: p_client.c:822
PITCH
#define PITCH
Definition: q_shared.h:72
Think_Weapon
void Think_Weapon(edict_t *ent)
Definition: p_weapon.c:282
FOFS
#define FOFS(x)
Definition: g_local.h:510
ClientUserinfoChanged
void ClientUserinfoChanged(edict_t *ent, char *userinfo)
Definition: p_client.c:1371
MOD_HG_SPLASH
#define MOD_HG_SPLASH
Definition: g_local.h:485
client_respawn_t::spectator
qboolean spectator
Definition: g_local.h:878
CheckBlock
unsigned CheckBlock(void *b, int c)
Definition: p_client.c:1555
FL_NO_KNOCKBACK
#define FL_NO_KNOCKBACK
Definition: g_local.h:70
DF_SPAWN_FARTHEST
#define DF_SPAWN_FARTHEST
Definition: q_shared.h:1033
client_persistant_t::userinfo
char userinfo[MAX_INFO_STRING]
Definition: g_local.h:835
edict_s::mins
vec3_t mins
Definition: g_local.h:990
meansOfDeath
int meansOfDeath
Definition: g_main.c:31
range
GLsizei range
Definition: qgl_win.c:121
pmove_t::maxs
vec3_t maxs
Definition: q_shared.h:545
pmove_state_t::velocity
short velocity[3]
Definition: q_shared.h:499
client_persistant_t::max_slugs
int max_slugs
Definition: g_local.h:856
player_state_t::fov
float fov
Definition: q_shared.h:1192
MOD_SLIME
#define MOD_SLIME
Definition: g_local.h:487
M_PI
#define M_PI
Definition: q_shared.h:142
game_locals_t::spawnpoint
char spawnpoint[512]
Definition: g_local.h:283
FRAME_death301
#define FRAME_death301
Definition: m_actor.h:48
g_edicts
edict_t * g_edicts
Definition: g_main.c:33
ATTN_NORM
#define ATTN_NORM
Definition: q_shared.h:995
client_persistant_t::max_bullets
int max_bullets
Definition: g_local.h:851
edict_s::groundentity_linkcount
int groundentity_linkcount
Definition: g_local.h:1080
TossClientWeapon
void TossClientWeapon(edict_t *self)
Definition: p_client.c:410
DF_FORCE_RESPAWN
#define DF_FORCE_RESPAWN
Definition: q_shared.h:1034
itemlist
gitem_t itemlist[]
Definition: g_items.c:1134
DF_FIXED_FOV
#define DF_FIXED_FOV
Definition: q_shared.h:1039
BUTTON_ATTACK
#define BUTTON_ATTACK
Definition: q_shared.h:511
edict_s::movetype
int movetype
Definition: g_local.h:1001
client_persistant_t::inventory
int inventory[MAX_ITEMS]
Definition: g_local.h:848
MAX_INFO_STRING
#define MAX_INFO_STRING
Definition: q_shared.h:259
entity_state_s::effects
unsigned int effects
Definition: q_shared.h:1156
CopyToBodyQue
void CopyToBodyQue(edict_t *ent)
Definition: p_client.c:946
MOD_EXIT
#define MOD_EXIT
Definition: g_local.h:497
j
GLint j
Definition: qgl_win.c:150
IT_KEY
#define IT_KEY
Definition: g_local.h:220
G_InitEdict
void G_InitEdict(edict_t *e)
Definition: g_utils.c:401
gclient_s::pers
client_persistant_t pers
Definition: g_local.h:890
va
char * va(char *format,...)
Definition: q_shared.c:1050
client_persistant_t::max_shells
int max_shells
Definition: g_local.h:852
client_respawn_t::score
int score
Definition: g_local.h:875
SVF_DEADMONSTER
#define SVF_DEADMONSTER
Definition: game.h:28
ClientDisconnect
void ClientDisconnect(edict_t *ent)
Definition: p_client.c:1514
gclient_s::newweapon
gitem_t * newweapon
Definition: g_local.h:907
edict_s::message
char * message
Definition: g_local.h:1010
PM_GIB
@ PM_GIB
Definition: q_shared.h:476
edict_s::svflags
int svflags
Definition: g_local.h:989
SP_CreateCoopSpots
static void SP_CreateCoopSpots(edict_t *self)
Definition: p_client.c:70
CHAN_VOICE
#define CHAN_VOICE
Definition: q_shared.h:985
PMF_TIME_TELEPORT
#define PMF_TIME_TELEPORT
Definition: q_shared.h:486
edict_s::item
gitem_t * item
Definition: g_local.h:1110
gclient_s::weapon_thunk
qboolean weapon_thunk
Definition: g_local.h:905
edict_s::classname
char * classname
Definition: g_local.h:1011
pmove_t::trace
trace_t(* trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
Definition: q_shared.h:552
edict_s
Definition: g_local.h:968
MOD_EXPLOSIVE
#define MOD_EXPLOSIVE
Definition: g_local.h:494
MOD_BFG_LASER
#define MOD_BFG_LASER
Definition: g_local.h:481
edict_s::mass
int mass
Definition: g_local.h:1032
PMF_JUMP_HELD
#define PMF_JUMP_HELD
Definition: q_shared.h:482
ClientThink
void ClientThink(edict_t *ent, usercmd_t *ucmd)
Definition: p_client.c:1580
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:452
pmove_state_t::pm_type
pmtype_t pm_type
Definition: q_shared.h:496
client_persistant_t::weapon
gitem_t * weapon
Definition: g_local.h:858
csurface_s
Definition: q_shared.h:439
edict_s::viewheight
int viewheight
Definition: g_local.h:1067
ROLL
#define ROLL
Definition: q_shared.h:74
DROPPED_PLAYER_ITEM
#define DROPPED_PLAYER_ITEM
Definition: g_local.h:564
game_locals_t::num_items
int num_items
Definition: g_local.h:293
client_persistant_t
Definition: g_local.h:833
pmove_t::groundentity
struct edict_s * groundentity
Definition: q_shared.h:547
MOD_HANDGRENADE
#define MOD_HANDGRENADE
Definition: g_local.h:484
game_import_t::configstring
void(* configstring)(int num, char *string)
Definition: game.h:116
player_state_t::viewangles
vec3_t viewangles
Definition: q_shared.h:1180
game_import_t::soundindex
int(* soundindex)(char *name)
Definition: game.h:122
edict_s::clipmask
int clipmask
Definition: g_local.h:993
edict_s::spawnflags
int spawnflags
Definition: g_local.h:1012
VectorLength
vec_t VectorLength(vec3_t v)
Definition: q_shared.c:762
player_state_t::pmove
pmove_state_t pmove
Definition: q_shared.h:1176
MOD_MACHINEGUN
#define MOD_MACHINEGUN
Definition: g_local.h:473
game_import_t::pointcontents
int(* pointcontents)(vec3_t point)
Definition: game.h:129
FL_GODMODE
#define FL_GODMODE
Definition: g_local.h:63
edict_s::owner
edict_t * owner
Definition: g_local.h:994
client_persistant_t::netname
char netname[16]
Definition: g_local.h:836
DF_QUAD_DROP
#define DF_QUAD_DROP
Definition: q_shared.h:1038
Info_ValueForKey
char * Info_ValueForKey(char *s, char *key)
Definition: q_shared.c:1253
game_import_t::modelindex
int(* modelindex)(char *name)
Definition: game.h:121
MZ_LOGOUT
#define MZ_LOGOUT
Definition: q_shared.h:642
GetChaseTarget
void GetChaseTarget(edict_t *ent)
Definition: g_chase.c:159
CS_PLAYERSKINS
#define CS_PLAYERSKINS
Definition: q_shared.h:1117
PlayerTrail_LastSpot
edict_t * PlayerTrail_LastSpot(void)
Definition: p_trail.c:143
edict_s::deadflag
int deadflag
Definition: g_local.h:1060
client_persistant_t::savedFlags
int savedFlags
Definition: g_local.h:845
BUTTON_ANY
#define BUTTON_ANY
Definition: q_shared.h:513
client_respawn_t::cmd_angles
vec3_t cmd_angles
Definition: g_local.h:876
player_pain
void player_pain(edict_t *self, edict_t *other, float kick, int damage)
Definition: p_client.c:179
respawn
void respawn(edict_t *self)
Definition: p_client.c:980
spectator_password
cvar_t * spectator_password
Definition: g_main.c:42
game_locals_t::clients
gclient_t * clients
Definition: g_local.h:279
PrintPmove
void PrintPmove(pmove_t *pm)
Definition: p_client.c:1563
edict_s::nextthink
float nextthink
Definition: g_local.h:1042
client_respawn_t
Definition: g_local.h:871
gclient_s::killer_yaw
float killer_yaw
Definition: g_local.h:917
cvar_s::value
float value
Definition: q_shared.h:331
game
game_locals_t game
Definition: g_main.c:23
FRAME_death106
#define FRAME_death106
Definition: m_actor.h:33
edict_s::think
void(* think)(edict_t *self)
Definition: g_local.h:1044
PM_trace
trace_t PM_trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
Definition: p_client.c:1547
PRINT_MEDIUM
#define PRINT_MEDIUM
Definition: q_shared.h:98
PRINT_HIGH
#define PRINT_HIGH
Definition: q_shared.h:99
MOD_G_SPLASH
#define MOD_G_SPLASH
Definition: g_local.h:476
pmove_state_t::delta_angles
short delta_angles[3]
Definition: q_shared.h:503
DAMAGE_NO
@ DAMAGE_NO
Definition: g_local.h:88
FL_NOTARGET
#define FL_NOTARGET
Definition: g_local.h:64
FRAME_death206
#define FRAME_death206
Definition: m_actor.h:40
pm_passent
edict_t * pm_passent
Definition: p_client.c:1544
gitem_s::pickup_name
char * pickup_name
Definition: g_local.h:250
gclient_s::ps
player_state_t ps
Definition: g_local.h:886
edict_s::watertype
int watertype
Definition: g_local.h:1099
entity_state_s::number
int number
Definition: q_shared.h:1147
NULL
#define NULL
Definition: q_shared.h:67
edict_s::solid
solid_t solid
Definition: g_local.h:992
MOD_R_SPLASH
#define MOD_R_SPLASH
Definition: g_local.h:478
pmove_t::touchents
struct edict_s * touchents[MAXTOUCH]
Definition: q_shared.h:540
body_die
void body_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: p_client.c:931
player_die
void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: p_client.c:501
pmove_t::numtouch
int numtouch
Definition: q_shared.h:539
MOVETYPE_WALK
@ MOVETYPE_WALK
Definition: g_local.h:195
MOD_BARREL
#define MOD_BARREL
Definition: g_local.h:495
PM_DEAD
@ PM_DEAD
Definition: q_shared.h:475
MOD_SHOTGUN
#define MOD_SHOTGUN
Definition: g_local.h:471
Q_stricmp
int Q_stricmp(char *s1, char *s2)
Definition: q_shared.c:1180
usercmd_s::upmove
short upmove
Definition: q_shared.h:522
SOLID_NOT
@ SOLID_NOT
Definition: game.h:35
SP_info_player_coop
void SP_info_player_coop(edict_t *self)
Definition: p_client.c:137
edict_s::pain
void(* pain)(edict_t *self, edict_t *other, float kick, int damage)
Definition: g_local.h:1048
client_respawn_t::enterframe
int enterframe
Definition: g_local.h:874
game_import_t::Pmove
void(* Pmove)(pmove_t *pmove)
Definition: game.h:141
edict_s::velocity
vec3_t velocity
Definition: g_local.h:1030
IsFemale
qboolean IsFemale(edict_t *ent)
Definition: p_client.c:185
MOD_CRUSH
#define MOD_CRUSH
Definition: g_local.h:489
ClientObituary
void ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker)
Definition: p_client.c:211
game_import_t::unlinkentity
void(* unlinkentity)(edict_t *ent)
Definition: game.h:139
s
static fixed16_t s
Definition: r_scan.c:30
game_locals_t::autosaved
qboolean autosaved
Definition: g_local.h:295
DEAD_NO
#define DEAD_NO
Definition: g_local.h:113
game_import_t::WriteShort
void(* WriteShort)(int c)
Definition: game.h:148
FetchClientEntData
void FetchClientEntData(edict_t *ent)
Definition: p_client.c:668
ClientBegin
void ClientBegin(edict_t *ent)
Definition: p_client.c:1305
Cmd_Help_f
void Cmd_Help_f(edict_t *ent)
Definition: p_hud.c:347
game_import_t::error
void(* error)(char *fmt,...)
Definition: game.h:118
entity_state_s::skinnum
int skinnum
Definition: q_shared.h:1155
Info_SetValueForKey
void Info_SetValueForKey(char *s, char *key, char *value)
Definition: q_shared.c:1362
SelectFarthestDeathmatchSpawnPoint
edict_t * SelectFarthestDeathmatchSpawnPoint(void)
Definition: p_client.c:789
edict_s::light_level
int light_level
Definition: g_local.h:1106
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:165
coop
cvar_t * coop
Definition: g_main.c:36
FRAME_crdeath1
#define FRAME_crdeath1
Definition: m_player.h:197
PM_SPECTATOR
@ PM_SPECTATOR
Definition: q_shared.h:473
game_import_t::AddCommandString
void(* AddCommandString)(char *text)
Definition: game.h:173
game_import_t::cprintf
void(* cprintf)(edict_t *ent, int printlevel, char *fmt,...)
Definition: game.h:107
game_import_t::unicast
void(* unicast)(edict_t *ent, qboolean reliable)
Definition: game.h:145
client_persistant_t::max_rockets
int max_rockets
Definition: g_local.h:853
visible
qboolean visible(edict_t *self, edict_t *other)
Definition: g_ai.c:287
ThrowClientHead
void ThrowClientHead(edict_t *self, int damage)
Definition: g_misc.c:229
MOD_BLASTER
#define MOD_BLASTER
Definition: g_local.h:470
usercmd_s
Definition: q_shared.h:517
DAMAGE_AIM
@ DAMAGE_AIM
Definition: g_local.h:90
world
#define world
Definition: g_local.h:556
PNOISE_SELF
#define PNOISE_SELF
Definition: g_local.h:182
ClientEndServerFrame
void ClientEndServerFrame(edict_t *ent)
Definition: p_view.c:958
gclient_s::oldbuttons
int oldbuttons
Definition: g_local.h:902
game_import_t::WriteByte
void(* WriteByte)(int c)
Definition: game.h:147
MOD_HELD_GRENADE
#define MOD_HELD_GRENADE
Definition: g_local.h:493
edict_s::takedamage
int takedamage
Definition: g_local.h:1068
level
GLint level
Definition: qgl_win.c:116
SHORT2ANGLE
#define SHORT2ANGLE(x)
Definition: q_shared.h:1093
gclient_s::old_pmove
pmove_state_t old_pmove
Definition: g_local.h:892
edict_s::flags
int flags
Definition: g_local.h:1002
Drop_Item
edict_t * Drop_Item(edict_t *ent, gitem_t *item)
Definition: g_items.c:843
usercmd_s::angles
short angles[3]
Definition: q_shared.h:521
GIB_ORGANIC
#define GIB_ORGANIC
Definition: g_local.h:125
client_persistant_t::game_helpchanged
int game_helpchanged
Definition: g_local.h:864
pmove_t::s
pmove_state_t s
Definition: q_shared.h:532
ChaseNext
void ChaseNext(edict_t *ent)
Definition: g_chase.c:111
pmove_t::cmd
usercmd_t cmd
Definition: q_shared.h:535
MOD_BFG_EFFECT
#define MOD_BFG_EFFECT
Definition: g_local.h:483
LookAtKiller
void LookAtKiller(edict_t *self, edict_t *inflictor, edict_t *attacker)
Definition: p_client.c:463
edict_s::maxs
vec3_t maxs
Definition: g_local.h:990
MOD_HYPERBLASTER
#define MOD_HYPERBLASTER
Definition: g_local.h:479
PlayerNoise
void PlayerNoise(edict_t *who, vec3_t where, int type)
Definition: p_weapon.c:58
PMF_DUCKED
#define PMF_DUCKED
Definition: q_shared.h:481
SelectSpawnPoint
void SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles)
Definition: p_client.c:875
entity_state_s::modelindex
int modelindex
Definition: q_shared.h:1152
entity_state_s::modelindex2
int modelindex2
Definition: q_shared.h:1153
SP_FixCoopSpots
static void SP_FixCoopSpots(edict_t *self)
Definition: p_client.c:39
pmove_t::mins
vec3_t mins
Definition: q_shared.h:545
KillBox
qboolean KillBox(edict_t *ent)
Definition: g_utils.c:549
edict_s::touch
void(* touch)(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_local.h:1046
PutClientInServer
void PutClientInServer(edict_t *ent)
Definition: p_client.c:1097
usercmd_s::buttons
byte buttons
Definition: q_shared.h:520
ClientBeginServerFrame
void ClientBeginServerFrame(edict_t *ent)
Definition: p_client.c:1765
gclient_s::chase_target
edict_t * chase_target
Definition: g_local.h:963
sv_gravity
cvar_t * sv_gravity
Definition: g_main.c:53
pmove_state_t::origin
short origin[3]
Definition: q_shared.h:498
gclient_s::respawn_time
float respawn_time
Definition: g_local.h:961
FRAME_death308
#define FRAME_death308
Definition: m_actor.h:55
MOVETYPE_TOSS
@ MOVETYPE_TOSS
Definition: g_local.h:198
ChangeWeapon
void ChangeWeapon(edict_t *ent)
Definition: p_weapon.c:174
MOD_ROCKET
#define MOD_ROCKET
Definition: g_local.h:477
Com_Printf
void Com_Printf(char *fmt,...)
Definition: common.c:104
ANGLE2SHORT
#define ANGLE2SHORT(x)
Definition: q_shared.h:1092
PM_NORMAL
@ PM_NORMAL
Definition: q_shared.h:472
pmove_t::viewangles
vec3_t viewangles
Definition: q_shared.h:542
dmflags
cvar_t * dmflags
Definition: g_main.c:37
edict_s::waterlevel
int waterlevel
Definition: g_local.h:1100
client_persistant_t::hand
int hand
Definition: g_local.h:837
CHAN_BODY
#define CHAN_BODY
Definition: q_shared.h:987
client_persistant_t::max_cells
int max_cells
Definition: g_local.h:855
client_persistant_t::max_health
int max_health
Definition: g_local.h:844
InitBodyQue
void InitBodyQue(void)
Definition: p_client.c:918
gitem_s::view_model
char * view_model
Definition: g_local.h:246
cplane_s
Definition: q_shared.h:413
gclient_s
Definition: g_local.h:883
InitClientResp
void InitClientResp(gclient_t *client)
Definition: p_client.c:633
game_import_t::linkentity
void(* linkentity)(edict_t *ent)
Definition: game.h:138
edict_s::size
vec3_t size
Definition: g_local.h:991
SaveClientData
void SaveClientData(void)
Definition: p_client.c:650
MASK_PLAYERSOLID
#define MASK_PLAYERSOLID
Definition: q_shared.h:396
PlayerTrail_Add
void PlayerTrail_Add(vec3_t spot)
Definition: p_trail.c:67
pmove_t::pointcontents
int(* pointcontents)(vec3_t point)
Definition: q_shared.h:553
player_state_t::gunindex
int gunindex
Definition: q_shared.h:1187
ClientBeginDeathmatch
void ClientBeginDeathmatch(edict_t *ent)
Definition: p_client.c:1268
svc_stufftext
@ svc_stufftext
Definition: qcommon.h:237
gclient_s::latched_buttons
int latched_buttons
Definition: g_local.h:903
entity_state_s::angles
vec3_t angles
Definition: q_shared.h:1150
pmove_state_t::pm_flags
byte pm_flags
Definition: q_shared.h:500
client_persistant_t::score
int score
Definition: g_local.h:862
game_import_t::WriteString
void(* WriteString)(char *s)
Definition: game.h:151
PlayersRangeFromSpot
float PlayersRangeFromSpot(edict_t *spot)
Definition: p_client.c:694
gitem_s::flags
int flags
Definition: g_local.h:255
edict_s::die
void(* die)(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_local.h:1049
MOD_SUICIDE
#define MOD_SUICIDE
Definition: g_local.h:492
MULTICAST_PVS
@ MULTICAST_PVS
Definition: q_shared.h:118
pmove_t::snapinitial
qboolean snapinitial
Definition: q_shared.h:536
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:134
MOD_LAVA
#define MOD_LAVA
Definition: g_local.h:488
MOD_WATER
#define MOD_WATER
Definition: g_local.h:486
edict_s::absmin
vec3_t absmin
Definition: g_local.h:991
pmove_t
Definition: q_shared.h:529
InitClientPersistant
void InitClientPersistant(gclient_t *client)
Definition: p_client.c:607
edict_s::target
char * target
Definition: g_local.h:1017
MOD_FRIENDLY_FIRE
#define MOD_FRIENDLY_FIRE
Definition: g_local.h:503
pmove_state_t::pm_time
byte pm_time
Definition: q_shared.h:501
client_persistant_t::health
int health
Definition: g_local.h:843
count
GLint GLsizei count
Definition: qgl_win.c:128
MOD_SSHOTGUN
#define MOD_SSHOTGUN
Definition: g_local.h:472
SelectCoopSpawnPoint
edict_t * SelectCoopSpawnPoint(edict_t *ent)
Definition: p_client.c:831
gclient_s::resp
client_respawn_t resp
Definition: g_local.h:891
g_local.h
edict_s::health
int health
Definition: g_local.h:1057
gitem_s
Definition: g_local.h:236
game_import_t::bprintf
void(* bprintf)(int printlevel, char *fmt,...)
Definition: game.h:105
game_locals_t::maxclients
int maxclients
Definition: g_local.h:286