Quake II RTX doxygen  1.0 dev
g_monster.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 modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 #include "g_local.h"
19 
20 
21 //
22 // monster weapons
23 //
24 
25 //FIXME mosnters should call these with a totally accurate direction
26 // and we can mess it up based on skill. Spread should be for normal
27 // and we can tighten or loosen based on skill. We could muck with
28 // the damages too, but I'm not sure that's such a good idea.
29 void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype)
30 {
31  fire_bullet(self, start, dir, damage, kick, hspread, vspread, MOD_UNKNOWN);
32 
33  gi.WriteByte(svc_muzzleflash2);
34  gi.WriteShort(self - g_edicts);
35  gi.WriteByte(flashtype);
36  gi.multicast(start, MULTICAST_PVS);
37 }
38 
39 void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int flashtype)
40 {
41  fire_shotgun(self, start, aimdir, damage, kick, hspread, vspread, count, MOD_UNKNOWN);
42 
43  gi.WriteByte(svc_muzzleflash2);
44  gi.WriteShort(self - g_edicts);
45  gi.WriteByte(flashtype);
46  gi.multicast(start, MULTICAST_PVS);
47 }
48 
49 void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect)
50 {
51  fire_blaster(self, start, dir, damage, speed, effect, qfalse);
52 
53  gi.WriteByte(svc_muzzleflash2);
54  gi.WriteShort(self - g_edicts);
55  gi.WriteByte(flashtype);
56  gi.multicast(start, MULTICAST_PVS);
57 }
58 
59 void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype)
60 {
61  fire_grenade(self, start, aimdir, damage, speed, 2.5, damage + 40);
62 
63  gi.WriteByte(svc_muzzleflash2);
64  gi.WriteShort(self - g_edicts);
65  gi.WriteByte(flashtype);
66  gi.multicast(start, MULTICAST_PVS);
67 }
68 
69 void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype)
70 {
71  fire_rocket(self, start, dir, damage, speed, damage + 20, damage);
72 
73  gi.WriteByte(svc_muzzleflash2);
74  gi.WriteShort(self - g_edicts);
75  gi.WriteByte(flashtype);
76  gi.multicast(start, MULTICAST_PVS);
77 }
78 
79 void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype)
80 {
81  fire_rail(self, start, aimdir, damage, kick);
82 
83  gi.WriteByte(svc_muzzleflash2);
84  gi.WriteShort(self - g_edicts);
85  gi.WriteByte(flashtype);
86  gi.multicast(start, MULTICAST_PVS);
87 }
88 
89 void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int kick, float damage_radius, int flashtype)
90 {
91  fire_bfg(self, start, aimdir, damage, speed, damage_radius);
92 
93  gi.WriteByte(svc_muzzleflash2);
94  gi.WriteShort(self - g_edicts);
95  gi.WriteByte(flashtype);
96  gi.multicast(start, MULTICAST_PVS);
97 }
98 
99 
100 
101 //
102 // Monster utility functions
103 //
104 
105 void M_FliesOff(edict_t *self)
106 {
107  self->s.effects &= ~EF_FLIES;
108  self->s.sound = 0;
109 }
110 
111 void M_FliesOn(edict_t *self)
112 {
113  if (self->waterlevel)
114  return;
115  self->s.effects |= EF_FLIES;
116  self->s.sound = gi.soundindex("infantry/inflies1.wav");
117  self->think = M_FliesOff;
118  self->nextthink = level.time + 60;
119 }
120 
121 void M_FlyCheck(edict_t *self)
122 {
123  if (self->waterlevel)
124  return;
125 
126  if (random() > 0.5)
127  return;
128 
129  self->think = M_FliesOn;
130  self->nextthink = level.time + 5 + 10 * random();
131 }
132 
133 void AttackFinished(edict_t *self, float time)
134 {
135  self->monsterinfo.attack_finished = level.time + time;
136 }
137 
138 
139 void M_CheckGround(edict_t *ent)
140 {
141  vec3_t point;
142  trace_t trace;
143 
144  if (ent->flags & (FL_SWIM | FL_FLY))
145  return;
146 
147  if (ent->velocity[2] > 100) {
148  ent->groundentity = NULL;
149  return;
150  }
151 
152 // if the hull point one-quarter unit down is solid the entity is on ground
153  point[0] = ent->s.origin[0];
154  point[1] = ent->s.origin[1];
155  point[2] = ent->s.origin[2] - 0.25;
156 
157  trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, point, ent, MASK_MONSTERSOLID);
158 
159  // check steepness
160  if (trace.plane.normal[2] < 0.7 && !trace.startsolid) {
161  ent->groundentity = NULL;
162  return;
163  }
164 
165 // ent->groundentity = trace.ent;
166 // ent->groundentity_linkcount = trace.ent->linkcount;
167 // if (!trace.startsolid && !trace.allsolid)
168 // VectorCopy (trace.endpos, ent->s.origin);
169  if (!trace.startsolid && !trace.allsolid) {
170  VectorCopy(trace.endpos, ent->s.origin);
171  ent->groundentity = trace.ent;
172  ent->groundentity_linkcount = trace.ent->linkcount;
173  ent->velocity[2] = 0;
174  }
175 }
176 
177 
178 void M_CatagorizePosition(edict_t *ent)
179 {
180  vec3_t point;
181  int cont;
182 
183 //
184 // get waterlevel
185 //
186  point[0] = ent->s.origin[0];
187  point[1] = ent->s.origin[1];
188  point[2] = ent->s.origin[2] + ent->mins[2] + 1;
189  cont = gi.pointcontents(point);
190 
191  if (!(cont & MASK_WATER)) {
192  ent->waterlevel = 0;
193  ent->watertype = 0;
194  return;
195  }
196 
197  ent->watertype = cont;
198  ent->waterlevel = 1;
199  point[2] += 26;
200  cont = gi.pointcontents(point);
201  if (!(cont & MASK_WATER))
202  return;
203 
204  ent->waterlevel = 2;
205  point[2] += 22;
206  cont = gi.pointcontents(point);
207  if (cont & MASK_WATER)
208  ent->waterlevel = 3;
209 }
210 
211 
212 void M_WorldEffects(edict_t *ent)
213 {
214  int dmg;
215 
216  if (ent->health > 0) {
217  if (!(ent->flags & FL_SWIM)) {
218  if (ent->waterlevel < 3) {
219  ent->air_finished = level.time + 12;
220  } else if (ent->air_finished < level.time) {
221  // drown!
222  if (ent->pain_debounce_time < level.time) {
223  dmg = 2 + 2 * floor(level.time - ent->air_finished);
224  if (dmg > 15)
225  dmg = 15;
226  T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
227  ent->pain_debounce_time = level.time + 1;
228  }
229  }
230  } else {
231  if (ent->waterlevel > 0) {
232  ent->air_finished = level.time + 9;
233  } else if (ent->air_finished < level.time) {
234  // suffocate!
235  if (ent->pain_debounce_time < level.time) {
236  dmg = 2 + 2 * floor(level.time - ent->air_finished);
237  if (dmg > 15)
238  dmg = 15;
239  T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
240  ent->pain_debounce_time = level.time + 1;
241  }
242  }
243  }
244  }
245 
246  if (ent->waterlevel == 0) {
247  if (ent->flags & FL_INWATER) {
248  gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0);
249  ent->flags &= ~FL_INWATER;
250  }
251  return;
252  }
253 
254  if ((ent->watertype & CONTENTS_LAVA) && !(ent->flags & FL_IMMUNE_LAVA)) {
255  if (ent->damage_debounce_time < level.time) {
256  ent->damage_debounce_time = level.time + 0.2;
257  T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 10 * ent->waterlevel, 0, 0, MOD_LAVA);
258  }
259  }
260  if ((ent->watertype & CONTENTS_SLIME) && !(ent->flags & FL_IMMUNE_SLIME)) {
261  if (ent->damage_debounce_time < level.time) {
262  ent->damage_debounce_time = level.time + 1;
263  T_Damage(ent, world, world, vec3_origin, ent->s.origin, vec3_origin, 4 * ent->waterlevel, 0, 0, MOD_SLIME);
264  }
265  }
266 
267  if (!(ent->flags & FL_INWATER)) {
268  if (!(ent->svflags & SVF_DEADMONSTER)) {
269  if (ent->watertype & CONTENTS_LAVA)
270  if (random() <= 0.5)
271  gi.sound(ent, CHAN_BODY, gi.soundindex("player/lava1.wav"), 1, ATTN_NORM, 0);
272  else
273  gi.sound(ent, CHAN_BODY, gi.soundindex("player/lava2.wav"), 1, ATTN_NORM, 0);
274  else if (ent->watertype & CONTENTS_SLIME)
275  gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
276  else if (ent->watertype & CONTENTS_WATER)
277  gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
278  }
279 
280  ent->flags |= FL_INWATER;
281  ent->damage_debounce_time = 0;
282  }
283 }
284 
285 
286 void M_droptofloor(edict_t *ent)
287 {
288  vec3_t end;
289  trace_t trace;
290 
291  ent->s.origin[2] += 1;
292  VectorCopy(ent->s.origin, end);
293  end[2] -= 256;
294 
295  trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
296 
297  if (trace.fraction == 1 || trace.allsolid)
298  return;
299 
300  VectorCopy(trace.endpos, ent->s.origin);
301 
302  gi.linkentity(ent);
303  M_CheckGround(ent);
305 }
306 
307 
308 void M_SetEffects(edict_t *ent)
309 {
310  ent->s.effects &= ~(EF_COLOR_SHELL | EF_POWERSCREEN);
311  ent->s.renderfx &= ~(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE);
312 
313  if (ent->monsterinfo.aiflags & AI_RESURRECTING) {
314  ent->s.effects |= EF_COLOR_SHELL;
315  ent->s.renderfx |= RF_SHELL_RED;
316  }
317 
318  if (ent->health <= 0)
319  return;
320 
321  if (ent->powerarmor_time > level.time) {
322  if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SCREEN) {
323  ent->s.effects |= EF_POWERSCREEN;
324  } else if (ent->monsterinfo.power_armor_type == POWER_ARMOR_SHIELD) {
325  ent->s.effects |= EF_COLOR_SHELL;
326  ent->s.renderfx |= RF_SHELL_GREEN;
327  }
328  }
329 }
330 
331 
332 void M_MoveFrame(edict_t *self)
333 {
334  mmove_t *move;
335  int index;
336 
337  move = self->monsterinfo.currentmove;
338  self->nextthink = level.time + FRAMETIME;
339 
340  if ((self->monsterinfo.nextframe) && (self->monsterinfo.nextframe >= move->firstframe) && (self->monsterinfo.nextframe <= move->lastframe)) {
341  self->s.frame = self->monsterinfo.nextframe;
342  self->monsterinfo.nextframe = 0;
343  } else {
344  if (self->s.frame == move->lastframe) {
345  if (move->endfunc) {
346  move->endfunc(self);
347 
348  // regrab move, endfunc is very likely to change it
349  move = self->monsterinfo.currentmove;
350 
351  // check for death
352  if (self->svflags & SVF_DEADMONSTER)
353  return;
354  }
355  }
356 
357  if (self->s.frame < move->firstframe || self->s.frame > move->lastframe) {
358  self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
359  self->s.frame = move->firstframe;
360  } else {
361  if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) {
362  self->s.frame++;
363  if (self->s.frame > move->lastframe)
364  self->s.frame = move->firstframe;
365  }
366  }
367  }
368 
369  index = self->s.frame - move->firstframe;
370  if (move->frame[index].aifunc) {
371  if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
372  move->frame[index].aifunc(self, move->frame[index].dist * self->monsterinfo.scale);
373  else
374  move->frame[index].aifunc(self, 0);
375  }
376 
377  if (move->frame[index].thinkfunc)
378  move->frame[index].thinkfunc(self);
379 }
380 
381 
382 void monster_think(edict_t *self)
383 {
384  M_MoveFrame(self);
385  if (self->linkcount != self->monsterinfo.linkcount) {
386  self->monsterinfo.linkcount = self->linkcount;
387  M_CheckGround(self);
388  }
389  M_CatagorizePosition(self);
390  M_WorldEffects(self);
391  M_SetEffects(self);
392 }
393 
394 
395 /*
396 ================
397 monster_use
398 
399 Using a monster makes it angry at the current activator
400 ================
401 */
402 void monster_use(edict_t *self, edict_t *other, edict_t *activator)
403 {
404  if (self->enemy)
405  return;
406  if (self->health <= 0)
407  return;
408  if (activator->flags & FL_NOTARGET)
409  return;
410  if (!(activator->client) && !(activator->monsterinfo.aiflags & AI_GOOD_GUY))
411  return;
412 
413 // delay reaction so if the monster is teleported, its sound is still heard
414  self->enemy = activator;
415  FoundTarget(self);
416 }
417 
418 
419 void monster_start_go(edict_t *self);
420 
421 
422 void monster_triggered_spawn(edict_t *self)
423 {
424  self->s.origin[2] += 1;
425  KillBox(self);
426 
427  self->solid = SOLID_BBOX;
428  self->movetype = MOVETYPE_STEP;
429  self->svflags &= ~SVF_NOCLIENT;
430  self->air_finished = level.time + 12;
431  gi.linkentity(self);
432 
433  monster_start_go(self);
434 
435  if (self->enemy && !(self->spawnflags & 1) && !(self->enemy->flags & FL_NOTARGET)) {
436  FoundTarget(self);
437  } else {
438  self->enemy = NULL;
439  }
440 }
441 
442 void monster_triggered_spawn_use(edict_t *self, edict_t *other, edict_t *activator)
443 {
444  // we have a one frame delay here so we don't telefrag the guy who activated us
445  self->think = monster_triggered_spawn;
446  self->nextthink = level.time + FRAMETIME;
447  if (activator->client)
448  self->enemy = activator;
449  self->use = monster_use;
450 }
451 
452 void monster_triggered_start(edict_t *self)
453 {
454  self->solid = SOLID_NOT;
455  self->movetype = MOVETYPE_NONE;
456  self->svflags |= SVF_NOCLIENT;
457  self->nextthink = 0;
458  self->use = monster_triggered_spawn_use;
459 }
460 
461 
462 /*
463 ================
464 monster_death_use
465 
466 When a monster dies, it fires all of its targets with the current
467 enemy as activator.
468 ================
469 */
470 void monster_death_use(edict_t *self)
471 {
472  self->flags &= ~(FL_FLY | FL_SWIM);
473  self->monsterinfo.aiflags &= AI_GOOD_GUY;
474 
475  if (self->item) {
476  Drop_Item(self, self->item);
477  self->item = NULL;
478  }
479 
480  if (self->deathtarget)
481  self->target = self->deathtarget;
482 
483  if (!self->target)
484  return;
485 
486  G_UseTargets(self, self->enemy);
487 }
488 
489 
490 //============================================================================
491 
492 qboolean monster_start(edict_t *self)
493 {
494  if (deathmatch->value) {
495  G_FreeEdict(self);
496  return qfalse;
497  }
498 
499  if ((self->spawnflags & 4) && !(self->monsterinfo.aiflags & AI_GOOD_GUY)) {
500  self->spawnflags &= ~4;
501  self->spawnflags |= 1;
502 // gi.dprintf("fixed spawnflags on %s at %s\n", self->classname, vtos(self->s.origin));
503  }
504 
505  if (!(self->monsterinfo.aiflags & AI_GOOD_GUY))
507 
508  self->nextthink = level.time + FRAMETIME;
509  self->svflags |= SVF_MONSTER;
510  self->s.renderfx |= RF_FRAMELERP;
511  self->takedamage = DAMAGE_AIM;
512  self->air_finished = level.time + 12;
513  self->use = monster_use;
514  self->max_health = self->health;
515  self->clipmask = MASK_MONSTERSOLID;
516 
517  self->s.skinnum = 0;
518  self->deadflag = DEAD_NO;
519  self->svflags &= ~SVF_DEADMONSTER;
520 
521  if (!self->monsterinfo.checkattack)
522  self->monsterinfo.checkattack = M_CheckAttack;
523  VectorCopy(self->s.origin, self->s.old_origin);
524 
525  if (st.item) {
526  self->item = FindItemByClassname(st.item);
527  if (!self->item)
528  gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item);
529  }
530 
531  // randomize what frame they start on
532  if (self->monsterinfo.currentmove)
533  self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1));
534 
535  return qtrue;
536 }
537 
538 void monster_start_go(edict_t *self)
539 {
540  vec3_t v;
541 
542  if (self->health <= 0)
543  return;
544 
545  // check for target to combat_point and change to combattarget
546  if (self->target) {
547  qboolean notcombat;
548  qboolean fixup;
549  edict_t *target;
550 
551  target = NULL;
552  notcombat = qfalse;
553  fixup = qfalse;
554  while ((target = G_Find(target, FOFS(targetname), self->target)) != NULL) {
555  if (strcmp(target->classname, "point_combat") == 0) {
556  self->combattarget = self->target;
557  fixup = qtrue;
558  } else {
559  notcombat = qtrue;
560  }
561  }
562  if (notcombat && self->combattarget)
563  gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin));
564  if (fixup)
565  self->target = NULL;
566  }
567 
568  // validate combattarget
569  if (self->combattarget) {
570  edict_t *target;
571 
572  target = NULL;
573  while ((target = G_Find(target, FOFS(targetname), self->combattarget)) != NULL) {
574  if (strcmp(target->classname, "point_combat") != 0) {
575  gi.dprintf("%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n",
576  self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2],
577  self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1],
578  (int)target->s.origin[2]);
579  }
580  }
581  }
582 
583  if (self->target) {
584  self->goalentity = self->movetarget = G_PickTarget(self->target);
585  if (!self->movetarget) {
586  gi.dprintf("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin));
587  self->target = NULL;
588  self->monsterinfo.pausetime = 100000000;
589  self->monsterinfo.stand(self);
590  } else if (strcmp(self->movetarget->classname, "path_corner") == 0) {
591  VectorSubtract(self->goalentity->s.origin, self->s.origin, v);
592  self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v);
593  self->monsterinfo.walk(self);
594  self->target = NULL;
595  } else {
596  self->goalentity = self->movetarget = NULL;
597  self->monsterinfo.pausetime = 100000000;
598  self->monsterinfo.stand(self);
599  }
600  } else {
601  self->monsterinfo.pausetime = 100000000;
602  self->monsterinfo.stand(self);
603  }
604 
605  self->think = monster_think;
606  self->nextthink = level.time + FRAMETIME;
607 }
608 
609 
610 void walkmonster_start_go(edict_t *self)
611 {
612  if (!(self->spawnflags & 2) && level.time < 1) {
613  M_droptofloor(self);
614 
615  if (self->groundentity)
616  if (!M_walkmove(self, 0, 0))
617  gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin));
618  }
619 
620  if (!self->yaw_speed)
621  self->yaw_speed = 20;
622  self->viewheight = 25;
623 
624  monster_start_go(self);
625 
626  if (self->spawnflags & 2)
628 }
629 
630 void walkmonster_start(edict_t *self)
631 {
632  self->think = walkmonster_start_go;
633  monster_start(self);
634 }
635 
636 
637 void flymonster_start_go(edict_t *self)
638 {
639  if (!M_walkmove(self, 0, 0))
640  gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin));
641 
642  if (!self->yaw_speed)
643  self->yaw_speed = 10;
644  self->viewheight = 25;
645 
646  monster_start_go(self);
647 
648  if (self->spawnflags & 2)
650 }
651 
652 
653 void flymonster_start(edict_t *self)
654 {
655  self->flags |= FL_FLY;
656  self->think = flymonster_start_go;
657  monster_start(self);
658 }
659 
660 
661 void swimmonster_start_go(edict_t *self)
662 {
663  if (!self->yaw_speed)
664  self->yaw_speed = 10;
665  self->viewheight = 10;
666 
667  monster_start_go(self);
668 
669  if (self->spawnflags & 2)
671 }
672 
673 void swimmonster_start(edict_t *self)
674 {
675  self->flags |= FL_SWIM;
676  self->think = swimmonster_start_go;
677  monster_start(self);
678 }
gi
game_import_t gi
Definition: g_main.c:23
AI_RESURRECTING
#define AI_RESURRECTING
Definition: g_local.h:140
AttackFinished
void AttackFinished(edict_t *self, float time)
Definition: g_monster.c:133
deathmatch
cvar_t * deathmatch
Definition: g_main.c:33
monster_fire_rocket
void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype)
Definition: g_monster.c:69
flymonster_start
void flymonster_start(edict_t *self)
Definition: g_monster.c:653
AI_GOOD_GUY
#define AI_GOOD_GUY
Definition: g_local.h:134
FindItemByClassname
gitem_t * FindItemByClassname(char *classname)
Definition: g_items.c:76
monster_start
qboolean monster_start(edict_t *self)
Definition: g_monster.c:492
FRAMETIME
#define FRAMETIME
Definition: g_local.h:75
mmove_t::endfunc
void(* endfunc)(edict_t *self)
Definition: g_local.h:404
monster_fire_blaster
void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect)
Definition: g_monster.c:49
fire_rail
void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick)
Definition: g_weapon.c:615
M_SetEffects
void M_SetEffects(edict_t *ent)
Definition: g_monster.c:308
st
spawn_temp_t st
Definition: g_main.c:25
mmove_t::lastframe
int lastframe
Definition: g_local.h:402
M_walkmove
qboolean M_walkmove(edict_t *ent, float yaw, float dist)
Definition: m_move.c:503
monster_triggered_start
void monster_triggered_start(edict_t *self)
Definition: g_monster.c:452
fire_rocket
void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage)
Definition: g_weapon.c:577
mmove_t::frame
mframe_t * frame
Definition: g_local.h:403
fire_bfg
void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius)
Definition: g_weapon.c:830
svc_muzzleflash2
#define svc_muzzleflash2
Definition: g_local.h:37
walkmonster_start_go
void walkmonster_start_go(edict_t *self)
Definition: g_monster.c:610
G_Find
edict_t * G_Find(edict_t *from, int fieldofs, char *match)
Definition: g_utils.c:43
monster_use
void monster_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_monster.c:402
FOFS
#define FOFS(x)
Definition: g_local.h:498
monster_fire_railgun
void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype)
Definition: g_monster.c:79
M_CheckGround
void M_CheckGround(edict_t *ent)
Definition: g_monster.c:139
vectoyaw
float vectoyaw(vec3_t vec)
Definition: g_utils.c:310
fire_grenade
void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius)
Definition: g_weapon.c:450
monster_start_go
void monster_start_go(edict_t *self)
Definition: g_monster.c:538
flymonster_start_go
void flymonster_start_go(edict_t *self)
Definition: g_monster.c:637
swimmonster_start
void swimmonster_start(edict_t *self)
Definition: g_monster.c:673
MOD_SLIME
#define MOD_SLIME
Definition: g_local.h:475
M_CheckAttack
qboolean M_CheckAttack(edict_t *self)
Definition: g_ai.c:553
g_edicts
edict_t * g_edicts
Definition: g_main.c:31
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:358
other
@ other
Definition: ogg.c:63
MOVETYPE_STEP
@ MOVETYPE_STEP
Definition: g_local.h:192
FL_SWIM
#define FL_SWIM
Definition: g_local.h:60
monster_think
void monster_think(edict_t *self)
Definition: g_monster.c:382
monster_fire_bullet
void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype)
Definition: g_monster.c:29
mframe_t::thinkfunc
void(* thinkfunc)(edict_t *self)
Definition: g_local.h:397
POWER_ARMOR_SHIELD
#define POWER_ARMOR_SHIELD
Definition: g_local.h:158
POWER_ARMOR_SCREEN
#define POWER_ARMOR_SCREEN
Definition: g_local.h:157
vec3_origin
vec3_t vec3_origin
Definition: shared.c:21
FL_INWATER
#define FL_INWATER
Definition: g_local.h:62
monster_triggered_spawn
void monster_triggered_spawn(edict_t *self)
Definition: g_monster.c:422
M_droptofloor
void M_droptofloor(edict_t *ent)
Definition: g_monster.c:286
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:421
M_MoveFrame
void M_MoveFrame(edict_t *self)
Definition: g_monster.c:332
MOVETYPE_NONE
@ MOVETYPE_NONE
Definition: g_local.h:186
AI_HOLD_FRAME
#define AI_HOLD_FRAME
Definition: g_local.h:133
M_CatagorizePosition
void M_CatagorizePosition(edict_t *ent)
Definition: g_monster.c:178
M_WorldEffects
void M_WorldEffects(edict_t *ent)
Definition: g_monster.c:212
mmove_t
Definition: g_local.h:400
M_FliesOn
void M_FliesOn(edict_t *self)
Definition: g_monster.c:111
vtos
char * vtos(vec3_t v)
Definition: g_utils.c:275
monster_triggered_spawn_use
void monster_triggered_spawn_use(edict_t *self, edict_t *other, edict_t *activator)
Definition: g_monster.c:442
random
#define random()
Definition: g_local.h:504
monster_fire_bfg
void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int kick, float damage_radius, int flashtype)
Definition: g_monster.c:89
FL_NOTARGET
#define FL_NOTARGET
Definition: g_local.h:64
mmove_t::firstframe
int firstframe
Definition: g_local.h:401
FoundTarget
void FoundTarget(edict_t *self)
Definition: g_ai.c:328
monster_fire_grenade
void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype)
Definition: g_monster.c:59
walkmonster_start
void walkmonster_start(edict_t *self)
Definition: g_monster.c:630
FL_IMMUNE_SLIME
#define FL_IMMUNE_SLIME
Definition: g_local.h:65
DEAD_NO
#define DEAD_NO
Definition: g_local.h:110
level_locals_t::time
float time
Definition: g_local.h:299
fire_bullet
void fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod)
Definition: g_weapon.c:255
monster_death_use
void monster_death_use(edict_t *self)
Definition: g_monster.c:470
M_FliesOff
void M_FliesOff(edict_t *self)
Definition: g_monster.c:105
DAMAGE_AIM
@ DAMAGE_AIM
Definition: g_local.h:89
world
#define world
Definition: g_local.h:550
spawn_temp_t::item
char * item
Definition: g_local.h:354
G_UseTargets
void G_UseTargets(edict_t *ent, edict_t *activator)
Definition: g_utils.c:166
Drop_Item
edict_t * Drop_Item(edict_t *ent, gitem_t *item)
Definition: g_items.c:798
M_FlyCheck
void M_FlyCheck(edict_t *self)
Definition: g_monster.c:121
level
level_locals_t level
Definition: g_main.c:22
level_locals_t::total_monsters
int total_monsters
Definition: g_local.h:329
MOD_UNKNOWN
#define MOD_UNKNOWN
Definition: g_local.h:457
mframe_t::dist
float dist
Definition: g_local.h:396
swimmonster_start_go
void swimmonster_start_go(edict_t *self)
Definition: g_monster.c:661
FL_FLY
#define FL_FLY
Definition: g_local.h:59
KillBox
qboolean KillBox(edict_t *ent)
Definition: g_utils.c:515
monster_fire_shotgun
void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int flashtype)
Definition: g_monster.c:39
fire_blaster
void fire_blaster(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect, qboolean hyper)
Definition: g_weapon.c:319
FL_IMMUNE_LAVA
#define FL_IMMUNE_LAVA
Definition: g_local.h:66
mframe_t::aifunc
void(* aifunc)(edict_t *self, float dist)
Definition: g_local.h:395
DAMAGE_NO_ARMOR
#define DAMAGE_NO_ARMOR
Definition: g_local.h:648
fire_shotgun
void fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod)
Definition: g_weapon.c:268
G_PickTarget
edict_t * G_PickTarget(char *targetname)
Definition: g_utils.c:114
MOD_LAVA
#define MOD_LAVA
Definition: g_local.h:476
MOD_WATER
#define MOD_WATER
Definition: g_local.h:474
g_local.h