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