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 /*
21 ==============================================================================
22
23 boss2
24
25 ==============================================================================
26 */
27
28 #include "g_local.h"
29 #include "m_boss2.h"
30
31 void BossExplode (edict_t *self);
32
33 qBool infront (edict_t *self, edict_t *other);
34
35 static int sound_pain1;
36 static int sound_pain2;
37 static int sound_pain3;
38 static int sound_death;
39 static int sound_search1;
40
boss2_search(edict_t * self)41 void boss2_search (edict_t *self)
42 {
43 if (random() < 0.5)
44 gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0);
45 }
46
47 void boss2_run (edict_t *self);
48 void boss2_stand (edict_t *self);
49 void boss2_dead (edict_t *self);
50 void boss2_attack (edict_t *self);
51 void boss2_attack_mg (edict_t *self);
52 void boss2_reattack_mg (edict_t *self);
53 void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
54
Boss2Rocket(edict_t * self)55 void Boss2Rocket (edict_t *self)
56 {
57 vec3_t forward, right;
58 vec3_t start;
59 vec3_t dir;
60 vec3_t vec;
61
62 Angles_Vectors (self->s.angles, forward, right, NULL);
63
64 //1
65 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_ROCKET_1], forward, right, start);
66 Vec3Copy (self->enemy->s.origin, vec);
67 vec[2] += self->enemy->viewheight;
68 Vec3Subtract (vec, start, dir);
69 VectorNormalizef (dir, dir);
70 monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1);
71
72 //2
73 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_ROCKET_2], forward, right, start);
74 Vec3Copy (self->enemy->s.origin, vec);
75 vec[2] += self->enemy->viewheight;
76 Vec3Subtract (vec, start, dir);
77 VectorNormalizef (dir, dir);
78 monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2);
79
80 //3
81 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_ROCKET_3], forward, right, start);
82 Vec3Copy (self->enemy->s.origin, vec);
83 vec[2] += self->enemy->viewheight;
84 Vec3Subtract (vec, start, dir);
85 VectorNormalizef (dir, dir);
86 monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3);
87
88 //4
89 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_ROCKET_4], forward, right, start);
90 Vec3Copy (self->enemy->s.origin, vec);
91 vec[2] += self->enemy->viewheight;
92 Vec3Subtract (vec, start, dir);
93 VectorNormalizef (dir, dir);
94 monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4);
95 }
96
boss2_firebullet_right(edict_t * self)97 void boss2_firebullet_right (edict_t *self)
98 {
99 vec3_t forward, right, target;
100 vec3_t start;
101
102 Angles_Vectors (self->s.angles, forward, right, NULL);
103 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start);
104
105 Vec3MA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
106 target[2] += self->enemy->viewheight;
107 Vec3Subtract (target, start, forward);
108 VectorNormalizef (forward, forward);
109
110 monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1);
111 }
112
boss2_firebullet_left(edict_t * self)113 void boss2_firebullet_left (edict_t *self)
114 {
115 vec3_t forward, right, target;
116 vec3_t start;
117
118 Angles_Vectors (self->s.angles, forward, right, NULL);
119 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start);
120
121 Vec3MA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
122
123 target[2] += self->enemy->viewheight;
124 Vec3Subtract (target, start, forward);
125 VectorNormalizef (forward, forward);
126
127 monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1);
128 }
129
Boss2MachineGun(edict_t * self)130 void Boss2MachineGun (edict_t *self)
131 {
132 /* vec3_t forward, right;
133 vec3_t start;
134 vec3_t dir;
135 vec3_t vec;
136 int flash_number;
137
138 Angles_Vectors (self->s.angles, forward, right, NULL);
139
140 flash_number = MZ2_BOSS2_MACHINEGUN_1 + (self->s.frame - FRAME_attack10);
141 G_ProjectSource (self->s.origin, dumb_and_hacky_monster_MuzzFlashOffset[flash_number], forward, right, start);
142
143 Vec3Copy (self->enemy->s.origin, vec);
144 vec[2] += self->enemy->viewheight;
145 Vec3Subtract (vec, start, dir);
146 VectorNormalizef (dir);
147 monster_fire_bullet (self, start, dir, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
148 */
149 boss2_firebullet_left(self);
150 boss2_firebullet_right(self);
151 }
152
153
154 mframe_t boss2_frames_stand [] =
155 {
156 ai_stand, 0, NULL,
157 ai_stand, 0, NULL,
158 ai_stand, 0, NULL,
159 ai_stand, 0, NULL,
160 ai_stand, 0, NULL,
161 ai_stand, 0, NULL,
162 ai_stand, 0, NULL,
163 ai_stand, 0, NULL,
164 ai_stand, 0, NULL,
165 ai_stand, 0, NULL,
166 ai_stand, 0, NULL,
167 ai_stand, 0, NULL,
168 ai_stand, 0, NULL,
169 ai_stand, 0, NULL,
170 ai_stand, 0, NULL,
171 ai_stand, 0, NULL,
172 ai_stand, 0, NULL,
173 ai_stand, 0, NULL,
174 ai_stand, 0, NULL,
175 ai_stand, 0, NULL,
176 ai_stand, 0, NULL
177 };
178 mmove_t boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL};
179
180 mframe_t boss2_frames_fidget [] =
181 {
182 ai_stand, 0, NULL,
183 ai_stand, 0, NULL,
184 ai_stand, 0, NULL,
185 ai_stand, 0, NULL,
186 ai_stand, 0, NULL,
187 ai_stand, 0, NULL,
188 ai_stand, 0, NULL,
189 ai_stand, 0, NULL,
190 ai_stand, 0, NULL,
191 ai_stand, 0, NULL,
192 ai_stand, 0, NULL,
193 ai_stand, 0, NULL,
194 ai_stand, 0, NULL,
195 ai_stand, 0, NULL,
196 ai_stand, 0, NULL,
197 ai_stand, 0, NULL,
198 ai_stand, 0, NULL,
199 ai_stand, 0, NULL,
200 ai_stand, 0, NULL,
201 ai_stand, 0, NULL,
202 ai_stand, 0, NULL,
203 ai_stand, 0, NULL,
204 ai_stand, 0, NULL,
205 ai_stand, 0, NULL,
206 ai_stand, 0, NULL,
207 ai_stand, 0, NULL,
208 ai_stand, 0, NULL,
209 ai_stand, 0, NULL,
210 ai_stand, 0, NULL,
211 ai_stand, 0, NULL
212 };
213 mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL};
214
215 mframe_t boss2_frames_walk [] =
216 {
217 ai_walk, 8, NULL,
218 ai_walk, 8, NULL,
219 ai_walk, 8, NULL,
220 ai_walk, 8, NULL,
221 ai_walk, 8, NULL,
222 ai_walk, 8, NULL,
223 ai_walk, 8, NULL,
224 ai_walk, 8, NULL,
225 ai_walk, 8, NULL,
226 ai_walk, 8, NULL,
227 ai_walk, 8, NULL,
228 ai_walk, 8, NULL,
229 ai_walk, 8, NULL,
230 ai_walk, 8, NULL,
231 ai_walk, 8, NULL,
232 ai_walk, 8, NULL,
233 ai_walk, 8, NULL,
234 ai_walk, 8, NULL,
235 ai_walk, 8, NULL,
236 ai_walk, 8, NULL
237 };
238 mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL};
239
240
241 mframe_t boss2_frames_run [] =
242 {
243 ai_run, 8, NULL,
244 ai_run, 8, NULL,
245 ai_run, 8, NULL,
246 ai_run, 8, NULL,
247 ai_run, 8, NULL,
248 ai_run, 8, NULL,
249 ai_run, 8, NULL,
250 ai_run, 8, NULL,
251 ai_run, 8, NULL,
252 ai_run, 8, NULL,
253 ai_run, 8, NULL,
254 ai_run, 8, NULL,
255 ai_run, 8, NULL,
256 ai_run, 8, NULL,
257 ai_run, 8, NULL,
258 ai_run, 8, NULL,
259 ai_run, 8, NULL,
260 ai_run, 8, NULL,
261 ai_run, 8, NULL,
262 ai_run, 8, NULL
263 };
264 mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL};
265
266 mframe_t boss2_frames_attack_pre_mg [] =
267 {
268 ai_charge, 1, NULL,
269 ai_charge, 1, NULL,
270 ai_charge, 1, NULL,
271 ai_charge, 1, NULL,
272 ai_charge, 1, NULL,
273 ai_charge, 1, NULL,
274 ai_charge, 1, NULL,
275 ai_charge, 1, NULL,
276 ai_charge, 1, boss2_attack_mg
277 };
278 mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL};
279
280
281 // Loop this
282 mframe_t boss2_frames_attack_mg [] =
283 {
284 ai_charge, 1, Boss2MachineGun,
285 ai_charge, 1, Boss2MachineGun,
286 ai_charge, 1, Boss2MachineGun,
287 ai_charge, 1, Boss2MachineGun,
288 ai_charge, 1, Boss2MachineGun,
289 ai_charge, 1, boss2_reattack_mg
290 };
291 mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL};
292
293 mframe_t boss2_frames_attack_post_mg [] =
294 {
295 ai_charge, 1, NULL,
296 ai_charge, 1, NULL,
297 ai_charge, 1, NULL,
298 ai_charge, 1, NULL
299 };
300 mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run};
301
302 mframe_t boss2_frames_attack_rocket [] =
303 {
304 ai_charge, 1, NULL,
305 ai_charge, 1, NULL,
306 ai_charge, 1, NULL,
307 ai_charge, 1, NULL,
308 ai_charge, 1, NULL,
309 ai_charge, 1, NULL,
310 ai_charge, 1, NULL,
311 ai_charge, 1, NULL,
312 ai_charge, 1, NULL,
313 ai_charge, 1, NULL,
314 ai_charge, 1, NULL,
315 ai_charge, 1, NULL,
316 ai_move, -20, Boss2Rocket,
317 ai_charge, 1, NULL,
318 ai_charge, 1, NULL,
319 ai_charge, 1, NULL,
320 ai_charge, 1, NULL,
321 ai_charge, 1, NULL,
322 ai_charge, 1, NULL,
323 ai_charge, 1, NULL,
324 ai_charge, 1, NULL
325 };
326 mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run};
327
328 mframe_t boss2_frames_pain_heavy [] =
329 {
330 ai_move, 0, NULL,
331 ai_move, 0, NULL,
332 ai_move, 0, NULL,
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,
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, 0, NULL,
346 ai_move, 0, NULL,
347 ai_move, 0, NULL
348 };
349 mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run};
350
351 mframe_t boss2_frames_pain_light [] =
352 {
353 ai_move, 0, NULL,
354 ai_move, 0, NULL,
355 ai_move, 0, NULL,
356 ai_move, 0, NULL
357 };
358 mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run};
359
360 mframe_t boss2_frames_death [] =
361 {
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 ai_move, 0, NULL,
380 ai_move, 0, NULL,
381 ai_move, 0, NULL,
382 ai_move, 0, NULL,
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 ai_move, 0, NULL,
397 ai_move, 0, NULL,
398 ai_move, 0, NULL,
399 ai_move, 0, NULL,
400 ai_move, 0, NULL,
401 ai_move, 0, NULL,
402 ai_move, 0, NULL,
403 ai_move, 0, NULL,
404 ai_move, 0, NULL,
405 ai_move, 0, NULL,
406 ai_move, 0, NULL,
407 ai_move, 0, NULL,
408 ai_move, 0, NULL,
409 ai_move, 0, NULL,
410 ai_move, 0, BossExplode
411 };
412 mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead};
413
boss2_stand(edict_t * self)414 void boss2_stand (edict_t *self)
415 {
416 self->monsterinfo.currentmove = &boss2_move_stand;
417 }
418
boss2_run(edict_t * self)419 void boss2_run (edict_t *self)
420 {
421 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
422 self->monsterinfo.currentmove = &boss2_move_stand;
423 else
424 self->monsterinfo.currentmove = &boss2_move_run;
425 }
426
boss2_walk(edict_t * self)427 void boss2_walk (edict_t *self)
428 {
429 self->monsterinfo.currentmove = &boss2_move_walk;
430 }
431
boss2_attack(edict_t * self)432 void boss2_attack (edict_t *self)
433 {
434 vec3_t vec;
435 float range;
436
437 Vec3Subtract (self->enemy->s.origin, self->s.origin, vec);
438 range = Vec3Length (vec);
439
440 if (range <= 125)
441 {
442 self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
443 }
444 else
445 {
446 if (random() <= 0.6)
447 self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
448 else
449 self->monsterinfo.currentmove = &boss2_move_attack_rocket;
450 }
451 }
452
boss2_attack_mg(edict_t * self)453 void boss2_attack_mg (edict_t *self)
454 {
455 self->monsterinfo.currentmove = &boss2_move_attack_mg;
456 }
457
boss2_reattack_mg(edict_t * self)458 void boss2_reattack_mg (edict_t *self)
459 {
460 if ( infront(self, self->enemy) )
461 if (random() <= 0.7)
462 self->monsterinfo.currentmove = &boss2_move_attack_mg;
463 else
464 self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
465 else
466 self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
467 }
468
469
boss2_pain(edict_t * self,edict_t * other,float kick,int damage)470 void boss2_pain (edict_t *self, edict_t *other, float kick, int damage)
471 {
472 if (self->health < (self->max_health / 2))
473 self->s.skinNum = 1;
474
475 if (level.time < self->pain_debounce_time)
476 return;
477
478 self->pain_debounce_time = level.time + 3;
479 // American wanted these at no attenuation
480 if (damage < 10)
481 {
482 gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0);
483 self->monsterinfo.currentmove = &boss2_move_pain_light;
484 }
485 else if (damage < 30)
486 {
487 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0);
488 self->monsterinfo.currentmove = &boss2_move_pain_light;
489 }
490 else
491 {
492 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0);
493 self->monsterinfo.currentmove = &boss2_move_pain_heavy;
494 }
495 }
496
boss2_dead(edict_t * self)497 void boss2_dead (edict_t *self)
498 {
499 Vec3Set (self->mins, -56, -56, 0);
500 Vec3Set (self->maxs, 56, 56, 80);
501 self->movetype = MOVETYPE_TOSS;
502 self->svFlags |= SVF_DEADMONSTER;
503 self->nextthink = 0;
504 gi.linkentity (self);
505 }
506
boss2_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)507 void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
508 {
509 gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
510 self->deadflag = DEAD_DEAD;
511 self->takedamage = DAMAGE_NO;
512 self->count = 0;
513 self->monsterinfo.currentmove = &boss2_move_death;
514 #if 0
515 int n;
516
517 self->s.sound = 0;
518 // check for gib
519 if (self->health <= self->gib_health)
520 {
521 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
522 for (n= 0; n < 2; n++)
523 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
524 for (n= 0; n < 4; n++)
525 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
526 ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
527 self->deadflag = DEAD_DEAD;
528 return;
529 }
530
531 if (self->deadflag == DEAD_DEAD)
532 return;
533
534 self->deadflag = DEAD_DEAD;
535 self->takedamage = DAMAGE_YES;
536 self->monsterinfo.currentmove = &boss2_move_death;
537 #endif
538 }
539
Boss2_CheckAttack(edict_t * self)540 qBool Boss2_CheckAttack (edict_t *self)
541 {
542 vec3_t spot1, spot2;
543 vec3_t temp;
544 float chance;
545 trace_t tr;
546 qBool enemy_infront;
547 int enemy_range;
548 float enemy_yaw;
549
550 if (self->enemy->health > 0)
551 {
552 // see if any entities are in the way of the shot
553 Vec3Copy (self->s.origin, spot1);
554 spot1[2] += self->viewheight;
555 Vec3Copy (self->enemy->s.origin, spot2);
556 spot2[2] += self->enemy->viewheight;
557
558 tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
559
560 // do we have a clear shot?
561 if (tr.ent != self->enemy)
562 return qFalse;
563 }
564
565 enemy_infront = infront(self, self->enemy);
566 enemy_range = range(self, self->enemy);
567 Vec3Subtract (self->enemy->s.origin, self->s.origin, temp);
568 enemy_yaw = VecToYaw(temp);
569
570 self->ideal_yaw = enemy_yaw;
571
572
573 // melee attack
574 if (enemy_range == RANGE_MELEE)
575 {
576 if (self->monsterinfo.melee)
577 self->monsterinfo.attack_state = AS_MELEE;
578 else
579 self->monsterinfo.attack_state = AS_MISSILE;
580 return qTrue;
581 }
582
583 // missile attack
584 if (!self->monsterinfo.attack)
585 return qFalse;
586
587 if (level.time < self->monsterinfo.attack_finished)
588 return qFalse;
589
590 if (enemy_range == RANGE_FAR)
591 return qFalse;
592
593 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
594 {
595 chance = 0.4f;
596 }
597 else if (enemy_range == RANGE_MELEE)
598 {
599 chance = 0.8f;
600 }
601 else if (enemy_range == RANGE_NEAR)
602 {
603 chance = 0.8f;
604 }
605 else if (enemy_range == RANGE_MID)
606 {
607 chance = 0.8f;
608 }
609 else
610 {
611 return qFalse;
612 }
613
614 if (random () < chance)
615 {
616 self->monsterinfo.attack_state = AS_MISSILE;
617 self->monsterinfo.attack_finished = level.time + 2*random();
618 return qTrue;
619 }
620
621 if (self->flags & FL_FLY)
622 {
623 if (random() < 0.3)
624 self->monsterinfo.attack_state = AS_SLIDING;
625 else
626 self->monsterinfo.attack_state = AS_STRAIGHT;
627 }
628
629 return qFalse;
630 }
631
632
633
634 /*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight
635 */
SP_monster_boss2(edict_t * self)636 void SP_monster_boss2 (edict_t *self)
637 {
638 if (deathmatch->floatVal)
639 {
640 G_FreeEdict (self);
641 return;
642 }
643
644 sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav");
645 sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav");
646 sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav");
647 sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav");
648 sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav");
649
650 self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav");
651
652 self->movetype = MOVETYPE_STEP;
653 self->solid = SOLID_BBOX;
654 self->s.modelIndex = gi.modelindex ("models/monsters/boss2/tris.md2");
655 Vec3Set (self->mins, -56, -56, 0);
656 Vec3Set (self->maxs, 56, 56, 80);
657
658 self->health = 2000;
659 self->gib_health = -200;
660 self->mass = 1000;
661
662 self->flags |= FL_IMMUNE_LASER;
663
664 self->pain = boss2_pain;
665 self->die = boss2_die;
666
667 self->monsterinfo.stand = boss2_stand;
668 self->monsterinfo.walk = boss2_walk;
669 self->monsterinfo.run = boss2_run;
670 self->monsterinfo.attack = boss2_attack;
671 self->monsterinfo.search = boss2_search;
672 self->monsterinfo.checkattack = Boss2_CheckAttack;
673 gi.linkentity (self);
674
675 self->monsterinfo.currentmove = &boss2_move_stand;
676 self->monsterinfo.scale = MODEL_SCALE;
677
678 flymonster_start (self);
679 }
680