icculus quake2 doxygen  1.0 dev
g_misc.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 // g_misc.c
21 
22 #include "g_local.h"
23 
24 
25 /*QUAKED func_group (0 0 0) ?
26 Used to group brushes together just for editor convenience.
27 */
28 
29 //=====================================================
30 
31 void Use_Areaportal (edict_t *ent, edict_t *other, edict_t *activator)
32 {
33  ent->count ^= 1; // toggle state
34 // gi.dprintf ("portalstate: %i = %i\n", ent->style, ent->count);
35  gi.SetAreaPortalState (ent->style, ent->count);
36 }
37 
38 /*QUAKED func_areaportal (0 0 0) ?
39 
40 This is a non-visible object that divides the world into
41 areas that are seperated when this portal is not activated.
42 Usually enclosed in the middle of a door.
43 */
45 {
46  ent->use = Use_Areaportal;
47  ent->count = 0; // always start closed;
48 }
49 
50 //=====================================================
51 
52 
53 /*
54 =================
55 Misc functions
56 =================
57 */
58 void VelocityForDamage (int damage, vec3_t v)
59 {
60  v[0] = 100.0 * crandom();
61  v[1] = 100.0 * crandom();
62  v[2] = 200.0 + 100.0 * random();
63 
64  if (damage < 50)
65  VectorScale (v, 0.7, v);
66  else
67  VectorScale (v, 1.2, v);
68 }
69 
71 {
72  if (ent->velocity[0] < -300)
73  ent->velocity[0] = -300;
74  else if (ent->velocity[0] > 300)
75  ent->velocity[0] = 300;
76  if (ent->velocity[1] < -300)
77  ent->velocity[1] = -300;
78  else if (ent->velocity[1] > 300)
79  ent->velocity[1] = 300;
80  if (ent->velocity[2] < 200)
81  ent->velocity[2] = 200; // always some upwards
82  else if (ent->velocity[2] > 500)
83  ent->velocity[2] = 500;
84 }
85 
86 
87 /*
88 =================
89 gibs
90 =================
91 */
92 void gib_think (edict_t *self)
93 {
94  self->s.frame++;
95  self->nextthink = level.time + FRAMETIME;
96 
97  if (self->s.frame == 10)
98  {
99  self->think = G_FreeEdict;
100  self->nextthink = level.time + 8 + random()*10;
101  }
102 }
103 
104 void gib_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
105 {
106  vec3_t normal_angles, right;
107 
108  if (!self->groundentity)
109  return;
110 
111  self->touch = NULL;
112 
113  if (plane)
114  {
115  gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/fhit3.wav"), 1, ATTN_NORM, 0);
116 
117  vectoangles (plane->normal, normal_angles);
118  AngleVectors (normal_angles, NULL, right, NULL);
119  vectoangles (right, self->s.angles);
120 
121  if (self->s.modelindex == sm_meat_index)
122  {
123  self->s.frame++;
124  self->think = gib_think;
125  self->nextthink = level.time + FRAMETIME;
126  }
127  }
128 }
129 
130 void gib_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
131 {
132  G_FreeEdict (self);
133 }
134 
135 void ThrowGib (edict_t *self, char *gibname, int damage, int type)
136 {
137  edict_t *gib;
138  vec3_t vd;
139  vec3_t origin;
140  vec3_t size;
141  float vscale;
142 
143  gib = G_Spawn();
144 
145  VectorScale (self->size, 0.5, size);
146  VectorAdd (self->absmin, size, origin);
147  gib->s.origin[0] = origin[0] + crandom() * size[0];
148  gib->s.origin[1] = origin[1] + crandom() * size[1];
149  gib->s.origin[2] = origin[2] + crandom() * size[2];
150 
151  gi.setmodel (gib, gibname);
152  gib->solid = SOLID_NOT;
153  gib->s.effects |= EF_GIB;
154  gib->flags |= FL_NO_KNOCKBACK;
155  gib->takedamage = DAMAGE_YES;
156  gib->die = gib_die;
157 
158  if (type == GIB_ORGANIC)
159  {
160  gib->movetype = MOVETYPE_TOSS;
161  gib->touch = gib_touch;
162  vscale = 0.5;
163  }
164  else
165  {
166  gib->movetype = MOVETYPE_BOUNCE;
167  vscale = 1.0;
168  }
169 
170  VelocityForDamage (damage, vd);
171  VectorMA (self->velocity, vscale, vd, gib->velocity);
172  ClipGibVelocity (gib);
173  gib->avelocity[0] = random()*600;
174  gib->avelocity[1] = random()*600;
175  gib->avelocity[2] = random()*600;
176 
177  gib->think = G_FreeEdict;
178  gib->nextthink = level.time + 10 + random()*10;
179 
180  gi.linkentity (gib);
181 }
182 
183 void ThrowHead (edict_t *self, char *gibname, int damage, int type)
184 {
185  vec3_t vd;
186  float vscale;
187 
188  self->s.skinnum = 0;
189  self->s.frame = 0;
190  VectorClear (self->mins);
191  VectorClear (self->maxs);
192 
193  self->s.modelindex2 = 0;
194  gi.setmodel (self, gibname);
195  self->solid = SOLID_NOT;
196  self->s.effects |= EF_GIB;
197  self->s.effects &= ~EF_FLIES;
198  self->s.sound = 0;
199  self->flags |= FL_NO_KNOCKBACK;
200  self->svflags &= ~SVF_MONSTER;
201  self->takedamage = DAMAGE_YES;
202  self->die = gib_die;
203 
204  if (type == GIB_ORGANIC)
205  {
206  self->movetype = MOVETYPE_TOSS;
207  self->touch = gib_touch;
208  vscale = 0.5;
209  }
210  else
211  {
212  self->movetype = MOVETYPE_BOUNCE;
213  vscale = 1.0;
214  }
215 
216  VelocityForDamage (damage, vd);
217  VectorMA (self->velocity, vscale, vd, self->velocity);
218  ClipGibVelocity (self);
219 
220  self->avelocity[YAW] = crandom()*600;
221 
222  self->think = G_FreeEdict;
223  self->nextthink = level.time + 10 + random()*10;
224 
225  gi.linkentity (self);
226 }
227 
228 
229 void ThrowClientHead (edict_t *self, int damage)
230 {
231  vec3_t vd;
232  char *gibname;
233 
234  if (rand()&1)
235  {
236  gibname = "models/objects/gibs/head2/tris.md2";
237  self->s.skinnum = 1; // second skin is player
238  }
239  else
240  {
241  gibname = "models/objects/gibs/skull/tris.md2";
242  self->s.skinnum = 0;
243  }
244 
245  self->s.origin[2] += 32;
246  self->s.frame = 0;
247  gi.setmodel (self, gibname);
248  VectorSet (self->mins, -16, -16, 0);
249  VectorSet (self->maxs, 16, 16, 16);
250 
251  self->takedamage = DAMAGE_NO;
252  self->solid = SOLID_NOT;
253  self->s.effects = EF_GIB;
254  self->s.sound = 0;
255  self->flags |= FL_NO_KNOCKBACK;
256 
257  self->movetype = MOVETYPE_BOUNCE;
258  VelocityForDamage (damage, vd);
259  VectorAdd (self->velocity, vd, self->velocity);
260 
261  if (self->client) // bodies in the queue don't have a client anymore
262  {
263  self->client->anim_priority = ANIM_DEATH;
264  self->client->anim_end = self->s.frame;
265  }
266  else
267  {
268  self->think = NULL;
269  self->nextthink = 0;
270  }
271 
272  gi.linkentity (self);
273 }
274 
275 
276 /*
277 =================
278 debris
279 =================
280 */
281 void debris_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
282 {
283  G_FreeEdict (self);
284 }
285 
286 void ThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin)
287 {
288  edict_t *chunk;
289  vec3_t v;
290 
291  chunk = G_Spawn();
292  VectorCopy (origin, chunk->s.origin);
293  gi.setmodel (chunk, modelname);
294  v[0] = 100 * crandom();
295  v[1] = 100 * crandom();
296  v[2] = 100 + 100 * crandom();
297  VectorMA (self->velocity, speed, v, chunk->velocity);
298  chunk->movetype = MOVETYPE_BOUNCE;
299  chunk->solid = SOLID_NOT;
300  chunk->avelocity[0] = random()*600;
301  chunk->avelocity[1] = random()*600;
302  chunk->avelocity[2] = random()*600;
303  chunk->think = G_FreeEdict;
304  chunk->nextthink = level.time + 5 + random()*5;
305  chunk->s.frame = 0;
306  chunk->flags = 0;
307  chunk->classname = "debris";
308  chunk->takedamage = DAMAGE_YES;
309  chunk->die = debris_die;
310  gi.linkentity (chunk);
311 }
312 
313 
315 {
318  gi.WritePosition (self->s.origin);
319  gi.multicast (self->s.origin, MULTICAST_PVS);
320 
321  G_FreeEdict (self);
322 }
323 
324 
326 {
329  gi.WritePosition (self->s.origin);
330  gi.multicast (self->s.origin, MULTICAST_PVS);
331 
332  G_FreeEdict (self);
333 }
334 
335 
336 /*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORT
337 Target: next path corner
338 Pathtarget: gets used when an entity that has
339  this path_corner targeted touches it
340 */
341 
342 void path_corner_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
343 {
344  vec3_t v;
345  edict_t *next;
346 
347  if (other->movetarget != self)
348  return;
349 
350  if (other->enemy)
351  return;
352 
353  if (self->pathtarget)
354  {
355  char *savetarget;
356 
357  savetarget = self->target;
358  self->target = self->pathtarget;
359  G_UseTargets (self, other);
360  self->target = savetarget;
361  }
362 
363  if (self->target)
364  next = G_PickTarget(self->target);
365  else
366  next = NULL;
367 
368  if ((next) && (next->spawnflags & 1))
369  {
370  VectorCopy (next->s.origin, v);
371  v[2] += next->mins[2];
372  v[2] -= other->mins[2];
373  VectorCopy (v, other->s.origin);
374  next = G_PickTarget(next->target);
375  other->s.event = EV_OTHER_TELEPORT;
376  }
377 
378  other->goalentity = other->movetarget = next;
379 
380  if (self->wait)
381  {
382  other->monsterinfo.pausetime = level.time + self->wait;
383  other->monsterinfo.stand (other);
384  return;
385  }
386 
387  if (!other->movetarget)
388  {
389  other->monsterinfo.pausetime = level.time + 100000000;
390  other->monsterinfo.stand (other);
391  }
392  else
393  {
394  VectorSubtract (other->goalentity->s.origin, other->s.origin, v);
395  other->ideal_yaw = vectoyaw (v);
396  }
397 }
398 
400 {
401  if (!self->targetname)
402  {
403  gi.dprintf ("path_corner with no targetname at %s\n", vtos(self->s.origin));
404  G_FreeEdict (self);
405  return;
406  }
407 
408  self->solid = SOLID_TRIGGER;
409  self->touch = path_corner_touch;
410  VectorSet (self->mins, -8, -8, -8);
411  VectorSet (self->maxs, 8, 8, 8);
412  self->svflags |= SVF_NOCLIENT;
413  gi.linkentity (self);
414 }
415 
416 
417 /*QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold
418 Makes this the target of a monster and it will head here
419 when first activated before going after the activator. If
420 hold is selected, it will stay here.
421 */
422 void point_combat_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
423 {
424  edict_t *activator;
425 
426  if (other->movetarget != self)
427  return;
428 
429  if (self->target)
430  {
431  other->target = self->target;
432  other->goalentity = other->movetarget = G_PickTarget(other->target);
433  if (!other->goalentity)
434  {
435  gi.dprintf("%s at %s target %s does not exist\n", self->classname, vtos(self->s.origin), self->target);
436  other->movetarget = self;
437  }
438  self->target = NULL;
439  }
440  else if ((self->spawnflags & 1) && !(other->flags & (FL_SWIM|FL_FLY)))
441  {
442  other->monsterinfo.pausetime = level.time + 100000000;
444  other->monsterinfo.stand (other);
445  }
446 
447  if (other->movetarget == self)
448  {
449  other->target = NULL;
450  other->movetarget = NULL;
451  other->goalentity = other->enemy;
453  }
454 
455  if (self->pathtarget)
456  {
457  char *savetarget;
458 
459  savetarget = self->target;
460  self->target = self->pathtarget;
461  if (other->enemy && other->enemy->client)
462  activator = other->enemy;
463  else if (other->oldenemy && other->oldenemy->client)
464  activator = other->oldenemy;
465  else if (other->activator && other->activator->client)
466  activator = other->activator;
467  else
468  activator = other;
469  G_UseTargets (self, activator);
470  self->target = savetarget;
471  }
472 }
473 
475 {
476  if (deathmatch->value)
477  {
478  G_FreeEdict (self);
479  return;
480  }
481  self->solid = SOLID_TRIGGER;
482  self->touch = point_combat_touch;
483  VectorSet (self->mins, -8, -8, -16);
484  VectorSet (self->maxs, 8, 8, 16);
485  self->svflags = SVF_NOCLIENT;
486  gi.linkentity (self);
487 }
488 
489 
490 /*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8)
491 Just for the debugging level. Don't use
492 */
494 {
495  ent->s.frame = (ent->s.frame + 1) % 7;
496  ent->nextthink = level.time + FRAMETIME;
497 }
498 
500 {
501  gi.dprintf ("viewthing spawned\n");
502 
503  ent->movetype = MOVETYPE_NONE;
504  ent->solid = SOLID_BBOX;
505  ent->s.renderfx = RF_FRAMELERP;
506  VectorSet (ent->mins, -16, -16, -24);
507  VectorSet (ent->maxs, 16, 16, 32);
508  ent->s.modelindex = gi.modelindex ("models/objects/banner/tris.md2");
509  gi.linkentity (ent);
510  ent->nextthink = level.time + 0.5;
511  ent->think = TH_viewthing;
512  return;
513 }
514 
515 
516 /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
517 Used as a positional target for spotlights, etc.
518 */
519 void SP_info_null (edict_t *self)
520 {
521  G_FreeEdict (self);
522 }
523 
524 
525 /*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
526 Used as a positional target for lightning.
527 */
529 {
530  VectorCopy (self->s.origin, self->absmin);
531  VectorCopy (self->s.origin, self->absmax);
532 }
533 
534 
535 /*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
536 Non-displayed light.
537 Default light value is 300.
538 Default style is 0.
539 If targeted, will toggle between on and off.
540 Default _cone value is 10 (used to set size of light for spotlights)
541 */
542 
543 #define START_OFF 1
544 
545 static void light_use (edict_t *self, edict_t *other, edict_t *activator)
546 {
547  if (self->spawnflags & START_OFF)
548  {
549  gi.configstring (CS_LIGHTS+self->style, "m");
550  self->spawnflags &= ~START_OFF;
551  }
552  else
553  {
554  gi.configstring (CS_LIGHTS+self->style, "a");
555  self->spawnflags |= START_OFF;
556  }
557 }
558 
559 void SP_light (edict_t *self)
560 {
561  // no targeted lights in deathmatch, because they cause global messages
562  if (!self->targetname || deathmatch->value)
563  {
564  G_FreeEdict (self);
565  return;
566  }
567 
568  if (self->style >= 32)
569  {
570  self->use = light_use;
571  if (self->spawnflags & START_OFF)
572  gi.configstring (CS_LIGHTS+self->style, "a");
573  else
574  gi.configstring (CS_LIGHTS+self->style, "m");
575  }
576 }
577 
578 
579 /*QUAKED func_wall (0 .5 .8) ? TRIGGER_SPAWN TOGGLE START_ON ANIMATED ANIMATED_FAST
580 This is just a solid wall if not inhibited
581 
582 TRIGGER_SPAWN the wall will not be present until triggered
583  it will then blink in to existance; it will
584  kill anything that was in it's way
585 
586 TOGGLE only valid for TRIGGER_SPAWN walls
587  this allows the wall to be turned on and off
588 
589 START_ON only valid for TRIGGER_SPAWN walls
590  the wall will initially be present
591 */
592 
593 void func_wall_use (edict_t *self, edict_t *other, edict_t *activator)
594 {
595  if (self->solid == SOLID_NOT)
596  {
597  self->solid = SOLID_BSP;
598  self->svflags &= ~SVF_NOCLIENT;
599  KillBox (self);
600  }
601  else
602  {
603  self->solid = SOLID_NOT;
604  self->svflags |= SVF_NOCLIENT;
605  }
606  gi.linkentity (self);
607 
608  if (!(self->spawnflags & 2))
609  self->use = NULL;
610 }
611 
612 void SP_func_wall (edict_t *self)
613 {
614  self->movetype = MOVETYPE_PUSH;
615  gi.setmodel (self, self->model);
616 
617  if (self->spawnflags & 8)
618  self->s.effects |= EF_ANIM_ALL;
619  if (self->spawnflags & 16)
620  self->s.effects |= EF_ANIM_ALLFAST;
621 
622  // just a wall
623  if ((self->spawnflags & 7) == 0)
624  {
625  self->solid = SOLID_BSP;
626  gi.linkentity (self);
627  return;
628  }
629 
630  // it must be TRIGGER_SPAWN
631  if (!(self->spawnflags & 1))
632  {
633 // gi.dprintf("func_wall missing TRIGGER_SPAWN\n");
634  self->spawnflags |= 1;
635  }
636 
637  // yell if the spawnflags are odd
638  if (self->spawnflags & 4)
639  {
640  if (!(self->spawnflags & 2))
641  {
642  gi.dprintf("func_wall START_ON without TOGGLE\n");
643  self->spawnflags |= 2;
644  }
645  }
646 
647  self->use = func_wall_use;
648  if (self->spawnflags & 4)
649  {
650  self->solid = SOLID_BSP;
651  }
652  else
653  {
654  self->solid = SOLID_NOT;
655  self->svflags |= SVF_NOCLIENT;
656  }
657  gi.linkentity (self);
658 }
659 
660 
661 /*QUAKED func_object (0 .5 .8) ? TRIGGER_SPAWN ANIMATED ANIMATED_FAST
662 This is solid bmodel that will fall if it's support it removed.
663 */
664 
665 void func_object_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
666 {
667  // only squash thing we fall on top of
668  if (!plane)
669  return;
670  if (plane->normal[2] < 1.0)
671  return;
672  if (other->takedamage == DAMAGE_NO)
673  return;
674  T_Damage (other, self, self, vec3_origin, self->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH);
675 }
676 
678 {
679  self->movetype = MOVETYPE_TOSS;
680  self->touch = func_object_touch;
681 }
682 
683 void func_object_use (edict_t *self, edict_t *other, edict_t *activator)
684 {
685  self->solid = SOLID_BSP;
686  self->svflags &= ~SVF_NOCLIENT;
687  self->use = NULL;
688  KillBox (self);
689  func_object_release (self);
690 }
691 
693 {
694  gi.setmodel (self, self->model);
695 
696  self->mins[0] += 1;
697  self->mins[1] += 1;
698  self->mins[2] += 1;
699  self->maxs[0] -= 1;
700  self->maxs[1] -= 1;
701  self->maxs[2] -= 1;
702 
703  if (!self->dmg)
704  self->dmg = 100;
705 
706  if (self->spawnflags == 0)
707  {
708  self->solid = SOLID_BSP;
709  self->movetype = MOVETYPE_PUSH;
710  self->think = func_object_release;
711  self->nextthink = level.time + 2 * FRAMETIME;
712  }
713  else
714  {
715  self->solid = SOLID_NOT;
716  self->movetype = MOVETYPE_PUSH;
717  self->use = func_object_use;
718  self->svflags |= SVF_NOCLIENT;
719  }
720 
721  if (self->spawnflags & 2)
722  self->s.effects |= EF_ANIM_ALL;
723  if (self->spawnflags & 4)
724  self->s.effects |= EF_ANIM_ALLFAST;
725 
726  self->clipmask = MASK_MONSTERSOLID;
727 
728  gi.linkentity (self);
729 }
730 
731 
732 /*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST
733 Any brush that you want to explode or break apart. If you want an
734 ex0plosion, set dmg and it will do a radius explosion of that amount
735 at the center of the bursh.
736 
737 If targeted it will not be shootable.
738 
739 health defaults to 100.
740 
741 mass defaults to 75. This determines how much debris is emitted when
742 it explodes. You get one large chunk per 100 of mass (up to 8) and
743 one small chunk per 25 of mass (up to 16). So 800 gives the most.
744 */
745 void func_explosive_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
746 {
747  vec3_t origin;
748  vec3_t chunkorigin;
749  vec3_t size;
750  int count;
751  int mass;
752 
753  // bmodel origins are (0 0 0), we need to adjust that here
754  VectorScale (self->size, 0.5, size);
755  VectorAdd (self->absmin, size, origin);
756  VectorCopy (origin, self->s.origin);
757 
758  self->takedamage = DAMAGE_NO;
759 
760  if (self->dmg)
761  T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE);
762 
763  VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity);
764  VectorNormalize (self->velocity);
765  VectorScale (self->velocity, 150, self->velocity);
766 
767  // start chunks towards the center
768  VectorScale (size, 0.5, size);
769 
770  mass = self->mass;
771  if (!mass)
772  mass = 75;
773 
774  // big chunks
775  if (mass >= 100)
776  {
777  count = mass / 100;
778  if (count > 8)
779  count = 8;
780  while(count--)
781  {
782  chunkorigin[0] = origin[0] + crandom() * size[0];
783  chunkorigin[1] = origin[1] + crandom() * size[1];
784  chunkorigin[2] = origin[2] + crandom() * size[2];
785  ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin);
786  }
787  }
788 
789  // small chunks
790  count = mass / 25;
791  if (count > 16)
792  count = 16;
793  while(count--)
794  {
795  chunkorigin[0] = origin[0] + crandom() * size[0];
796  chunkorigin[1] = origin[1] + crandom() * size[1];
797  chunkorigin[2] = origin[2] + crandom() * size[2];
798  ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin);
799  }
800 
801  G_UseTargets (self, attacker);
802 
803  if (self->dmg)
804  BecomeExplosion1 (self);
805  else
806  G_FreeEdict (self);
807 }
808 
809 void func_explosive_use(edict_t *self, edict_t *other, edict_t *activator)
810 {
811  func_explosive_explode (self, self, other, self->health, vec3_origin);
812 }
813 
814 void func_explosive_spawn (edict_t *self, edict_t *other, edict_t *activator)
815 {
816  self->solid = SOLID_BSP;
817  self->svflags &= ~SVF_NOCLIENT;
818  self->use = NULL;
819  KillBox (self);
820  gi.linkentity (self);
821 }
822 
824 {
825  if (deathmatch->value)
826  { // auto-remove for deathmatch
827  G_FreeEdict (self);
828  return;
829  }
830 
831  self->movetype = MOVETYPE_PUSH;
832 
833  gi.modelindex ("models/objects/debris1/tris.md2");
834  gi.modelindex ("models/objects/debris2/tris.md2");
835 
836  gi.setmodel (self, self->model);
837 
838  if (self->spawnflags & 1)
839  {
840  self->svflags |= SVF_NOCLIENT;
841  self->solid = SOLID_NOT;
842  self->use = func_explosive_spawn;
843  }
844  else
845  {
846  self->solid = SOLID_BSP;
847  if (self->targetname)
848  self->use = func_explosive_use;
849  }
850 
851  if (self->spawnflags & 2)
852  self->s.effects |= EF_ANIM_ALL;
853  if (self->spawnflags & 4)
854  self->s.effects |= EF_ANIM_ALLFAST;
855 
856  if (self->use != func_explosive_use)
857  {
858  if (!self->health)
859  self->health = 100;
860  self->die = func_explosive_explode;
861  self->takedamage = DAMAGE_YES;
862  }
863 
864  gi.linkentity (self);
865 }
866 
867 
868 /*QUAKED misc_explobox (0 .5 .8) (-16 -16 0) (16 16 40)
869 Large exploding box. You can override its mass (100),
870 health (80), and dmg (150).
871 */
872 
873 void barrel_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
874 
875 {
876  float ratio;
877  vec3_t v;
878 
879  if ((!other->groundentity) || (other->groundentity == self))
880  return;
881 
882  ratio = (float)other->mass / (float)self->mass;
883  VectorSubtract (self->s.origin, other->s.origin, v);
884  M_walkmove (self, vectoyaw(v), 20 * ratio * FRAMETIME);
885 }
886 
888 {
889  vec3_t org;
890  float spd;
891  vec3_t save;
892 
893  T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_BARREL);
894 
895  VectorCopy (self->s.origin, save);
896  VectorMA (self->absmin, 0.5, self->size, self->s.origin);
897 
898  // a few big chunks
899  spd = 1.5 * (float)self->dmg / 200.0;
900  org[0] = self->s.origin[0] + crandom() * self->size[0];
901  org[1] = self->s.origin[1] + crandom() * self->size[1];
902  org[2] = self->s.origin[2] + crandom() * self->size[2];
903  ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org);
904  org[0] = self->s.origin[0] + crandom() * self->size[0];
905  org[1] = self->s.origin[1] + crandom() * self->size[1];
906  org[2] = self->s.origin[2] + crandom() * self->size[2];
907  ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org);
908 
909  // bottom corners
910  spd = 1.75 * (float)self->dmg / 200.0;
911  VectorCopy (self->absmin, org);
912  ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
913  VectorCopy (self->absmin, org);
914  org[0] += self->size[0];
915  ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
916  VectorCopy (self->absmin, org);
917  org[1] += self->size[1];
918  ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
919  VectorCopy (self->absmin, org);
920  org[0] += self->size[0];
921  org[1] += self->size[1];
922  ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
923 
924  // a bunch of little chunks
925  spd = 2 * self->dmg / 200;
926  org[0] = self->s.origin[0] + crandom() * self->size[0];
927  org[1] = self->s.origin[1] + crandom() * self->size[1];
928  org[2] = self->s.origin[2] + crandom() * self->size[2];
929  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
930  org[0] = self->s.origin[0] + crandom() * self->size[0];
931  org[1] = self->s.origin[1] + crandom() * self->size[1];
932  org[2] = self->s.origin[2] + crandom() * self->size[2];
933  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
934  org[0] = self->s.origin[0] + crandom() * self->size[0];
935  org[1] = self->s.origin[1] + crandom() * self->size[1];
936  org[2] = self->s.origin[2] + crandom() * self->size[2];
937  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
938  org[0] = self->s.origin[0] + crandom() * self->size[0];
939  org[1] = self->s.origin[1] + crandom() * self->size[1];
940  org[2] = self->s.origin[2] + crandom() * self->size[2];
941  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
942  org[0] = self->s.origin[0] + crandom() * self->size[0];
943  org[1] = self->s.origin[1] + crandom() * self->size[1];
944  org[2] = self->s.origin[2] + crandom() * self->size[2];
945  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
946  org[0] = self->s.origin[0] + crandom() * self->size[0];
947  org[1] = self->s.origin[1] + crandom() * self->size[1];
948  org[2] = self->s.origin[2] + crandom() * self->size[2];
949  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
950  org[0] = self->s.origin[0] + crandom() * self->size[0];
951  org[1] = self->s.origin[1] + crandom() * self->size[1];
952  org[2] = self->s.origin[2] + crandom() * self->size[2];
953  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
954  org[0] = self->s.origin[0] + crandom() * self->size[0];
955  org[1] = self->s.origin[1] + crandom() * self->size[1];
956  org[2] = self->s.origin[2] + crandom() * self->size[2];
957  ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
958 
959  VectorCopy (save, self->s.origin);
960  if (self->groundentity)
961  BecomeExplosion2 (self);
962  else
963  BecomeExplosion1 (self);
964 }
965 
966 void barrel_delay (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
967 {
968  self->takedamage = DAMAGE_NO;
969  self->nextthink = level.time + 2 * FRAMETIME;
970  self->think = barrel_explode;
971  self->activator = attacker;
972 }
973 
975 {
976  if (deathmatch->value)
977  { // auto-remove for deathmatch
978  G_FreeEdict (self);
979  return;
980  }
981 
982  gi.modelindex ("models/objects/debris1/tris.md2");
983  gi.modelindex ("models/objects/debris2/tris.md2");
984  gi.modelindex ("models/objects/debris3/tris.md2");
985 
986  self->solid = SOLID_BBOX;
987  self->movetype = MOVETYPE_STEP;
988 
989  self->model = "models/objects/barrels/tris.md2";
990  self->s.modelindex = gi.modelindex (self->model);
991  VectorSet (self->mins, -16, -16, 0);
992  VectorSet (self->maxs, 16, 16, 40);
993 
994  if (!self->mass)
995  self->mass = 400;
996  if (!self->health)
997  self->health = 10;
998  if (!self->dmg)
999  self->dmg = 150;
1000 
1001  self->die = barrel_delay;
1002  self->takedamage = DAMAGE_YES;
1003  self->monsterinfo.aiflags = AI_NOSTEP;
1004 
1005  self->touch = barrel_touch;
1006 
1007  self->think = M_droptofloor;
1008  self->nextthink = level.time + 2 * FRAMETIME;
1009 
1010  gi.linkentity (self);
1011 }
1012 
1013 
1014 //
1015 // miscellaneous specialty items
1016 //
1017 
1018 /*QUAKED misc_blackhole (1 .5 0) (-8 -8 -8) (8 8 8)
1019 */
1020 
1021 void misc_blackhole_use (edict_t *ent, edict_t *other, edict_t *activator)
1022 {
1023  /*
1024  gi.WriteByte (svc_temp_entity);
1025  gi.WriteByte (TE_BOSSTPORT);
1026  gi.WritePosition (ent->s.origin);
1027  gi.multicast (ent->s.origin, MULTICAST_PVS);
1028  */
1029  G_FreeEdict (ent);
1030 }
1031 
1033 {
1034  if (++self->s.frame < 19)
1035  self->nextthink = level.time + FRAMETIME;
1036  else
1037  {
1038  self->s.frame = 0;
1039  self->nextthink = level.time + FRAMETIME;
1040  }
1041 }
1042 
1044 {
1045  ent->movetype = MOVETYPE_NONE;
1046  ent->solid = SOLID_NOT;
1047  VectorSet (ent->mins, -64, -64, 0);
1048  VectorSet (ent->maxs, 64, 64, 8);
1049  ent->s.modelindex = gi.modelindex ("models/objects/black/tris.md2");
1050  ent->s.renderfx = RF_TRANSLUCENT;
1051  ent->use = misc_blackhole_use;
1052  ent->think = misc_blackhole_think;
1053  ent->nextthink = level.time + 2 * FRAMETIME;
1054  gi.linkentity (ent);
1055 }
1056 
1057 /*QUAKED misc_eastertank (1 .5 0) (-32 -32 -16) (32 32 32)
1058 */
1059 
1061 {
1062  if (++self->s.frame < 293)
1063  self->nextthink = level.time + FRAMETIME;
1064  else
1065  {
1066  self->s.frame = 254;
1067  self->nextthink = level.time + FRAMETIME;
1068  }
1069 }
1070 
1072 {
1073  ent->movetype = MOVETYPE_NONE;
1074  ent->solid = SOLID_BBOX;
1075  VectorSet (ent->mins, -32, -32, -16);
1076  VectorSet (ent->maxs, 32, 32, 32);
1077  ent->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2");
1078  ent->s.frame = 254;
1080  ent->nextthink = level.time + 2 * FRAMETIME;
1081  gi.linkentity (ent);
1082 }
1083 
1084 /*QUAKED misc_easterchick (1 .5 0) (-32 -32 0) (32 32 32)
1085 */
1086 
1087 
1089 {
1090  if (++self->s.frame < 247)
1091  self->nextthink = level.time + FRAMETIME;
1092  else
1093  {
1094  self->s.frame = 208;
1095  self->nextthink = level.time + FRAMETIME;
1096  }
1097 }
1098 
1100 {
1101  ent->movetype = MOVETYPE_NONE;
1102  ent->solid = SOLID_BBOX;
1103  VectorSet (ent->mins, -32, -32, 0);
1104  VectorSet (ent->maxs, 32, 32, 32);
1105  ent->s.modelindex = gi.modelindex ("models/monsters/bitch/tris.md2");
1106  ent->s.frame = 208;
1108  ent->nextthink = level.time + 2 * FRAMETIME;
1109  gi.linkentity (ent);
1110 }
1111 
1112 /*QUAKED misc_easterchick2 (1 .5 0) (-32 -32 0) (32 32 32)
1113 */
1114 
1115 
1117 {
1118  if (++self->s.frame < 287)
1119  self->nextthink = level.time + FRAMETIME;
1120  else
1121  {
1122  self->s.frame = 248;
1123  self->nextthink = level.time + FRAMETIME;
1124  }
1125 }
1126 
1128 {
1129  ent->movetype = MOVETYPE_NONE;
1130  ent->solid = SOLID_BBOX;
1131  VectorSet (ent->mins, -32, -32, 0);
1132  VectorSet (ent->maxs, 32, 32, 32);
1133  ent->s.modelindex = gi.modelindex ("models/monsters/bitch/tris.md2");
1134  ent->s.frame = 248;
1136  ent->nextthink = level.time + 2 * FRAMETIME;
1137  gi.linkentity (ent);
1138 }
1139 
1140 
1141 /*QUAKED monster_commander_body (1 .5 0) (-32 -32 0) (32 32 48)
1142 Not really a monster, this is the Tank Commander's decapitated body.
1143 There should be a item_commander_head that has this as it's target.
1144 */
1145 
1147 {
1148  if (++self->s.frame < 24)
1149  self->nextthink = level.time + FRAMETIME;
1150  else
1151  self->nextthink = 0;
1152 
1153  if (self->s.frame == 22)
1154  gi.sound (self, CHAN_BODY, gi.soundindex ("tank/thud.wav"), 1, ATTN_NORM, 0);
1155 }
1156 
1157 void commander_body_use (edict_t *self, edict_t *other, edict_t *activator)
1158 {
1159  self->think = commander_body_think;
1160  self->nextthink = level.time + FRAMETIME;
1161  gi.sound (self, CHAN_BODY, gi.soundindex ("tank/pain.wav"), 1, ATTN_NORM, 0);
1162 }
1163 
1165 {
1166  self->movetype = MOVETYPE_TOSS;
1167  self->s.origin[2] += 2;
1168 }
1169 
1171 {
1172  self->movetype = MOVETYPE_NONE;
1173  self->solid = SOLID_BBOX;
1174  self->model = "models/monsters/commandr/tris.md2";
1175  self->s.modelindex = gi.modelindex (self->model);
1176  VectorSet (self->mins, -32, -32, 0);
1177  VectorSet (self->maxs, 32, 32, 48);
1178  self->use = commander_body_use;
1179  self->takedamage = DAMAGE_YES;
1180  self->flags = FL_GODMODE;
1181  self->s.renderfx |= RF_FRAMELERP;
1182  gi.linkentity (self);
1183 
1184  gi.soundindex ("tank/thud.wav");
1185  gi.soundindex ("tank/pain.wav");
1186 
1187  self->think = commander_body_drop;
1188  self->nextthink = level.time + 5 * FRAMETIME;
1189 }
1190 
1191 
1192 /*QUAKED misc_banner (1 .5 0) (-4 -4 -4) (4 4 4)
1193 The origin is the bottom of the banner.
1194 The banner is 128 tall.
1195 */
1197 {
1198  ent->s.frame = (ent->s.frame + 1) % 16;
1199  ent->nextthink = level.time + FRAMETIME;
1200 }
1201 
1203 {
1204  ent->movetype = MOVETYPE_NONE;
1205  ent->solid = SOLID_NOT;
1206  ent->s.modelindex = gi.modelindex ("models/objects/banner/tris.md2");
1207  ent->s.frame = rand() % 16;
1208  gi.linkentity (ent);
1209 
1210  ent->think = misc_banner_think;
1211  ent->nextthink = level.time + FRAMETIME;
1212 }
1213 
1214 /*QUAKED misc_deadsoldier (1 .5 0) (-16 -16 0) (16 16 16) ON_BACK ON_STOMACH BACK_DECAP FETAL_POS SIT_DECAP IMPALED
1215 This is the dead player model. Comes in 6 exciting different poses!
1216 */
1217 void misc_deadsoldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
1218 {
1219  int n;
1220 
1221  if (self->health > -80)
1222  return;
1223 
1224  gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1225  for (n= 0; n < 4; n++)
1226  ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
1227  ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
1228 }
1229 
1231 {
1232  if (deathmatch->value)
1233  { // auto-remove for deathmatch
1234  G_FreeEdict (ent);
1235  return;
1236  }
1237 
1238  ent->movetype = MOVETYPE_NONE;
1239  ent->solid = SOLID_BBOX;
1240  ent->s.modelindex=gi.modelindex ("models/deadbods/dude/tris.md2");
1241 
1242  // Defaults to frame 0
1243  if (ent->spawnflags & 2)
1244  ent->s.frame = 1;
1245  else if (ent->spawnflags & 4)
1246  ent->s.frame = 2;
1247  else if (ent->spawnflags & 8)
1248  ent->s.frame = 3;
1249  else if (ent->spawnflags & 16)
1250  ent->s.frame = 4;
1251  else if (ent->spawnflags & 32)
1252  ent->s.frame = 5;
1253  else
1254  ent->s.frame = 0;
1255 
1256  VectorSet (ent->mins, -16, -16, 0);
1257  VectorSet (ent->maxs, 16, 16, 16);
1258  ent->deadflag = DEAD_DEAD;
1259  ent->takedamage = DAMAGE_YES;
1261  ent->die = misc_deadsoldier_die;
1263 
1264  gi.linkentity (ent);
1265 }
1266 
1267 /*QUAKED misc_viper (1 .5 0) (-16 -16 0) (16 16 32)
1268 This is the Viper for the flyby bombing.
1269 It is trigger_spawned, so you must have something use it for it to show up.
1270 There must be a path for it to follow once it is activated.
1271 
1272 "speed" How fast the Viper should fly
1273 */
1274 
1275 extern void train_use (edict_t *self, edict_t *other, edict_t *activator);
1276 extern void func_train_find (edict_t *self);
1277 
1278 void misc_viper_use (edict_t *self, edict_t *other, edict_t *activator)
1279 {
1280  self->svflags &= ~SVF_NOCLIENT;
1281  self->use = train_use;
1282  train_use (self, other, activator);
1283 }
1284 
1286 {
1287  if (!ent->target)
1288  {
1289  gi.dprintf ("misc_viper without a target at %s\n", vtos(ent->absmin));
1290  G_FreeEdict (ent);
1291  return;
1292  }
1293 
1294  if (!ent->speed)
1295  ent->speed = 300;
1296 
1297  ent->movetype = MOVETYPE_PUSH;
1298  ent->solid = SOLID_NOT;
1299  ent->s.modelindex = gi.modelindex ("models/ships/viper/tris.md2");
1300  VectorSet (ent->mins, -16, -16, 0);
1301  VectorSet (ent->maxs, 16, 16, 32);
1302 
1303  ent->think = func_train_find;
1304  ent->nextthink = level.time + FRAMETIME;
1305  ent->use = misc_viper_use;
1306  ent->svflags |= SVF_NOCLIENT;
1307  ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed;
1308 
1309  gi.linkentity (ent);
1310 }
1311 
1312 
1313 /*QUAKED misc_bigviper (1 .5 0) (-176 -120 -24) (176 120 72)
1314 This is a large stationary viper as seen in Paul's intro
1315 */
1317 {
1318  ent->movetype = MOVETYPE_NONE;
1319  ent->solid = SOLID_BBOX;
1320  VectorSet (ent->mins, -176, -120, -24);
1321  VectorSet (ent->maxs, 176, 120, 72);
1322  ent->s.modelindex = gi.modelindex ("models/ships/bigviper/tris.md2");
1323  gi.linkentity (ent);
1324 }
1325 
1326 
1327 /*QUAKED misc_viper_bomb (1 0 0) (-8 -8 -8) (8 8 8)
1328 "dmg" how much boom should the bomb make?
1329 */
1330 void misc_viper_bomb_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
1331 {
1332  G_UseTargets (self, self->activator);
1333 
1334  self->s.origin[2] = self->absmin[2] + 1;
1335  T_RadiusDamage (self, self, self->dmg, NULL, self->dmg+40, MOD_BOMB);
1336  BecomeExplosion2 (self);
1337 }
1338 
1340 {
1341  vec3_t v;
1342  float diff;
1343 
1344  self->groundentity = NULL;
1345 
1346  diff = self->timestamp - level.time;
1347  if (diff < -1.0)
1348  diff = -1.0;
1349 
1350  VectorScale (self->moveinfo.dir, 1.0 + diff, v);
1351  v[2] = diff;
1352 
1353  diff = self->s.angles[2];
1354  vectoangles (v, self->s.angles);
1355  self->s.angles[2] = diff + 10;
1356 }
1357 
1358 void misc_viper_bomb_use (edict_t *self, edict_t *other, edict_t *activator)
1359 {
1360  edict_t *viper;
1361 
1362  self->solid = SOLID_BBOX;
1363  self->svflags &= ~SVF_NOCLIENT;
1364  self->s.effects |= EF_ROCKET;
1365  self->use = NULL;
1366  self->movetype = MOVETYPE_TOSS;
1367  self->prethink = misc_viper_bomb_prethink;
1368  self->touch = misc_viper_bomb_touch;
1369  self->activator = activator;
1370 
1371  viper = G_Find (NULL, FOFS(classname), "misc_viper");
1372  VectorScale (viper->moveinfo.dir, viper->moveinfo.speed, self->velocity);
1373 
1374  self->timestamp = level.time;
1375  VectorCopy (viper->moveinfo.dir, self->moveinfo.dir);
1376 }
1377 
1379 {
1380  self->movetype = MOVETYPE_NONE;
1381  self->solid = SOLID_NOT;
1382  VectorSet (self->mins, -8, -8, -8);
1383  VectorSet (self->maxs, 8, 8, 8);
1384 
1385  self->s.modelindex = gi.modelindex ("models/objects/bomb/tris.md2");
1386 
1387  if (!self->dmg)
1388  self->dmg = 1000;
1389 
1390  self->use = misc_viper_bomb_use;
1391  self->svflags |= SVF_NOCLIENT;
1392 
1393  gi.linkentity (self);
1394 }
1395 
1396 
1397 /*QUAKED misc_strogg_ship (1 .5 0) (-16 -16 0) (16 16 32)
1398 This is a Storgg ship for the flybys.
1399 It is trigger_spawned, so you must have something use it for it to show up.
1400 There must be a path for it to follow once it is activated.
1401 
1402 "speed" How fast it should fly
1403 */
1404 
1405 extern void train_use (edict_t *self, edict_t *other, edict_t *activator);
1406 extern void func_train_find (edict_t *self);
1407 
1408 void misc_strogg_ship_use (edict_t *self, edict_t *other, edict_t *activator)
1409 {
1410  self->svflags &= ~SVF_NOCLIENT;
1411  self->use = train_use;
1412  train_use (self, other, activator);
1413 }
1414 
1416 {
1417  if (!ent->target)
1418  {
1419  gi.dprintf ("%s without a target at %s\n", ent->classname, vtos(ent->absmin));
1420  G_FreeEdict (ent);
1421  return;
1422  }
1423 
1424  if (!ent->speed)
1425  ent->speed = 300;
1426 
1427  ent->movetype = MOVETYPE_PUSH;
1428  ent->solid = SOLID_NOT;
1429  ent->s.modelindex = gi.modelindex ("models/ships/strogg1/tris.md2");
1430  VectorSet (ent->mins, -16, -16, 0);
1431  VectorSet (ent->maxs, 16, 16, 32);
1432 
1433  ent->think = func_train_find;
1434  ent->nextthink = level.time + FRAMETIME;
1435  ent->use = misc_strogg_ship_use;
1436  ent->svflags |= SVF_NOCLIENT;
1437  ent->moveinfo.accel = ent->moveinfo.decel = ent->moveinfo.speed = ent->speed;
1438 
1439  gi.linkentity (ent);
1440 }
1441 
1442 
1443 /*QUAKED misc_satellite_dish (1 .5 0) (-64 -64 0) (64 64 128)
1444 */
1446 {
1447  self->s.frame++;
1448  if (self->s.frame < 38)
1449  self->nextthink = level.time + FRAMETIME;
1450 }
1451 
1452 void misc_satellite_dish_use (edict_t *self, edict_t *other, edict_t *activator)
1453 {
1454  self->s.frame = 0;
1455  self->think = misc_satellite_dish_think;
1456  self->nextthink = level.time + FRAMETIME;
1457 }
1458 
1460 {
1461  ent->movetype = MOVETYPE_NONE;
1462  ent->solid = SOLID_BBOX;
1463  VectorSet (ent->mins, -64, -64, 0);
1464  VectorSet (ent->maxs, 64, 64, 128);
1465  ent->s.modelindex = gi.modelindex ("models/objects/satellite/tris.md2");
1467  gi.linkentity (ent);
1468 }
1469 
1470 
1471 /*QUAKED light_mine1 (0 1 0) (-2 -2 -12) (2 2 12)
1472 */
1474 {
1475  ent->movetype = MOVETYPE_NONE;
1476  ent->solid = SOLID_BBOX;
1477  ent->s.modelindex = gi.modelindex ("models/objects/minelite/light1/tris.md2");
1478  gi.linkentity (ent);
1479 }
1480 
1481 
1482 /*QUAKED light_mine2 (0 1 0) (-2 -2 -12) (2 2 12)
1483 */
1485 {
1486  ent->movetype = MOVETYPE_NONE;
1487  ent->solid = SOLID_BBOX;
1488  ent->s.modelindex = gi.modelindex ("models/objects/minelite/light2/tris.md2");
1489  gi.linkentity (ent);
1490 }
1491 
1492 
1493 /*QUAKED misc_gib_arm (1 0 0) (-8 -8 -8) (8 8 8)
1494 Intended for use with the target_spawner
1495 */
1497 {
1498  gi.setmodel (ent, "models/objects/gibs/arm/tris.md2");
1499  ent->solid = SOLID_NOT;
1500  ent->s.effects |= EF_GIB;
1501  ent->takedamage = DAMAGE_YES;
1502  ent->die = gib_die;
1503  ent->movetype = MOVETYPE_TOSS;
1504  ent->svflags |= SVF_MONSTER;
1505  ent->deadflag = DEAD_DEAD;
1506  ent->avelocity[0] = random()*200;
1507  ent->avelocity[1] = random()*200;
1508  ent->avelocity[2] = random()*200;
1509  ent->think = G_FreeEdict;
1510  ent->nextthink = level.time + 30;
1511  gi.linkentity (ent);
1512 }
1513 
1514 /*QUAKED misc_gib_leg (1 0 0) (-8 -8 -8) (8 8 8)
1515 Intended for use with the target_spawner
1516 */
1518 {
1519  gi.setmodel (ent, "models/objects/gibs/leg/tris.md2");
1520  ent->solid = SOLID_NOT;
1521  ent->s.effects |= EF_GIB;
1522  ent->takedamage = DAMAGE_YES;
1523  ent->die = gib_die;
1524  ent->movetype = MOVETYPE_TOSS;
1525  ent->svflags |= SVF_MONSTER;
1526  ent->deadflag = DEAD_DEAD;
1527  ent->avelocity[0] = random()*200;
1528  ent->avelocity[1] = random()*200;
1529  ent->avelocity[2] = random()*200;
1530  ent->think = G_FreeEdict;
1531  ent->nextthink = level.time + 30;
1532  gi.linkentity (ent);
1533 }
1534 
1535 /*QUAKED misc_gib_head (1 0 0) (-8 -8 -8) (8 8 8)
1536 Intended for use with the target_spawner
1537 */
1539 {
1540  gi.setmodel (ent, "models/objects/gibs/head/tris.md2");
1541  ent->solid = SOLID_NOT;
1542  ent->s.effects |= EF_GIB;
1543  ent->takedamage = DAMAGE_YES;
1544  ent->die = gib_die;
1545  ent->movetype = MOVETYPE_TOSS;
1546  ent->svflags |= SVF_MONSTER;
1547  ent->deadflag = DEAD_DEAD;
1548  ent->avelocity[0] = random()*200;
1549  ent->avelocity[1] = random()*200;
1550  ent->avelocity[2] = random()*200;
1551  ent->think = G_FreeEdict;
1552  ent->nextthink = level.time + 30;
1553  gi.linkentity (ent);
1554 }
1555 
1556 //=====================================================
1557 
1558 /*QUAKED target_character (0 0 1) ?
1559 used with target_string (must be on same "team")
1560 "count" is position in the string (starts at 1)
1561 */
1562 
1564 {
1565  self->movetype = MOVETYPE_PUSH;
1566  gi.setmodel (self, self->model);
1567  self->solid = SOLID_BSP;
1568  self->s.frame = 12;
1569  gi.linkentity (self);
1570  return;
1571 }
1572 
1573 
1574 /*QUAKED target_string (0 0 1) (-8 -8 -8) (8 8 8)
1575 */
1576 
1577 void target_string_use (edict_t *self, edict_t *other, edict_t *activator)
1578 {
1579  edict_t *e;
1580  int n, l;
1581  char c;
1582 
1583  l = strlen(self->message);
1584  for (e = self->teammaster; e; e = e->teamchain)
1585  {
1586  if (!e->count)
1587  continue;
1588  n = e->count - 1;
1589  if (n > l)
1590  {
1591  e->s.frame = 12;
1592  continue;
1593  }
1594 
1595  c = self->message[n];
1596  if (c >= '0' && c <= '9')
1597  e->s.frame = c - '0';
1598  else if (c == '-')
1599  e->s.frame = 10;
1600  else if (c == ':')
1601  e->s.frame = 11;
1602  else
1603  e->s.frame = 12;
1604  }
1605 }
1606 
1608 {
1609  if (!self->message)
1610  self->message = "";
1611  self->use = target_string_use;
1612 }
1613 
1614 
1615 /*QUAKED func_clock (0 0 1) (-8 -8 -8) (8 8 8) TIMER_UP TIMER_DOWN START_OFF MULTI_USE
1616 target a target_string with this
1617 
1618 The default is to be a time of day clock
1619 
1620 TIMER_UP and TIMER_DOWN run for "count" seconds and the fire "pathtarget"
1621 If START_OFF, this entity must be used before it starts
1622 
1623 "style" 0 "xx"
1624  1 "xx:xx"
1625  2 "xx:xx:xx"
1626 */
1627 
1628 #define CLOCK_MESSAGE_SIZE 16
1629 
1630 // don't let field width of any clock messages change, or it
1631 // could cause an overwrite after a game load
1632 
1633 static void func_clock_reset (edict_t *self)
1634 {
1635  self->activator = NULL;
1636  if (self->spawnflags & 1)
1637  {
1638  self->health = 0;
1639  self->wait = self->count;
1640  }
1641  else if (self->spawnflags & 2)
1642  {
1643  self->health = self->count;
1644  self->wait = 0;
1645  }
1646 }
1647 
1649 {
1650  if (self->style == 0)
1651  {
1652  Com_sprintf (self->message, CLOCK_MESSAGE_SIZE, "%2i", self->health);
1653  return;
1654  }
1655 
1656  if (self->style == 1)
1657  {
1658  Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i", self->health / 60, self->health % 60);
1659  if (self->message[3] == ' ')
1660  self->message[3] = '0';
1661  return;
1662  }
1663 
1664  if (self->style == 2)
1665  {
1666  Com_sprintf(self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", self->health / 3600, (self->health - (self->health / 3600) * 3600) / 60, self->health % 60);
1667  if (self->message[3] == ' ')
1668  self->message[3] = '0';
1669  if (self->message[6] == ' ')
1670  self->message[6] = '0';
1671  return;
1672  }
1673 }
1674 
1676 {
1677  if (!self->enemy)
1678  {
1679  self->enemy = G_Find (NULL, FOFS(targetname), self->target);
1680  if (!self->enemy)
1681  return;
1682  }
1683 
1684  if (self->spawnflags & 1)
1685  {
1687  self->health++;
1688  }
1689  else if (self->spawnflags & 2)
1690  {
1692  self->health--;
1693  }
1694  else
1695  {
1696  struct tm *ltime;
1697  time_t gmtime;
1698 
1699  time(&gmtime);
1700  ltime = localtime(&gmtime);
1701  Com_sprintf (self->message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", ltime->tm_hour, ltime->tm_min, ltime->tm_sec);
1702  if (self->message[3] == ' ')
1703  self->message[3] = '0';
1704  if (self->message[6] == ' ')
1705  self->message[6] = '0';
1706  }
1707 
1708  self->enemy->message = self->message;
1709  self->enemy->use (self->enemy, self, self);
1710 
1711  if (((self->spawnflags & 1) && (self->health > self->wait)) ||
1712  ((self->spawnflags & 2) && (self->health < self->wait)))
1713  {
1714  if (self->pathtarget)
1715  {
1716  char *savetarget;
1717  char *savemessage;
1718 
1719  savetarget = self->target;
1720  savemessage = self->message;
1721  self->target = self->pathtarget;
1722  self->message = NULL;
1723  G_UseTargets (self, self->activator);
1724  self->target = savetarget;
1725  self->message = savemessage;
1726  }
1727 
1728  if (!(self->spawnflags & 8))
1729  return;
1730 
1731  func_clock_reset (self);
1732 
1733  if (self->spawnflags & 4)
1734  return;
1735  }
1736 
1737  self->nextthink = level.time + 1;
1738 }
1739 
1740 void func_clock_use (edict_t *self, edict_t *other, edict_t *activator)
1741 {
1742  if (!(self->spawnflags & 8))
1743  self->use = NULL;
1744  if (self->activator)
1745  return;
1746  self->activator = activator;
1747  self->think (self);
1748 }
1749 
1751 {
1752  if (!self->target)
1753  {
1754  gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin));
1755  G_FreeEdict (self);
1756  return;
1757  }
1758 
1759  if ((self->spawnflags & 2) && (!self->count))
1760  {
1761  gi.dprintf("%s with no count at %s\n", self->classname, vtos(self->s.origin));
1762  G_FreeEdict (self);
1763  return;
1764  }
1765 
1766  if ((self->spawnflags & 1) && (!self->count))
1767  self->count = 60*60;;
1768 
1769  func_clock_reset (self);
1770 
1771  self->message = gi.TagMalloc (CLOCK_MESSAGE_SIZE, TAG_LEVEL);
1772 
1773  self->think = func_clock_think;
1774 
1775  if (self->spawnflags & 4)
1776  self->use = func_clock_use;
1777  else
1778  self->nextthink = level.time + 1;
1779 }
1780 
1781 //=================================================================================
1782 
1783 void teleporter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
1784 {
1785  edict_t *dest;
1786  int i;
1787 
1788  if (!other->client)
1789  return;
1790  dest = G_Find (NULL, FOFS(targetname), self->target);
1791  if (!dest)
1792  {
1793  gi.dprintf ("Couldn't find destination\n");
1794  return;
1795  }
1796 
1797  // unlink to make sure it can't possibly interfere with KillBox
1798  gi.unlinkentity (other);
1799 
1800  VectorCopy (dest->s.origin, other->s.origin);
1801  VectorCopy (dest->s.origin, other->s.old_origin);
1802  other->s.origin[2] += 10;
1803 
1804  // clear the velocity and hold them in place briefly
1805  VectorClear (other->velocity);
1806  other->client->ps.pmove.pm_time = 160>>3; // hold time
1808 
1809  // draw the teleport splash at source and on the player
1810  self->owner->s.event = EV_PLAYER_TELEPORT;
1811  other->s.event = EV_PLAYER_TELEPORT;
1812 
1813  // set angles
1814  for (i=0 ; i<3 ; i++)
1815  {
1816  other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(dest->s.angles[i] - other->client->resp.cmd_angles[i]);
1817  }
1818 
1819  VectorClear (other->s.angles);
1820  VectorClear (other->client->ps.viewangles);
1821  VectorClear (other->client->v_angle);
1822 
1823  // kill anything at the destination
1824  KillBox (other);
1825 
1826  gi.linkentity (other);
1827 }
1828 
1829 /*QUAKED misc_teleporter (1 0 0) (-32 -32 -24) (32 32 -16)
1830 Stepping onto this disc will teleport players to the targeted misc_teleporter_dest object.
1831 */
1833 {
1834  edict_t *trig;
1835 
1836  if (!ent->target)
1837  {
1838  gi.dprintf ("teleporter without a target.\n");
1839  G_FreeEdict (ent);
1840  return;
1841  }
1842 
1843  gi.setmodel (ent, "models/objects/dmspot/tris.md2");
1844  ent->s.skinnum = 1;
1845  ent->s.effects = EF_TELEPORTER;
1846  ent->s.sound = gi.soundindex ("world/amb10.wav");
1847  ent->solid = SOLID_BBOX;
1848 
1849  VectorSet (ent->mins, -32, -32, -24);
1850  VectorSet (ent->maxs, 32, 32, -16);
1851  gi.linkentity (ent);
1852 
1853  trig = G_Spawn ();
1854  trig->touch = teleporter_touch;
1855  trig->solid = SOLID_TRIGGER;
1856  trig->target = ent->target;
1857  trig->owner = ent;
1858  VectorCopy (ent->s.origin, trig->s.origin);
1859  VectorSet (trig->mins, -8, -8, 8);
1860  VectorSet (trig->maxs, 8, 8, 24);
1861  gi.linkentity (trig);
1862 
1863 }
1864 
1865 /*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16)
1866 Point teleporters at these.
1867 */
1869 {
1870  gi.setmodel (ent, "models/objects/dmspot/tris.md2");
1871  ent->s.skinnum = 0;
1872  ent->solid = SOLID_BBOX;
1873 // ent->s.effects |= EF_FLIES;
1874  VectorSet (ent->mins, -32, -32, -24);
1875  VectorSet (ent->maxs, 32, 32, -16);
1876  gi.linkentity (ent);
1877 }
1878 
entity_state_s::old_origin
vec3_t old_origin
Definition: q_shared.h:1175
gi
game_import_t gi
Definition: g_main.c:25
ThrowHead
void ThrowHead(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:183
RF_TRANSLUCENT
#define RF_TRANSLUCENT
Definition: q_shared.h:618
moveinfo_t::decel
float decel
Definition: g_local.h:384
misc_strogg_ship_use
void misc_strogg_ship_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1408
SP_viewthing
void SP_viewthing(edict_t *ent)
Definition: g_misc.c:499
misc_deadsoldier_die
void misc_deadsoldier_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_misc.c:1217
edict_s::ideal_yaw
float ideal_yaw
Definition: g_local.h:1034
game_import_t::dprintf
void(* dprintf)(char *fmt,...)
Definition: game.h:106
SP_light
void SP_light(edict_t *self)
Definition: g_misc.c:559
cplane_s::normal
vec3_t normal
Definition: q_shared.h:411
edict_s::s
entity_state_t s
Definition: g_local.h:964
EF_TELEPORTER
#define EF_TELEPORTER
Definition: q_shared.h:574
edict_s::groundentity
edict_t * groundentity
Definition: g_local.h:1073
ThrowClientHead
void ThrowClientHead(edict_t *self, int damage)
Definition: g_misc.c:229
deathmatch
cvar_t * deathmatch
Definition: g_main.c:35
SP_misc_viper
void SP_misc_viper(edict_t *ent)
Definition: g_misc.c:1285
SP_misc_satellite_dish
void SP_misc_satellite_dish(edict_t *ent)
Definition: g_misc.c:1459
misc_viper_bomb_use
void misc_viper_bomb_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1358
YAW
#define YAW
Definition: q_shared.h:66
DEAD_DEAD
#define DEAD_DEAD
Definition: g_local.h:113
SP_misc_teleporter_dest
void SP_misc_teleporter_dest(edict_t *ent)
Definition: g_misc.c:1868
AI_COMBAT_POINT
#define AI_COMBAT_POINT
Definition: g_local.h:139
MASK_MONSTERSOLID
#define MASK_MONSTERSOLID
Definition: q_shared.h:394
SP_misc_strogg_ship
void SP_misc_strogg_ship(edict_t *ent)
Definition: g_misc.c:1415
barrel_delay
void barrel_delay(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_misc.c:966
gclient_s::v_angle
vec3_t v_angle
Definition: g_local.h:921
G_Spawn
edict_t * G_Spawn(void)
Definition: g_utils.c:420
func_object_use
void func_object_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:683
VectorSubtract
#define VectorSubtract(a, b, c)
Definition: q_shared.h:156
light_use
static void light_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:545
edict_s::activator
edict_t * activator
Definition: g_local.h:1072
entity_state_s::frame
int frame
Definition: q_shared.h:1178
ANIM_DEATH
#define ANIM_DEATH
Definition: g_local.h:822
TE_EXPLOSION1
@ TE_EXPLOSION1
Definition: q_shared.h:940
EV_PLAYER_TELEPORT
@ EV_PLAYER_TELEPORT
Definition: q_shared.h:1161
AI_GOOD_GUY
#define AI_GOOD_GUY
Definition: g_local.h:135
game_import_t::WritePosition
void(* WritePosition)(vec3_t pos)
Definition: game.h:152
game_import_t::multicast
void(* multicast)(vec3_t origin, multicast_t to)
Definition: game.h:144
barrel_touch
void barrel_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:873
edict_s::count
int count
Definition: g_local.h:1067
SOLID_BBOX
@ SOLID_BBOX
Definition: game.h:37
TH_viewthing
void TH_viewthing(edict_t *ent)
Definition: g_misc.c:493
misc_viper_use
void misc_viper_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1278
FRAMETIME
#define FRAMETIME
Definition: g_local.h:73
edict_s::movetarget
edict_t * movetarget
Definition: g_local.h:1032
MOD_BOMB
#define MOD_BOMB
Definition: g_local.h:490
SP_light_mine1
void SP_light_mine1(edict_t *ent)
Definition: g_misc.c:1473
entity_state_s::renderfx
int renderfx
Definition: q_shared.h:1181
v
GLdouble v
Definition: qgl_win.c:143
SP_misc_deadsoldier
void SP_misc_deadsoldier(edict_t *ent)
Definition: g_misc.c:1230
path_corner_touch
void path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:342
M_walkmove
qboolean M_walkmove(edict_t *ent, float yaw, float dist)
Definition: m_move.c:542
func_clock_think
void func_clock_think(edict_t *self)
Definition: g_misc.c:1675
EF_FLIES
#define EF_FLIES
Definition: q_shared.h:571
SP_point_combat
void SP_point_combat(edict_t *self)
Definition: g_misc.c:474
entity_state_s::origin
vec3_t origin
Definition: q_shared.h:1173
SP_misc_bigviper
void SP_misc_bigviper(edict_t *ent)
Definition: g_misc.c:1316
SVF_NOCLIENT
#define SVF_NOCLIENT
Definition: game.h:27
SP_misc_gib_arm
void SP_misc_gib_arm(edict_t *ent)
Definition: g_misc.c:1496
misc_banner_think
void misc_banner_think(edict_t *ent)
Definition: g_misc.c:1196
target_string_use
void target_string_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1577
AI_STAND_GROUND
#define AI_STAND_GROUND
Definition: g_local.h:127
VectorScale
void VectorScale(vec3_t in, vec_t scale, vec3_t out)
Definition: q_shared.c:782
SP_misc_easterchick
void SP_misc_easterchick(edict_t *ent)
Definition: g_misc.c:1099
edict_s::oldenemy
edict_t * oldenemy
Definition: g_local.h:1071
monsterinfo_t::stand
void(* stand)(edict_t *self)
Definition: g_local.h:423
VectorClear
#define VectorClear(a)
Definition: q_shared.h:159
i
int i
Definition: q_shared.c:305
MOVETYPE_PUSH
@ MOVETYPE_PUSH
Definition: g_local.h:190
func_train_find
void func_train_find(edict_t *self)
Definition: g_func.c:1601
SP_misc_blackhole
void SP_misc_blackhole(edict_t *ent)
Definition: g_misc.c:1043
G_Find
edict_t * G_Find(edict_t *from, int fieldofs, char *match)
Definition: g_utils.c:45
SOLID_TRIGGER
@ SOLID_TRIGGER
Definition: game.h:36
DAMAGE_YES
@ DAMAGE_YES
Definition: g_local.h:87
edict_s::client
struct gclient_s * client
Definition: g_local.h:965
entity_state_s::event
int event
Definition: q_shared.h:1186
game_import_t::sound
void(* sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs)
Definition: game.h:109
SP_monster_commander_body
void SP_monster_commander_body(edict_t *self)
Definition: g_misc.c:1170
FOFS
#define FOFS(x)
Definition: g_local.h:504
M_droptofloor
void M_droptofloor(edict_t *ent)
Definition: g_monster.c:310
FL_NO_KNOCKBACK
#define FL_NO_KNOCKBACK
Definition: g_local.h:68
vectoyaw
float vectoyaw(vec3_t vec)
Definition: g_utils.c:333
TAG_LEVEL
#define TAG_LEVEL
Definition: g_local.h:77
commander_body_use
void commander_body_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1157
edict_s::mins
vec3_t mins
Definition: g_local.h:984
misc_easterchick2_think
void misc_easterchick2_think(edict_t *self)
Definition: g_misc.c:1116
SP_target_string
void SP_target_string(edict_t *self)
Definition: g_misc.c:1607
type
GLenum type
Definition: qgl_win.c:72
ATTN_NORM
#define ATTN_NORM
Definition: q_shared.h:1019
T_Damage
void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod)
Definition: g_combat.c:378
BecomeExplosion2
void BecomeExplosion2(edict_t *self)
Definition: g_misc.c:325
TE_EXPLOSION2
@ TE_EXPLOSION2
Definition: q_shared.h:941
edict_s::movetype
int movetype
Definition: g_local.h:995
barrel_explode
void barrel_explode(edict_t *self)
Definition: g_misc.c:887
MOVETYPE_STEP
@ MOVETYPE_STEP
Definition: g_local.h:194
entity_state_s::effects
unsigned int effects
Definition: q_shared.h:1180
commander_body_drop
void commander_body_drop(edict_t *self)
Definition: g_misc.c:1164
FL_SWIM
#define FL_SWIM
Definition: g_local.h:58
func_object_touch
void func_object_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:665
entity_state_s::sound
int sound
Definition: q_shared.h:1185
teleporter_touch
void teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:1783
func_wall_use
void func_wall_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:593
debris_die
void debris_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_misc.c:281
SVF_DEADMONSTER
#define SVF_DEADMONSTER
Definition: game.h:28
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: q_shared.c:93
edict_s::svflags
int svflags
Definition: g_local.h:983
CHAN_VOICE
#define CHAN_VOICE
Definition: q_shared.h:1009
commander_body_think
void commander_body_think(edict_t *self)
Definition: g_misc.c:1146
PMF_TIME_TELEPORT
#define PMF_TIME_TELEPORT
Definition: q_shared.h:482
SP_misc_banner
void SP_misc_banner(edict_t *ent)
Definition: g_misc.c:1202
vectoangles
void vectoangles(vec3_t vec, vec3_t angles)
Definition: g_utils.c:356
gib_touch
void gib_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:104
SP_func_areaportal
void SP_func_areaportal(edict_t *ent)
Definition: g_misc.c:44
edict_s::classname
char * classname
Definition: g_local.h:1005
edict_s::speed
float speed
Definition: g_local.h:1020
edict_s
Definition: g_local.h:962
MOD_EXPLOSIVE
#define MOD_EXPLOSIVE
Definition: g_local.h:488
edict_s::mass
int mass
Definition: g_local.h:1026
EF_ROCKET
#define EF_ROCKET
Definition: q_shared.h:561
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:452
monsterinfo_t::pausetime
float pausetime
Definition: g_local.h:434
edict_s::moveinfo
moveinfo_t moveinfo
Definition: g_local.h:1107
MOVETYPE_NONE
@ MOVETYPE_NONE
Definition: g_local.h:188
SP_info_notnull
void SP_info_notnull(edict_t *self)
Definition: g_misc.c:528
csurface_s
Definition: q_shared.h:435
point_combat_touch
void point_combat_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:422
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:1204
func_object_release
void func_object_release(edict_t *self)
Definition: g_misc.c:677
game_import_t::SetAreaPortalState
void(* SetAreaPortalState)(int portalnum, qboolean open)
Definition: game.h:132
game_import_t::soundindex
int(* soundindex)(char *name)
Definition: game.h:122
edict_s::spawnflags
int spawnflags
Definition: g_local.h:1006
crandom
#define crandom()
Definition: g_local.h:510
player_state_t::pmove
pmove_state_t pmove
Definition: q_shared.h:1200
SP_misc_viper_bomb
void SP_misc_viper_bomb(edict_t *self)
Definition: g_misc.c:1378
FL_GODMODE
#define FL_GODMODE
Definition: g_local.h:61
edict_s::owner
edict_t * owner
Definition: g_local.h:988
game_import_t::modelindex
int(* modelindex)(char *name)
Definition: game.h:121
EF_GIB
#define EF_GIB
Definition: q_shared.h:559
edict_s::deadflag
int deadflag
Definition: g_local.h:1054
client_respawn_t::cmd_angles
vec3_t cmd_angles
Definition: g_local.h:870
misc_eastertank_think
void misc_eastertank_think(edict_t *self)
Definition: g_misc.c:1060
SP_info_null
void SP_info_null(edict_t *self)
Definition: g_misc.c:519
edict_s::nextthink
float nextthink
Definition: g_local.h:1036
Use_Areaportal
void Use_Areaportal(edict_t *ent, edict_t *other, edict_t *activator)
Definition: g_misc.c:31
cvar_s::value
float value
Definition: q_shared.h:324
vtos
char * vtos(vec3_t v)
Definition: g_utils.c:293
SP_func_explosive
void SP_func_explosive(edict_t *self)
Definition: g_misc.c:823
edict_s::think
void(* think)(edict_t *self)
Definition: g_local.h:1038
func_clock_use
void func_clock_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1740
random
#define random()
Definition: g_local.h:509
pmove_state_t::delta_angles
short delta_angles[3]
Definition: q_shared.h:499
DAMAGE_NO
@ DAMAGE_NO
Definition: g_local.h:86
moveinfo_t::dir
vec3_t dir
Definition: g_local.h:391
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: q_shared.c:681
EF_ANIM_ALLFAST
#define EF_ANIM_ALLFAST
Definition: q_shared.h:570
gclient_s::ps
player_state_t ps
Definition: g_local.h:880
NULL
#define NULL
Definition: q_shared.h:60
edict_s::solid
solid_t solid
Definition: g_local.h:986
game_import_t::TagMalloc
void *(* TagMalloc)(int size, int tag)
Definition: game.h:157
EV_OTHER_TELEPORT
@ EV_OTHER_TELEPORT
Definition: q_shared.h:1162
SP_func_wall
void SP_func_wall(edict_t *self)
Definition: g_misc.c:612
BecomeExplosion1
void BecomeExplosion1(edict_t *self)
Definition: g_misc.c:314
SP_misc_eastertank
void SP_misc_eastertank(edict_t *ent)
Definition: g_misc.c:1071
SP_misc_easterchick2
void SP_misc_easterchick2(edict_t *ent)
Definition: g_misc.c:1127
func_clock_reset
static void func_clock_reset(edict_t *self)
Definition: g_misc.c:1633
SP_func_object
void SP_func_object(edict_t *self)
Definition: g_misc.c:692
sm_meat_index
int sm_meat_index
Definition: g_main.c:29
misc_blackhole_use
void misc_blackhole_use(edict_t *ent, edict_t *other, edict_t *activator)
Definition: g_misc.c:1021
monsterinfo_t::aiflags
int aiflags
Definition: g_local.h:419
MOD_BARREL
#define MOD_BARREL
Definition: g_local.h:489
misc_blackhole_think
void misc_blackhole_think(edict_t *self)
Definition: g_misc.c:1032
edict_s::goalentity
edict_t * goalentity
Definition: g_local.h:1031
SP_misc_teleporter
void SP_misc_teleporter(edict_t *ent)
Definition: g_misc.c:1832
SOLID_NOT
@ SOLID_NOT
Definition: game.h:35
edict_s::dmg
int dmg
Definition: g_local.h:1063
edict_s::velocity
vec3_t velocity
Definition: g_local.h:1024
misc_viper_bomb_prethink
void misc_viper_bomb_prethink(edict_t *self)
Definition: g_misc.c:1339
MOD_CRUSH
#define MOD_CRUSH
Definition: g_local.h:483
game_import_t::setmodel
void(* setmodel)(edict_t *ent, char *name)
Definition: game.h:125
VectorAdd
#define VectorAdd(a, b, c)
Definition: q_shared.h:157
game_import_t::unlinkentity
void(* unlinkentity)(edict_t *ent)
Definition: game.h:139
svc_temp_entity
@ svc_temp_entity
Definition: qcommon.h:210
entity_state_s::skinnum
int skinnum
Definition: q_shared.h:1179
SP_misc_explobox
void SP_misc_explobox(edict_t *self)
Definition: g_misc.c:974
ClipGibVelocity
void ClipGibVelocity(edict_t *ent)
Definition: g_misc.c:70
func_explosive_use
void func_explosive_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:809
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:158
ThrowGib
void ThrowGib(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:135
func_explosive_spawn
void func_explosive_spawn(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:814
edict_s::use
void(* use)(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_local.h:1041
edict_s::monsterinfo
monsterinfo_t monsterinfo
Definition: g_local.h:1108
vec3_origin
vec3_t vec3_origin
Definition: q_shared.c:24
gib_die
void gib_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_misc.c:130
edict_s::style
int style
Definition: g_local.h:1102
game_import_t::WriteByte
void(* WriteByte)(int c)
Definition: game.h:147
SP_target_character
void SP_target_character(edict_t *self)
Definition: g_misc.c:1563
SP_misc_gib_leg
void SP_misc_gib_leg(edict_t *ent)
Definition: g_misc.c:1517
edict_s::takedamage
int takedamage
Definition: g_local.h:1062
misc_viper_bomb_touch
void misc_viper_bomb_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_misc.c:1330
level
GLint level
Definition: qgl_win.c:116
G_UseTargets
void G_UseTargets(edict_t *ent, edict_t *activator)
Definition: g_utils.c:173
edict_s::flags
int flags
Definition: g_local.h:996
GIB_ORGANIC
#define GIB_ORGANIC
Definition: g_local.h:123
CLOCK_MESSAGE_SIZE
#define CLOCK_MESSAGE_SIZE
Definition: g_misc.c:1628
VectorMA
void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
Definition: q_shared.c:719
SOLID_BSP
@ SOLID_BSP
Definition: game.h:38
edict_s::maxs
vec3_t maxs
Definition: g_local.h:984
SP_path_corner
void SP_path_corner(edict_t *self)
Definition: g_misc.c:399
edict_s::avelocity
vec3_t avelocity
Definition: g_local.h:1025
edict_s::teammaster
edict_t * teammaster
Definition: g_local.h:1076
entity_state_s::modelindex
int modelindex
Definition: q_shared.h:1176
moveinfo_t::accel
float accel
Definition: g_local.h:382
FL_FLY
#define FL_FLY
Definition: g_local.h:57
KillBox
qboolean KillBox(edict_t *ent)
Definition: g_utils.c:549
SVF_MONSTER
#define SVF_MONSTER
Definition: game.h:29
edict_s::touch
void(* touch)(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
Definition: g_local.h:1040
misc_easterchick_think
void misc_easterchick_think(edict_t *self)
Definition: g_misc.c:1088
SP_misc_gib_head
void SP_misc_gib_head(edict_t *ent)
Definition: g_misc.c:1538
MOVETYPE_BOUNCE
@ MOVETYPE_BOUNCE
Definition: g_local.h:198
gib_think
void gib_think(edict_t *self)
Definition: g_misc.c:92
func_clock_format_countdown
static void func_clock_format_countdown(edict_t *self)
Definition: g_misc.c:1648
func_explosive_explode
void func_explosive_explode(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_misc.c:745
MOVETYPE_TOSS
@ MOVETYPE_TOSS
Definition: g_local.h:196
RF_FRAMELERP
#define RF_FRAMELERP
Definition: q_shared.h:619
VectorSet
#define VectorSet(v, x, y, z)
Definition: q_shared.h:161
right
GLdouble right
Definition: qgl_win.c:159
SP_func_clock
void SP_func_clock(edict_t *self)
Definition: g_misc.c:1750
ANGLE2SHORT
#define ANGLE2SHORT(x)
Definition: q_shared.h:1116
CS_LIGHTS
#define CS_LIGHTS
Definition: q_shared.h:1139
CHAN_BODY
#define CHAN_BODY
Definition: q_shared.h:1011
misc_satellite_dish_think
void misc_satellite_dish_think(edict_t *self)
Definition: g_misc.c:1445
cplane_s
Definition: q_shared.h:409
EF_ANIM_ALL
#define EF_ANIM_ALL
Definition: q_shared.h:569
SP_light_mine2
void SP_light_mine2(edict_t *ent)
Definition: g_misc.c:1484
VelocityForDamage
void VelocityForDamage(int damage, vec3_t v)
Definition: g_misc.c:58
G_PickTarget
edict_t * G_PickTarget(char *targetname)
Definition: g_utils.c:118
edict_s::enemy
edict_t * enemy
Definition: g_local.h:1070
edict_s::teamchain
edict_t * teamchain
Definition: g_local.h:1075
game_import_t::linkentity
void(* linkentity)(edict_t *ent)
Definition: game.h:138
entity_state_s::angles
vec3_t angles
Definition: q_shared.h:1174
train_use
void train_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_func.c:1633
pmove_state_t::pm_flags
byte pm_flags
Definition: q_shared.h:496
misc_satellite_dish_use
void misc_satellite_dish_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_misc.c:1452
edict_s::die
void(* die)(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: g_local.h:1043
MULTICAST_PVS
@ MULTICAST_PVS
Definition: q_shared.h:111
START_OFF
#define START_OFF
Definition: g_misc.c:543
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:127
Com_sprintf
void Com_sprintf(char *dest, int size, char *fmt,...)
Definition: q_shared.c:1236
edict_s::absmin
vec3_t absmin
Definition: g_local.h:985
edict_s::target
char * target
Definition: g_local.h:1011
pmove_state_t::pm_time
byte pm_time
Definition: q_shared.h:497
count
GLint GLsizei count
Definition: qgl_win.c:128
ThrowDebris
void ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin)
Definition: g_misc.c:286
moveinfo_t::speed
float speed
Definition: g_local.h:383
gclient_s::resp
client_respawn_t resp
Definition: g_local.h:885
g_local.h
T_RadiusDamage
void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod)
Definition: g_combat.c:548
edict_s::health
int health
Definition: g_local.h:1051
AI_NOSTEP
#define AI_NOSTEP
Definition: g_local.h:137