Quake II RTX doxygen  1.0 dev
m_boss32.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 /*
19 ==============================================================================
20 
21 Makron -- Final Boss
22 
23 ==============================================================================
24 */
25 
26 #include "g_local.h"
27 #include "m_boss32.h"
28 
29 qboolean visible(edict_t *self, edict_t *other);
30 
31 void MakronRailgun(edict_t *self);
32 void MakronSaveloc(edict_t *self);
33 void MakronHyperblaster(edict_t *self);
34 void makron_step_left(edict_t *self);
35 void makron_step_right(edict_t *self);
36 void makronBFG(edict_t *self);
37 void makron_dead(edict_t *self);
38 
39 static int sound_pain4;
40 static int sound_pain5;
41 static int sound_pain6;
42 static int sound_death;
43 static int sound_step_left;
44 static int sound_step_right;
45 static int sound_attack_bfg;
46 static int sound_brainsplorch;
47 static int sound_prerailgun;
48 static int sound_popup;
49 static int sound_taunt1;
50 static int sound_taunt2;
51 static int sound_taunt3;
52 static int sound_hit;
53 
54 void makron_taunt(edict_t *self)
55 {
56  float r;
57 
58  r = random();
59  if (r <= 0.3)
60  gi.sound(self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0);
61  else if (r <= 0.6)
62  gi.sound(self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0);
63  else
64  gi.sound(self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0);
65 }
66 
67 //
68 // stand
69 //
70 
72  { ai_stand, 0, NULL },
73  { ai_stand, 0, NULL },
74  { ai_stand, 0, NULL },
75  { ai_stand, 0, NULL },
76  { ai_stand, 0, NULL },
77  { ai_stand, 0, NULL },
78  { ai_stand, 0, NULL },
79  { ai_stand, 0, NULL },
80  { ai_stand, 0, NULL },
81  { ai_stand, 0, NULL }, // 10
82  { ai_stand, 0, NULL },
83  { ai_stand, 0, NULL },
84  { ai_stand, 0, NULL },
85  { ai_stand, 0, NULL },
86  { ai_stand, 0, NULL },
87  { ai_stand, 0, NULL },
88  { ai_stand, 0, NULL },
89  { ai_stand, 0, NULL },
90  { ai_stand, 0, NULL },
91  { ai_stand, 0, NULL }, // 20
92  { ai_stand, 0, NULL },
93  { ai_stand, 0, NULL },
94  { ai_stand, 0, NULL },
95  { ai_stand, 0, NULL },
96  { ai_stand, 0, NULL },
97  { ai_stand, 0, NULL },
98  { ai_stand, 0, NULL },
99  { ai_stand, 0, NULL },
100  { ai_stand, 0, NULL },
101  { ai_stand, 0, NULL }, // 30
102  { ai_stand, 0, NULL },
103  { ai_stand, 0, NULL },
104  { ai_stand, 0, NULL },
105  { ai_stand, 0, NULL },
106  { ai_stand, 0, NULL },
107  { ai_stand, 0, NULL },
108  { ai_stand, 0, NULL },
109  { ai_stand, 0, NULL },
110  { ai_stand, 0, NULL },
111  { ai_stand, 0, NULL }, // 40
112  { ai_stand, 0, NULL },
113  { ai_stand, 0, NULL },
114  { ai_stand, 0, NULL },
115  { ai_stand, 0, NULL },
116  { ai_stand, 0, NULL },
117  { ai_stand, 0, NULL },
118  { ai_stand, 0, NULL },
119  { ai_stand, 0, NULL },
120  { ai_stand, 0, NULL },
121  { ai_stand, 0, NULL }, // 50
122  { ai_stand, 0, NULL },
123  { ai_stand, 0, NULL },
124  { ai_stand, 0, NULL },
125  { ai_stand, 0, NULL },
126  { ai_stand, 0, NULL },
127  { ai_stand, 0, NULL },
128  { ai_stand, 0, NULL },
129  { ai_stand, 0, NULL },
130  { ai_stand, 0, NULL },
131  { ai_stand, 0, NULL } // 60
132 };
134 
135 void makron_stand(edict_t *self)
136 {
137  self->monsterinfo.currentmove = &makron_move_stand;
138 }
139 
141  { ai_run, 3, makron_step_left },
142  { ai_run, 12, NULL },
143  { ai_run, 8, NULL },
144  { ai_run, 8, NULL },
145  { ai_run, 8, makron_step_right },
146  { ai_run, 6, NULL },
147  { ai_run, 12, NULL },
148  { ai_run, 9, NULL },
149  { ai_run, 6, NULL },
150  { ai_run, 12, NULL }
151 };
153 
154 void makron_hit(edict_t *self)
155 {
156  gi.sound(self, CHAN_AUTO, sound_hit, 1, ATTN_NONE, 0);
157 }
158 
159 void makron_popup(edict_t *self)
160 {
161  gi.sound(self, CHAN_BODY, sound_popup, 1, ATTN_NONE, 0);
162 }
163 
164 void makron_step_left(edict_t *self)
165 {
166  gi.sound(self, CHAN_BODY, sound_step_left, 1, ATTN_NORM, 0);
167 }
168 
169 void makron_step_right(edict_t *self)
170 {
171  gi.sound(self, CHAN_BODY, sound_step_right, 1, ATTN_NORM, 0);
172 }
173 
174 void makron_brainsplorch(edict_t *self)
175 {
176  gi.sound(self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM, 0);
177 }
178 
179 void makron_prerailgun(edict_t *self)
180 {
181  gi.sound(self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM, 0);
182 }
183 
184 
186  { ai_walk, 3, makron_step_left },
187  { ai_walk, 12, NULL },
188  { ai_walk, 8, NULL },
189  { ai_walk, 8, NULL },
190  { ai_walk, 8, makron_step_right },
191  { ai_walk, 6, NULL },
192  { ai_walk, 12, NULL },
193  { ai_walk, 9, NULL },
194  { ai_walk, 6, NULL },
195  { ai_walk, 12, NULL }
196 };
198 
199 void makron_walk(edict_t *self)
200 {
201  self->monsterinfo.currentmove = &makron_move_walk;
202 }
203 
204 void makron_run(edict_t *self)
205 {
206  if (self->monsterinfo.aiflags & AI_STAND_GROUND)
207  self->monsterinfo.currentmove = &makron_move_stand;
208  else
209  self->monsterinfo.currentmove = &makron_move_run;
210 }
211 
213  { ai_move, 0, NULL },
214  { ai_move, 0, NULL },
215  { ai_move, 0, NULL },
216  { ai_move, 0, NULL },
217  { ai_move, 0, NULL },
218  { ai_move, 0, NULL },
219  { ai_move, 0, NULL },
220  { ai_move, 0, NULL },
221  { ai_move, 0, NULL },
222  { ai_move, 0, NULL }, // 10
223  { ai_move, 0, NULL },
224  { ai_move, 0, NULL },
225  { ai_move, 0, NULL },
226  { ai_move, 0, NULL },
227  { ai_move, 0, NULL },
228  { ai_move, 0, makron_popup },
229  { ai_move, 0, NULL },
230  { ai_move, 0, NULL },
231  { ai_move, 0, NULL },
232  { ai_move, 0, NULL }, // 20
233  { ai_move, 0, NULL },
234  { ai_move, 0, NULL },
235  { ai_move, 0, NULL },
236  { ai_move, 0, makron_taunt },
237  { ai_move, 0, NULL },
238  { ai_move, 0, NULL },
239  { ai_move, 0, NULL }
240 };
242 
244  { ai_move, 0, NULL },
245  { ai_move, 0, NULL },
246  { ai_move, 0, NULL },
247  { ai_move, 0, NULL }
248 };
250 
252  { ai_move, 0, NULL },
253  { ai_move, 0, NULL },
254  { ai_move, 0, NULL },
255  { ai_move, 0, NULL }
256 };
258 
260  { ai_move, -15, NULL },
261  { ai_move, 3, NULL },
262  { ai_move, -12, NULL },
263  { ai_move, 0, makron_step_left },
264  { ai_move, 0, NULL },
265  { ai_move, 0, NULL },
266  { ai_move, 0, NULL },
267  { ai_move, 0, NULL },
268  { ai_move, 0, NULL },
269  { ai_move, 0, NULL }, // 10
270  { ai_move, 0, NULL },
271  { ai_move, 0, NULL },
272  { ai_move, 0, NULL },
273  { ai_move, 0, NULL },
274  { ai_move, 0, NULL },
275  { ai_move, 11, NULL },
276  { ai_move, 12, NULL },
277  { ai_move, 11, makron_step_right },
278  { ai_move, 0, NULL },
279  { ai_move, 0, NULL }, // 20
280  { ai_move, 0, NULL },
281  { ai_move, 0, NULL },
282  { ai_move, 0, NULL },
283  { ai_move, 0, NULL },
284  { ai_move, 0, NULL },
285  { ai_move, 0, NULL },
286  { ai_move, 0, NULL },
287  { ai_move, 0, NULL },
288  { ai_move, 0, NULL },
289  { ai_move, 0, NULL }, // 30
290  { ai_move, 0, NULL },
291  { ai_move, 0, NULL },
292  { ai_move, 0, NULL },
293  { ai_move, 5, NULL },
294  { ai_move, 7, NULL },
295  { ai_move, 6, makron_step_left },
296  { ai_move, 0, NULL },
297  { ai_move, 0, NULL },
298  { ai_move, -1, NULL },
299  { ai_move, 2, NULL }, // 40
300  { ai_move, 0, NULL },
301  { ai_move, 0, NULL },
302  { ai_move, 0, NULL },
303  { ai_move, 0, NULL },
304  { ai_move, 0, NULL },
305  { ai_move, 0, NULL },
306  { ai_move, 0, NULL },
307  { ai_move, 0, NULL },
308  { ai_move, 0, NULL },
309  { ai_move, 0, NULL }, // 50
310  { ai_move, 0, NULL },
311  { ai_move, 0, NULL },
312  { ai_move, 0, NULL },
313  { ai_move, -6, NULL },
314  { ai_move, -4, NULL },
315  { ai_move, -6, makron_step_right },
316  { ai_move, -4, NULL },
317  { ai_move, -4, makron_step_left },
318  { ai_move, 0, NULL },
319  { ai_move, 0, NULL }, // 60
320  { ai_move, 0, NULL },
321  { ai_move, 0, NULL },
322  { ai_move, -2, NULL },
323  { ai_move, -5, NULL },
324  { ai_move, -3, makron_step_right },
325  { ai_move, -8, NULL },
326  { ai_move, -3, makron_step_left },
327  { ai_move, -7, NULL },
328  { ai_move, -4, NULL },
329  { ai_move, -4, makron_step_right }, // 70
330  { ai_move, -6, NULL },
331  { ai_move, -7, NULL },
332  { ai_move, 0, makron_step_left },
333  { ai_move, 0, NULL },
334  { ai_move, 0, NULL },
335  { ai_move, 0, NULL },
336  { ai_move, 0, NULL },
337  { ai_move, 0, NULL },
338  { ai_move, 0, NULL },
339  { ai_move, 0, NULL }, // 80
340  { ai_move, 0, NULL },
341  { ai_move, 0, NULL },
342  { ai_move, 0, NULL },
343  { ai_move, 0, NULL },
344  { ai_move, 0, NULL },
345  { ai_move, -2, NULL },
346  { ai_move, 0, NULL },
347  { ai_move, 0, NULL },
348  { ai_move, 2, NULL },
349  { ai_move, 0, NULL }, // 90
350  { ai_move, 27, makron_hit },
351  { ai_move, 26, NULL },
353  { ai_move, 0, NULL },
354  { ai_move, 0, NULL } // 95
355 };
357 
359  { ai_move, 0, NULL },
360  { ai_move, 0, NULL },
361  { ai_move, 0, NULL },
362  { ai_move, 0, NULL },
363  { ai_move, 0, NULL },
364  { ai_move, 0, NULL },
365  { ai_move, 0, NULL },
366  { ai_move, 0, NULL },
367  { ai_move, 0, NULL },
368  { ai_move, 0, NULL },
369  { ai_move, 0, NULL },
370  { ai_move, 0, NULL },
371  { ai_move, 0, NULL },
372  { ai_move, 0, NULL },
373  { ai_move, 0, NULL },
374  { ai_move, 0, NULL },
375  { ai_move, 0, NULL },
376  { ai_move, 0, NULL },
377  { ai_move, 0, NULL },
378  { ai_move, 0, NULL }
379 };
381 
383  { ai_move, 0, NULL },
384  { ai_move, 0, NULL },
385  { ai_move, 0, NULL },
386  { ai_move, 0, NULL },
387  { ai_move, 0, NULL },
388  { ai_move, 0, NULL },
389  { ai_move, 0, NULL },
390  { ai_move, 0, NULL },
391  { ai_move, 0, NULL },
392  { ai_move, 0, NULL },
393  { ai_move, 0, NULL },
394  { ai_move, 0, NULL },
395  { ai_move, 0, NULL }
396 };
398 
399 void makronBFG(edict_t *self)
400 {
401  vec3_t forward, right;
402  vec3_t start;
403  vec3_t dir;
404  vec3_t vec;
405 
406  AngleVectors(self->s.angles, forward, right, NULL);
407  G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start);
408 
409  VectorCopy(self->enemy->s.origin, vec);
410  vec[2] += self->enemy->viewheight;
411  VectorSubtract(vec, start, dir);
412  VectorNormalize(dir);
413  gi.sound(self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0);
414  monster_fire_bfg(self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG);
415 }
416 
417 
419  { ai_charge, 0, NULL },
420  { ai_charge, 0, NULL },
421  { ai_charge, 0, NULL },
422  { ai_charge, 0, makronBFG }, // FIXME: BFG Attack here
423  { ai_move, 0, NULL },
424  { ai_move, 0, NULL },
425  { ai_move, 0, NULL },
426  { ai_move, 0, NULL }
427 };
429 
431  { ai_charge, 0, NULL },
432  { ai_charge, 0, NULL },
433  { ai_charge, 0, NULL },
434  { ai_charge, 0, NULL },
435  { ai_move, 0, MakronHyperblaster }, // fire
436  { ai_move, 0, MakronHyperblaster }, // fire
437  { ai_move, 0, MakronHyperblaster }, // fire
438  { ai_move, 0, MakronHyperblaster }, // fire
439  { ai_move, 0, MakronHyperblaster }, // fire
440  { ai_move, 0, MakronHyperblaster }, // fire
441  { ai_move, 0, MakronHyperblaster }, // fire
442  { ai_move, 0, MakronHyperblaster }, // fire
443  { ai_move, 0, MakronHyperblaster }, // fire
444  { ai_move, 0, MakronHyperblaster }, // fire
445  { ai_move, 0, MakronHyperblaster }, // fire
446  { ai_move, 0, MakronHyperblaster }, // fire
447  { ai_move, 0, MakronHyperblaster }, // fire
448  { ai_move, 0, MakronHyperblaster }, // fire
449  { ai_move, 0, MakronHyperblaster }, // fire
450  { ai_move, 0, MakronHyperblaster }, // fire
451  { ai_move, 0, MakronHyperblaster }, // fire
452  { ai_move, 0, NULL },
453  { ai_move, 0, NULL },
454  { ai_move, 0, NULL },
455  { ai_move, 0, NULL },
456  { ai_move, 0, NULL }
457 };
459 
462  { ai_charge, 0, NULL },
463  { ai_charge, 0, NULL },
464  { ai_charge, 0, NULL },
465  { ai_charge, 0, NULL },
466  { ai_charge, 0, NULL },
467  { ai_charge, 0, NULL },
468  { ai_charge, 0, MakronSaveloc },
469  { ai_move, 0, MakronRailgun }, // Fire railgun
470  { ai_move, 0, NULL },
471  { ai_move, 0, NULL },
472  { ai_move, 0, NULL },
473  { ai_move, 0, NULL },
474  { ai_move, 0, NULL },
475  { ai_move, 0, NULL },
476  { ai_move, 0, NULL }
477 };
479 
480 void MakronSaveloc(edict_t *self)
481 {
482  VectorCopy(self->enemy->s.origin, self->pos1); //save for aiming the shot
483  self->pos1[2] += self->enemy->viewheight;
484 }
485 
486 // FIXME: He's not firing from the proper Z
487 void MakronRailgun(edict_t *self)
488 {
489  vec3_t start;
490  vec3_t dir;
491  vec3_t forward, right;
492 
493  AngleVectors(self->s.angles, forward, right, NULL);
494  G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start);
495 
496  // calc direction to where we targted
497  VectorSubtract(self->pos1, start, dir);
498  VectorNormalize(dir);
499 
500  monster_fire_railgun(self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1);
501 }
502 
503 // FIXME: This is all wrong. He's not firing at the proper angles.
504 void MakronHyperblaster(edict_t *self)
505 {
506  vec3_t dir;
507  vec3_t vec;
508  vec3_t start;
509  vec3_t forward, right;
510  int flash_number;
511 
512  flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);
513 
514  AngleVectors(self->s.angles, forward, right, NULL);
515  G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start);
516 
517  if (self->enemy) {
518  VectorCopy(self->enemy->s.origin, vec);
519  vec[2] += self->enemy->viewheight;
520  VectorSubtract(vec, start, vec);
521  vectoangles(vec, vec);
522  dir[0] = vec[0];
523  } else {
524  dir[0] = 0;
525  }
526  if (self->s.frame <= FRAME_attak413)
527  dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413);
528  else
529  dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421);
530  dir[2] = 0;
531 
532  AngleVectors(dir, forward, NULL, NULL);
533 
534  monster_fire_blaster(self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER);
535 }
536 
537 
538 void makron_pain(edict_t *self, edict_t *other, float kick, int damage)
539 {
540 
541  if (self->health < (self->max_health / 2))
542  self->s.skinnum = 1;
543 
544  if (level.time < self->pain_debounce_time)
545  return;
546 
547  // Lessen the chance of him going into his pain frames
548  if (damage <= 25)
549  if (random() < 0.2)
550  return;
551 
552  self->pain_debounce_time = level.time + 3;
553  if (skill->value == 3)
554  return; // no pain anims in nightmare
555 
556 
557  if (damage <= 40) {
558  gi.sound(self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE, 0);
559  self->monsterinfo.currentmove = &makron_move_pain4;
560  } else if (damage <= 110) {
561  gi.sound(self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE, 0);
562  self->monsterinfo.currentmove = &makron_move_pain5;
563  } else {
564  if (damage <= 150) {
565  if (random() <= 0.45) {
566  gi.sound(self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE, 0);
567  self->monsterinfo.currentmove = &makron_move_pain6;
568  }
569  } else {
570  if (random() <= 0.35) {
571  gi.sound(self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE, 0);
572  self->monsterinfo.currentmove = &makron_move_pain6;
573  }
574  }
575  }
576 }
577 
578 void makron_sight(edict_t *self, edict_t *other)
579 {
580  self->monsterinfo.currentmove = &makron_move_sight;
581 }
582 
583 void makron_attack(edict_t *self)
584 {
585  float r;
586 
587  r = random();
588 
589  if (r <= 0.3)
590  self->monsterinfo.currentmove = &makron_move_attack3;
591  else if (r <= 0.6)
592  self->monsterinfo.currentmove = &makron_move_attack4;
593  else
594  self->monsterinfo.currentmove = &makron_move_attack5;
595 }
596 
597 /*
598 ---
599 Makron Torso. This needs to be spawned in
600 ---
601 */
602 
603 void makron_torso_think(edict_t *self)
604 {
605  if (++self->s.frame < 365)
606  self->nextthink = level.time + FRAMETIME;
607  else {
608  self->s.frame = 346;
609  self->nextthink = level.time + FRAMETIME;
610  }
611 }
612 
613 void makron_torso(edict_t *ent)
614 {
615  ent->movetype = MOVETYPE_NONE;
616  ent->solid = SOLID_NOT;
617  VectorSet(ent->mins, -8, -8, 0);
618  VectorSet(ent->maxs, 8, 8, 8);
619  ent->s.frame = 346;
620  ent->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2");
621  ent->think = makron_torso_think;
622  ent->nextthink = level.time + 2 * FRAMETIME;
623  ent->s.sound = gi.soundindex("makron/spine.wav");
624  gi.linkentity(ent);
625 }
626 
627 
628 //
629 // death
630 //
631 
632 void makron_dead(edict_t *self)
633 {
634  VectorSet(self->mins, -60, -60, 0);
635  VectorSet(self->maxs, 60, 60, 72);
636  self->movetype = MOVETYPE_TOSS;
637  self->svflags |= SVF_DEADMONSTER;
638  self->nextthink = 0;
639  gi.linkentity(self);
640 }
641 
642 
643 void makron_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
644 {
645  edict_t *tempent;
646 
647  int n;
648 
649  self->s.sound = 0;
650  // check for gib
651  if (self->health <= self->gib_health) {
652  gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
653  for (n = 0; n < 1 /*4*/; n++)
654  ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
655  for (n = 0; n < 4; n++)
656  ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
657  ThrowHead(self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
658  self->deadflag = DEAD_DEAD;
659  return;
660  }
661 
662  if (self->deadflag == DEAD_DEAD)
663  return;
664 
665 // regular death
666  gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
667  self->deadflag = DEAD_DEAD;
668  self->takedamage = DAMAGE_YES;
669 
670  tempent = G_Spawn();
671  VectorCopy(self->s.origin, tempent->s.origin);
672  VectorCopy(self->s.angles, tempent->s.angles);
673  tempent->s.origin[1] -= 84;
674  makron_torso(tempent);
675 
676  self->monsterinfo.currentmove = &makron_move_death2;
677 
678 }
679 
680 qboolean Makron_CheckAttack(edict_t *self)
681 {
682  vec3_t spot1, spot2;
683  vec3_t temp;
684  float chance;
685  trace_t tr;
686  int enemy_range;
687  float enemy_yaw;
688 
689  if (self->enemy->health > 0) {
690  // see if any entities are in the way of the shot
691  VectorCopy(self->s.origin, spot1);
692  spot1[2] += self->viewheight;
693  VectorCopy(self->enemy->s.origin, spot2);
694  spot2[2] += self->enemy->viewheight;
695 
696  tr = gi.trace(spot1, NULL, NULL, spot2, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA);
697 
698  // do we have a clear shot?
699  if (tr.ent != self->enemy)
700  return qfalse;
701  }
702 
703  enemy_range = range(self, self->enemy);
704  VectorSubtract(self->enemy->s.origin, self->s.origin, temp);
705  enemy_yaw = vectoyaw(temp);
706 
707  self->ideal_yaw = enemy_yaw;
708 
709 
710  // melee attack
711  if (enemy_range == RANGE_MELEE) {
712  if (self->monsterinfo.melee)
713  self->monsterinfo.attack_state = AS_MELEE;
714  else
715  self->monsterinfo.attack_state = AS_MISSILE;
716  return qtrue;
717  }
718 
719 // missile attack
720  if (!self->monsterinfo.attack)
721  return qfalse;
722 
723  if (level.time < self->monsterinfo.attack_finished)
724  return qfalse;
725 
726  if (enemy_range == RANGE_FAR)
727  return qfalse;
728 
729  if (self->monsterinfo.aiflags & AI_STAND_GROUND) {
730  chance = 0.4;
731  } else if (enemy_range == RANGE_MELEE) {
732  chance = 0.8;
733  } else if (enemy_range == RANGE_NEAR) {
734  chance = 0.4;
735  } else if (enemy_range == RANGE_MID) {
736  chance = 0.2;
737  } else {
738  return qfalse;
739  }
740 
741  if (random() < chance) {
742  self->monsterinfo.attack_state = AS_MISSILE;
743  self->monsterinfo.attack_finished = level.time + 2 * random();
744  return qtrue;
745  }
746 
747  if (self->flags & FL_FLY) {
748  if (random() < 0.3)
749  self->monsterinfo.attack_state = AS_SLIDING;
750  else
751  self->monsterinfo.attack_state = AS_STRAIGHT;
752  }
753 
754  return qfalse;
755 }
756 
757 
758 //
759 // monster_makron
760 //
761 
762 void MakronPrecache(void)
763 {
764  sound_pain4 = gi.soundindex("makron/pain3.wav");
765  sound_pain5 = gi.soundindex("makron/pain2.wav");
766  sound_pain6 = gi.soundindex("makron/pain1.wav");
767  sound_death = gi.soundindex("makron/death.wav");
768  sound_step_left = gi.soundindex("makron/step1.wav");
769  sound_step_right = gi.soundindex("makron/step2.wav");
770  sound_attack_bfg = gi.soundindex("makron/bfg_fire.wav");
771  sound_brainsplorch = gi.soundindex("makron/brain1.wav");
772  sound_prerailgun = gi.soundindex("makron/rail_up.wav");
773  sound_popup = gi.soundindex("makron/popup.wav");
774  sound_taunt1 = gi.soundindex("makron/voice4.wav");
775  sound_taunt2 = gi.soundindex("makron/voice3.wav");
776  sound_taunt3 = gi.soundindex("makron/voice.wav");
777  sound_hit = gi.soundindex("makron/bhit.wav");
778 
779  gi.modelindex("models/monsters/boss3/rider/tris.md2");
780 }
781 
782 /*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight
783 */
784 void SP_monster_makron(edict_t *self)
785 {
786  if (deathmatch->value) {
787  G_FreeEdict(self);
788  return;
789  }
790 
791  MakronPrecache();
792 
793  self->movetype = MOVETYPE_STEP;
794  self->solid = SOLID_BBOX;
795  self->s.modelindex = gi.modelindex("models/monsters/boss3/rider/tris.md2");
796  VectorSet(self->mins, -30, -30, 0);
797  VectorSet(self->maxs, 30, 30, 90);
798 
799  self->health = 3000;
800  self->gib_health = -2000;
801  self->mass = 500;
802 
803  self->pain = makron_pain;
804  self->die = makron_die;
805  self->monsterinfo.stand = makron_stand;
806  self->monsterinfo.walk = makron_walk;
807  self->monsterinfo.run = makron_run;
808  self->monsterinfo.dodge = NULL;
809  self->monsterinfo.attack = makron_attack;
810  self->monsterinfo.melee = NULL;
811  self->monsterinfo.sight = makron_sight;
812  self->monsterinfo.checkattack = Makron_CheckAttack;
813 
814  gi.linkentity(self);
815 
816 // self->monsterinfo.currentmove = &makron_move_stand;
817  self->monsterinfo.currentmove = &makron_move_sight;
818  self->monsterinfo.scale = MODEL_SCALE;
819 
820  walkmonster_start(self);
821 }
822 
823 
824 /*
825 =================
826 MakronSpawn
827 
828 =================
829 */
830 void MakronSpawn(edict_t *self)
831 {
832  vec3_t vec;
833  edict_t *player;
834 
835  SP_monster_makron(self);
836 
837  // jump at player
838  player = level.sight_client;
839  if (!player)
840  return;
841 
842  VectorSubtract(player->s.origin, self->s.origin, vec);
843  self->s.angles[YAW] = vectoyaw(vec);
844  VectorNormalize(vec);
845  VectorMA(vec3_origin, 400, vec, self->velocity);
846  self->velocity[2] = 200;
847  self->groundentity = NULL;
848 }
849 
850 /*
851 =================
852 MakronToss
853 
854 Jorg is just about dead, so set up to launch Makron out
855 =================
856 */
857 void MakronToss(edict_t *self)
858 {
859  edict_t *ent;
860 
861  ent = G_Spawn();
862  ent->nextthink = level.time + 0.8;
863  ent->think = MakronSpawn;
864  ent->target = self->target;
865  VectorCopy(self->s.origin, ent->s.origin);
866 }
FRAME_attak401
#define FRAME_attak401
Definition: m_boss32.h:231
FRAME_stand260
#define FRAME_stand260
Definition: m_boss32.h:495
gi
game_import_t gi
Definition: g_main.c:23
makron_attack
void makron_attack(edict_t *self)
Definition: m_boss32.c:583
RANGE_NEAR
#define RANGE_NEAR
Definition: g_local.h:117
FRAME_death201
#define FRAME_death201
Definition: m_actor.h:33
deathmatch
cvar_t * deathmatch
Definition: g_main.c:33
G_ProjectSource
void G_ProjectSource(const vec3_t point, const vec3_t distance, const vec3_t forward, const vec3_t right, vec3_t result)
Definition: g_utils.c:23
FRAME_attak501
#define FRAME_attak501
Definition: m_boss32.h:257
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
DEAD_DEAD
#define DEAD_DEAD
Definition: g_local.h:112
makron_step_right
void makron_step_right(edict_t *self)
Definition: m_boss32.c:169
G_Spawn
edict_t * G_Spawn(void)
Definition: g_utils.c:391
ThrowGib
void ThrowGib(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:130
makron_dead
void makron_dead(edict_t *self)
Definition: m_boss32.c:632
MakronSaveloc
void MakronSaveloc(edict_t *self)
Definition: m_boss32.c:480
makron_torso
void makron_torso(edict_t *ent)
Definition: m_boss32.c:613
ai_charge
void ai_charge(edict_t *self, float dist)
Definition: g_ai.c:175
level_locals_t::sight_client
edict_t * sight_client
Definition: g_local.h:312
makron_frames_stand
mframe_t makron_frames_stand[]
Definition: m_boss32.c:71
FRAMETIME
#define FRAMETIME
Definition: g_local.h:75
FRAME_pain401
#define FRAME_pain401
Definition: m_boss32.h:401
sound_step_left
static int sound_step_left
Definition: m_boss32.c:43
MakronSpawn
void MakronSpawn(edict_t *self)
Definition: m_boss32.c:830
FRAME_active13
#define FRAME_active13
Definition: m_boss32.h:222
FRAME_pain504
#define FRAME_pain504
Definition: m_boss32.h:408
FRAME_attak413
#define FRAME_attak413
Definition: m_boss32.h:243
MakronToss
void MakronToss(edict_t *self)
Definition: m_boss32.c:857
makron_move_pain5
mmove_t makron_move_pain5
Definition: m_boss32.c:249
FRAME_stand201
#define FRAME_stand201
Definition: m_actor.h:190
AI_STAND_GROUND
#define AI_STAND_GROUND
Definition: g_local.h:126
makron_move_run
mmove_t makron_move_run
Definition: m_boss32.c:152
FRAME_death320
#define FRAME_death320
Definition: m_boss32.h:387
MODEL_SCALE
#define MODEL_SCALE
Definition: m_actor.h:504
SP_monster_makron
void SP_monster_makron(edict_t *self)
Definition: m_boss32.c:784
makron_frames_death3
mframe_t makron_frames_death3[]
Definition: m_boss32.c:358
DAMAGE_YES
@ DAMAGE_YES
Definition: g_local.h:88
vectoyaw
float vectoyaw(vec3_t vec)
Definition: g_utils.c:310
makron_popup
void makron_popup(edict_t *self)
Definition: m_boss32.c:159
sound_step_right
static int sound_step_right
Definition: m_boss32.c:44
sound_attack_bfg
static int sound_attack_bfg
Definition: m_boss32.c:45
FRAME_death301
#define FRAME_death301
Definition: m_actor.h:46
FRAME_active01
#define FRAME_active01
Definition: m_boss32.h:210
sound_prerailgun
static int sound_prerailgun
Definition: m_boss32.c:47
other
@ other
Definition: ogg.c:63
walkmonster_start
void walkmonster_start(edict_t *self)
Definition: g_monster.c:630
MOVETYPE_STEP
@ MOVETYPE_STEP
Definition: g_local.h:192
makron_brainsplorch
void makron_brainsplorch(edict_t *self)
Definition: m_boss32.c:174
FRAME_pain601
#define FRAME_pain601
Definition: m_boss32.h:409
sound_taunt3
static int sound_taunt3
Definition: m_boss32.c:51
makron_hit
void makron_hit(edict_t *self)
Definition: m_boss32.c:154
sound_pain4
static int sound_pain4
Definition: m_boss32.c:39
sound_taunt1
static int sound_taunt1
Definition: m_boss32.c:49
MakronHyperblaster
void MakronHyperblaster(edict_t *self)
Definition: m_boss32.c:504
makron_frames_pain5
mframe_t makron_frames_pain5[]
Definition: m_boss32.c:243
makron_move_pain4
mmove_t makron_move_pain4
Definition: m_boss32.c:257
makron_frames_walk
mframe_t makron_frames_walk[]
Definition: m_boss32.c:185
vec3_origin
vec3_t vec3_origin
Definition: shared.c:21
vectoangles
void vectoangles(vec3_t vec, vec3_t angles)
Definition: g_utils.c:330
FRAME_walk204
#define FRAME_walk204
Definition: m_boss32.h:499
makron_die
void makron_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: m_boss32.c:643
m_boss32.h
FRAME_pain404
#define FRAME_pain404
Definition: m_boss32.h:404
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:421
GIB_METALLIC
#define GIB_METALLIC
Definition: g_local.h:123
MOVETYPE_NONE
@ MOVETYPE_NONE
Definition: g_local.h:186
MakronPrecache
void MakronPrecache(void)
Definition: m_boss32.c:762
AS_SLIDING
#define AS_SLIDING
Definition: g_local.h:144
forward
static vec3_t forward
Definition: p_view.c:27
AS_MISSILE
#define AS_MISSILE
Definition: g_local.h:146
makron_frames_attack4
mframe_t makron_frames_attack4[]
Definition: m_boss32.c:430
sound_pain6
static int sound_pain6
Definition: m_boss32.c:41
makron_stand
void makron_stand(edict_t *self)
Definition: m_boss32.c:135
FRAME_attak301
#define FRAME_attak301
Definition: m_boss32.h:223
mframe_t
Definition: g_local.h:394
mmove_t
Definition: g_local.h:400
makron_move_attack5
mmove_t makron_move_attack5
Definition: m_boss32.c:478
ai_walk
void ai_walk(edict_t *self, float dist)
Definition: g_ai.c:148
random
#define random()
Definition: g_local.h:504
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: shared.c:23
FRAME_pain501
#define FRAME_pain501
Definition: m_boss32.h:405
FRAME_death295
#define FRAME_death295
Definition: m_boss32.h:367
makron_taunt
void makron_taunt(edict_t *self)
Definition: m_boss32.c:54
makron_frames_pain6
mframe_t makron_frames_pain6[]
Definition: m_boss32.c:212
sound_pain5
static int sound_pain5
Definition: m_boss32.c:40
makron_move_stand
mmove_t makron_move_stand
Definition: m_boss32.c:133
FRAME_attak426
#define FRAME_attak426
Definition: m_boss32.h:256
skill
cvar_t * skill
Definition: g_main.c:36
makron_frames_run
mframe_t makron_frames_run[]
Definition: m_boss32.c:140
makron_walk
void makron_walk(edict_t *self)
Definition: m_boss32.c:199
visible
qboolean visible(edict_t *self, edict_t *other)
Definition: g_ai.c:268
sound_brainsplorch
static int sound_brainsplorch
Definition: m_boss32.c:46
makron_frames_sight
mframe_t makron_frames_sight[]
Definition: m_boss32.c:382
ai_move
void ai_move(edict_t *self, float dist)
Definition: g_ai.c:86
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
level_locals_t::time
float time
Definition: g_local.h:299
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
FRAME_attak421
#define FRAME_attak421
Definition: m_boss32.h:251
Makron_CheckAttack
qboolean Makron_CheckAttack(edict_t *self)
Definition: m_boss32.c:680
makron_move_death3
mmove_t makron_move_death3
Definition: m_boss32.c:380
makron_move_death2
mmove_t makron_move_death2
Definition: m_boss32.c:356
FRAME_walk213
#define FRAME_walk213
Definition: m_boss32.h:508
makronBFG
void makronBFG(edict_t *self)
Definition: m_boss32.c:399
sound_popup
static int sound_popup
Definition: m_boss32.c:48
RANGE_MELEE
#define RANGE_MELEE
Definition: g_local.h:116
makron_frames_death2
mframe_t makron_frames_death2[]
Definition: m_boss32.c:259
makron_move_attack3
mmove_t makron_move_attack3
Definition: m_boss32.c:428
right
static vec3_t right
Definition: p_view.c:27
ai_run
void ai_run(edict_t *self, float dist)
Definition: g_ai.c:821
enemy_range
int enemy_range
Definition: g_ai.c:28
GIB_ORGANIC
#define GIB_ORGANIC
Definition: g_local.h:122
makron_step_left
void makron_step_left(edict_t *self)
Definition: m_boss32.c:164
level
level_locals_t level
Definition: g_main.c:22
makron_frames_attack3
mframe_t makron_frames_attack3[]
Definition: m_boss32.c:418
RANGE_MID
#define RANGE_MID
Definition: g_local.h:118
FRAME_attak405
#define FRAME_attak405
Definition: m_boss32.h:235
makron_frames_attack5
mframe_t makron_frames_attack5[]
Definition: m_boss32.c:460
FL_FLY
#define FL_FLY
Definition: g_local.h:59
monster_flash_offset
const vec3_t monster_flash_offset[256]
Definition: m_flash.c:25
FRAME_attak516
#define FRAME_attak516
Definition: m_boss32.h:272
ThrowHead
void ThrowHead(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:175
makron_move_pain6
mmove_t makron_move_pain6
Definition: m_boss32.c:241
FRAME_pain627
#define FRAME_pain627
Definition: m_boss32.h:435
MOVETYPE_TOSS
@ MOVETYPE_TOSS
Definition: g_local.h:194
range
int range(edict_t *self, edict_t *other)
Definition: g_ai.c:245
sound_taunt2
static int sound_taunt2
Definition: m_boss32.c:50
makron_sight
void makron_sight(edict_t *self, edict_t *other)
Definition: m_boss32.c:578
MakronRailgun
void MakronRailgun(edict_t *self)
Definition: m_boss32.c:487
makron_move_attack4
mmove_t makron_move_attack4
Definition: m_boss32.c:458
makron_prerailgun
void makron_prerailgun(edict_t *self)
Definition: m_boss32.c:179
sound_hit
static int sound_hit
Definition: m_boss32.c:52
AS_MELEE
#define AS_MELEE
Definition: g_local.h:145
RANGE_FAR
#define RANGE_FAR
Definition: g_local.h:119
enemy_yaw
float enemy_yaw
Definition: g_ai.c:29
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
makron_pain
void makron_pain(edict_t *self, edict_t *other, float kick, int damage)
Definition: m_boss32.c:538
sound_death
static int sound_death
Definition: m_boss32.c:42
makron_frames_pain4
mframe_t makron_frames_pain4[]
Definition: m_boss32.c:251
makron_torso_think
void makron_torso_think(edict_t *self)
Definition: m_boss32.c:603
ai_stand
void ai_stand(edict_t *self, float dist)
Definition: g_ai.c:100
makron_move_walk
mmove_t makron_move_walk
Definition: m_boss32.c:197
FRAME_attak308
#define FRAME_attak308
Definition: m_boss32.h:230
makron_move_sight
mmove_t makron_move_sight
Definition: m_boss32.c:397
g_local.h
makron_run
void makron_run(edict_t *self)
Definition: m_boss32.c:204
AS_STRAIGHT
#define AS_STRAIGHT
Definition: g_local.h:143