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