|
|
1.1 root 1: /* 1.1.1.2 ! root 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: /* 1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.