|
|
1.1 ! root 1: /* ! 2: ============================================================================== ! 3: ! 4: boss2 ! 5: ! 6: ============================================================================== ! 7: */ ! 8: ! 9: #include "g_local.h" ! 10: #include "m_boss2.h" ! 11: ! 12: void BossExplode (edict_t *self); ! 13: ! 14: qboolean infront (edict_t *self, edict_t *other); ! 15: ! 16: static int sound_pain1; ! 17: static int sound_pain2; ! 18: static int sound_pain3; ! 19: static int sound_death; ! 20: static int sound_search1; ! 21: ! 22: void boss2_search (edict_t *self) ! 23: { ! 24: if (random() < 0.5) ! 25: gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0); ! 26: } ! 27: ! 28: void boss2_run (edict_t *self); ! 29: void boss2_stand (edict_t *self); ! 30: void boss2_dead (edict_t *self); ! 31: void boss2_attack (edict_t *self); ! 32: void boss2_attack_mg (edict_t *self); ! 33: void boss2_reattack_mg (edict_t *self); ! 34: void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); ! 35: ! 36: #define BOSS2_ROCKET_SPEED 750 ! 37: ! 38: void Boss2PredictiveRocket (edict_t *self) ! 39: { ! 40: vec3_t forward, right; ! 41: vec3_t start; ! 42: vec3_t dir; ! 43: vec3_t vec; ! 44: float time, dist; ! 45: ! 46: gi.dprintf("predictive fire\n"); ! 47: ! 48: AngleVectors (self->s.angles, forward, right, NULL); ! 49: ! 50: //1 ! 51: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); ! 52: VectorSubtract(self->enemy->s.origin, start, dir); ! 53: // dir[2] += self->enemy->viewheight; ! 54: dist = VectorLength(dir); ! 55: time = dist / BOSS2_ROCKET_SPEED; ! 56: VectorMA(self->enemy->s.origin, time-0.3, self->enemy->velocity, vec); ! 57: ! 58: // VectorCopy (self->enemy->s.origin, vec); ! 59: // vec[2] += self->enemy->viewheight; ! 60: VectorSubtract (vec, start, dir); ! 61: VectorNormalize (dir); ! 62: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_1); ! 63: ! 64: //2 ! 65: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); ! 66: VectorSubtract(self->enemy->s.origin, start, dir); ! 67: // dir[2] += self->enemy->viewheight; ! 68: dist = VectorLength(dir); ! 69: time = dist / BOSS2_ROCKET_SPEED; ! 70: VectorMA(self->enemy->s.origin, time-0.15, self->enemy->velocity, vec); ! 71: ! 72: // VectorCopy (self->enemy->s.origin, vec); ! 73: // vec[2] += self->enemy->viewheight; ! 74: VectorSubtract (vec, start, dir); ! 75: VectorNormalize (dir); ! 76: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_2); ! 77: ! 78: //3 ! 79: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); ! 80: VectorSubtract(self->enemy->s.origin, start, dir); ! 81: // dir[2] += self->enemy->viewheight; ! 82: dist = VectorLength(dir); ! 83: time = dist / BOSS2_ROCKET_SPEED; ! 84: VectorMA(self->enemy->s.origin, time, self->enemy->velocity, vec); ! 85: ! 86: // VectorCopy (self->enemy->s.origin, vec); ! 87: // vec[2] += self->enemy->viewheight; ! 88: VectorSubtract (vec, start, dir); ! 89: VectorNormalize (dir); ! 90: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_3); ! 91: ! 92: //4 ! 93: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); ! 94: VectorSubtract(self->enemy->s.origin, start, dir); ! 95: // dir[2] += self->enemy->viewheight; ! 96: dist = VectorLength(dir); ! 97: time = dist / BOSS2_ROCKET_SPEED; ! 98: VectorMA(self->enemy->s.origin, time+0.15, self->enemy->velocity, vec); ! 99: ! 100: // VectorCopy (self->enemy->s.origin, vec); ! 101: // vec[2] += self->enemy->viewheight; ! 102: VectorSubtract (vec, start, dir); ! 103: VectorNormalize (dir); ! 104: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_4); ! 105: } ! 106: ! 107: void Boss2Rocket (edict_t *self) ! 108: { ! 109: vec3_t forward, right; ! 110: vec3_t start; ! 111: vec3_t dir; ! 112: vec3_t vec; ! 113: ! 114: if(self->enemy) ! 115: { ! 116: if(self->enemy->client && random() < 0.9) ! 117: { ! 118: Boss2PredictiveRocket(self); ! 119: return; ! 120: } ! 121: } ! 122: ! 123: AngleVectors (self->s.angles, forward, right, NULL); ! 124: ! 125: //1 ! 126: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); ! 127: VectorCopy (self->enemy->s.origin, vec); ! 128: // vec[2] += self->enemy->viewheight; ! 129: vec[2] -= 15; ! 130: VectorSubtract (vec, start, dir); ! 131: VectorNormalize (dir); ! 132: VectorMA (dir, 0.4, right, dir); ! 133: VectorNormalize (dir); ! 134: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1); ! 135: ! 136: //2 ! 137: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); ! 138: VectorCopy (self->enemy->s.origin, vec); ! 139: // vec[2] += self->enemy->viewheight; ! 140: VectorSubtract (vec, start, dir); ! 141: VectorNormalize (dir); ! 142: VectorMA (dir, 0.025, right, dir); ! 143: VectorNormalize (dir); ! 144: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2); ! 145: ! 146: //3 ! 147: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); ! 148: VectorCopy (self->enemy->s.origin, vec); ! 149: // vec[2] += self->enemy->viewheight; ! 150: VectorSubtract (vec, start, dir); ! 151: VectorNormalize (dir); ! 152: VectorMA (dir, -0.025, right, dir); ! 153: VectorNormalize (dir); ! 154: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3); ! 155: ! 156: //4 ! 157: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); ! 158: VectorCopy (self->enemy->s.origin, vec); ! 159: // vec[2] += self->enemy->viewheight; ! 160: vec[2] -= 15; ! 161: VectorSubtract (vec, start, dir); ! 162: VectorNormalize (dir); ! 163: VectorMA (dir, -0.4, right, dir); ! 164: VectorNormalize (dir); ! 165: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4); ! 166: ! 167: //5 ! 168: // G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); ! 169: // VectorCopy (self->enemy->s.origin, vec); ! 170: // vec[2] += self->enemy->viewheight; ! 171: // VectorSubtract (vec, start, dir); ! 172: // VectorNormalize (dir); ! 173: // monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2); ! 174: } ! 175: ! 176: void boss2_firebullet_right (edict_t *self) ! 177: { ! 178: vec3_t forward, right, target; ! 179: vec3_t start; ! 180: ! 181: AngleVectors (self->s.angles, forward, right, NULL); ! 182: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start); ! 183: ! 184: // VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); ! 185: VectorMA (self->enemy->s.origin, 0.2, self->enemy->velocity, target); ! 186: target[2] += self->enemy->viewheight; ! 187: VectorSubtract (target, start, forward); ! 188: VectorNormalize (forward); ! 189: ! 190: monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1); ! 191: // monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1); ! 192: } ! 193: ! 194: void boss2_firebullet_left (edict_t *self) ! 195: { ! 196: vec3_t forward, right, target; ! 197: vec3_t start; ! 198: ! 199: AngleVectors (self->s.angles, forward, right, NULL); ! 200: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start); ! 201: ! 202: // VectorMA (self->enemy->s.origin, 0.2, self->enemy->velocity, target); ! 203: VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); ! 204: ! 205: target[2] += self->enemy->viewheight; ! 206: VectorSubtract (target, start, forward); ! 207: VectorNormalize (forward); ! 208: ! 209: monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1); ! 210: // monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1); ! 211: } ! 212: ! 213: void Boss2MachineGun (edict_t *self) ! 214: { ! 215: /* vec3_t forward, right; ! 216: vec3_t start; ! 217: vec3_t dir; ! 218: vec3_t vec; ! 219: int flash_number; ! 220: ! 221: AngleVectors (self->s.angles, forward, right, NULL); ! 222: ! 223: flash_number = MZ2_BOSS2_MACHINEGUN_1 + (self->s.frame - FRAME_attack10); ! 224: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); ! 225: ! 226: VectorCopy (self->enemy->s.origin, vec); ! 227: vec[2] += self->enemy->viewheight; ! 228: VectorSubtract (vec, start, dir); ! 229: VectorNormalize (dir); ! 230: monster_fire_bullet (self, start, dir, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); ! 231: */ ! 232: boss2_firebullet_left(self); ! 233: boss2_firebullet_right(self); ! 234: } ! 235: ! 236: ! 237: mframe_t boss2_frames_stand [] = ! 238: { ! 239: ai_stand, 0, NULL, ! 240: ai_stand, 0, NULL, ! 241: ai_stand, 0, NULL, ! 242: ai_stand, 0, NULL, ! 243: ai_stand, 0, NULL, ! 244: ai_stand, 0, NULL, ! 245: ai_stand, 0, NULL, ! 246: ai_stand, 0, NULL, ! 247: ai_stand, 0, NULL, ! 248: ai_stand, 0, NULL, ! 249: ai_stand, 0, NULL, ! 250: ai_stand, 0, NULL, ! 251: ai_stand, 0, NULL, ! 252: ai_stand, 0, NULL, ! 253: ai_stand, 0, NULL, ! 254: ai_stand, 0, NULL, ! 255: ai_stand, 0, NULL, ! 256: ai_stand, 0, NULL, ! 257: ai_stand, 0, NULL, ! 258: ai_stand, 0, NULL, ! 259: ai_stand, 0, NULL ! 260: }; ! 261: mmove_t boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL}; ! 262: ! 263: mframe_t boss2_frames_fidget [] = ! 264: { ! 265: ai_stand, 0, NULL, ! 266: ai_stand, 0, NULL, ! 267: ai_stand, 0, NULL, ! 268: ai_stand, 0, NULL, ! 269: ai_stand, 0, NULL, ! 270: ai_stand, 0, NULL, ! 271: ai_stand, 0, NULL, ! 272: ai_stand, 0, NULL, ! 273: ai_stand, 0, NULL, ! 274: ai_stand, 0, NULL, ! 275: ai_stand, 0, NULL, ! 276: ai_stand, 0, NULL, ! 277: ai_stand, 0, NULL, ! 278: ai_stand, 0, NULL, ! 279: ai_stand, 0, NULL, ! 280: ai_stand, 0, NULL, ! 281: ai_stand, 0, NULL, ! 282: ai_stand, 0, NULL, ! 283: ai_stand, 0, NULL, ! 284: ai_stand, 0, NULL, ! 285: ai_stand, 0, NULL, ! 286: ai_stand, 0, NULL, ! 287: ai_stand, 0, NULL, ! 288: ai_stand, 0, NULL, ! 289: ai_stand, 0, NULL, ! 290: ai_stand, 0, NULL, ! 291: ai_stand, 0, NULL, ! 292: ai_stand, 0, NULL, ! 293: ai_stand, 0, NULL, ! 294: ai_stand, 0, NULL ! 295: }; ! 296: mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL}; ! 297: ! 298: mframe_t boss2_frames_walk [] = ! 299: { ! 300: /* PMM - normally, this is all 8's .. I upped it */ ! 301: ai_walk, 10, NULL, ! 302: ai_walk, 10, NULL, ! 303: ai_walk, 10, NULL, ! 304: ai_walk, 10, NULL, ! 305: ai_walk, 10, NULL, ! 306: ai_walk, 10, NULL, ! 307: ai_walk, 10, NULL, ! 308: ai_walk, 10, NULL, ! 309: ai_walk, 10, NULL, ! 310: ai_walk, 10, NULL, ! 311: ai_walk, 10, NULL, ! 312: ai_walk, 10, NULL, ! 313: ai_walk, 10, NULL, ! 314: ai_walk, 10, NULL, ! 315: ai_walk, 10, NULL, ! 316: ai_walk, 10, NULL, ! 317: ai_walk, 10, NULL, ! 318: ai_walk, 10, NULL, ! 319: ai_walk, 10, NULL, ! 320: ai_walk, 10, NULL ! 321: }; ! 322: mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL}; ! 323: ! 324: ! 325: mframe_t boss2_frames_run [] = ! 326: { ! 327: /* PMM - normally, this is all 8's .. I upped it */ ! 328: ai_run, 10, NULL, ! 329: ai_run, 10, NULL, ! 330: ai_run, 10, NULL, ! 331: ai_run, 10, NULL, ! 332: ai_run, 10, NULL, ! 333: ai_run, 10, NULL, ! 334: ai_run, 10, NULL, ! 335: ai_run, 10, NULL, ! 336: ai_run, 10, NULL, ! 337: ai_run, 10, NULL, ! 338: ai_run, 10, NULL, ! 339: ai_run, 10, NULL, ! 340: ai_run, 10, NULL, ! 341: ai_run, 10, NULL, ! 342: ai_run, 10, NULL, ! 343: ai_run, 10, NULL, ! 344: ai_run, 10, NULL, ! 345: ai_run, 10, NULL, ! 346: ai_run, 10, NULL, ! 347: ai_run, 10, NULL ! 348: }; ! 349: mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL}; ! 350: ! 351: mframe_t boss2_frames_attack_pre_mg [] = ! 352: { ! 353: /* used to be all 1's .. what a slow guy */ ! 354: ai_charge, 2, NULL, ! 355: ai_charge, 2, NULL, ! 356: ai_charge, 2, NULL, ! 357: ai_charge, 2, NULL, ! 358: ai_charge, 2, NULL, ! 359: ai_charge, 2, NULL, ! 360: ai_charge, 2, NULL, ! 361: ai_charge, 2, NULL, ! 362: ai_charge, 2, boss2_attack_mg ! 363: }; ! 364: mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL}; ! 365: ! 366: ! 367: // Loop this ! 368: mframe_t boss2_frames_attack_mg [] = ! 369: { ! 370: /* used to be all 1's .. what a slow guy */ ! 371: ai_charge, 2, Boss2MachineGun, ! 372: ai_charge, 2, Boss2MachineGun, ! 373: ai_charge, 2, Boss2MachineGun, ! 374: ai_charge, 2, Boss2MachineGun, ! 375: ai_charge, 2, Boss2MachineGun, ! 376: ai_charge, 2, boss2_reattack_mg ! 377: }; ! 378: mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL}; ! 379: ! 380: mframe_t boss2_frames_attack_post_mg [] = ! 381: { ! 382: /* used to be all 1's .. what a slow guy */ ! 383: ai_charge, 2, NULL, ! 384: ai_charge, 2, NULL, ! 385: ai_charge, 2, NULL, ! 386: ai_charge, 2, NULL ! 387: }; ! 388: mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run}; ! 389: ! 390: mframe_t boss2_frames_attack_rocket [] = ! 391: { ! 392: /* used to be all 1's .. except the Boss2Rocket frame, which was -20(!) */ ! 393: ai_charge, 2, NULL, ! 394: ai_charge, 2, NULL, ! 395: ai_charge, 2, NULL, ! 396: ai_charge, 2, NULL, ! 397: ai_charge, 2, NULL, ! 398: ai_charge, 2, NULL, ! 399: ai_charge, 2, NULL, ! 400: ai_charge, 2, NULL, ! 401: ai_charge, 2, NULL, ! 402: ai_charge, 2, NULL, ! 403: ai_charge, 2, NULL, ! 404: ai_charge, 2, NULL, ! 405: ai_move, -5, Boss2Rocket, ! 406: ai_charge, 2, NULL, ! 407: ai_charge, 2, NULL, ! 408: ai_charge, 2, NULL, ! 409: ai_charge, 2, NULL, ! 410: ai_charge, 2, NULL, ! 411: ai_charge, 2, NULL, ! 412: ai_charge, 2, NULL, ! 413: ai_charge, 2, NULL ! 414: }; ! 415: mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run}; ! 416: ! 417: mframe_t boss2_frames_pain_heavy [] = ! 418: { ! 419: ai_move, 0, NULL, ! 420: ai_move, 0, NULL, ! 421: ai_move, 0, NULL, ! 422: ai_move, 0, NULL, ! 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, ! 433: ai_move, 0, NULL, ! 434: ai_move, 0, NULL, ! 435: ai_move, 0, NULL, ! 436: ai_move, 0, NULL ! 437: }; ! 438: mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run}; ! 439: ! 440: mframe_t boss2_frames_pain_light [] = ! 441: { ! 442: ai_move, 0, NULL, ! 443: ai_move, 0, NULL, ! 444: ai_move, 0, NULL, ! 445: ai_move, 0, NULL ! 446: }; ! 447: mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run}; ! 448: ! 449: mframe_t boss2_frames_death [] = ! 450: { ! 451: ai_move, 0, NULL, ! 452: ai_move, 0, NULL, ! 453: ai_move, 0, NULL, ! 454: ai_move, 0, NULL, ! 455: ai_move, 0, NULL, ! 456: ai_move, 0, NULL, ! 457: ai_move, 0, NULL, ! 458: ai_move, 0, NULL, ! 459: ai_move, 0, NULL, ! 460: ai_move, 0, NULL, ! 461: ai_move, 0, NULL, ! 462: ai_move, 0, NULL, ! 463: ai_move, 0, NULL, ! 464: ai_move, 0, NULL, ! 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: ai_move, 0, NULL, ! 471: ai_move, 0, NULL, ! 472: ai_move, 0, NULL, ! 473: ai_move, 0, NULL, ! 474: ai_move, 0, NULL, ! 475: ai_move, 0, NULL, ! 476: ai_move, 0, NULL, ! 477: 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, ! 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, 0, NULL, ! 489: ai_move, 0, NULL, ! 490: ai_move, 0, NULL, ! 491: ai_move, 0, NULL, ! 492: ai_move, 0, NULL, ! 493: ai_move, 0, NULL, ! 494: ai_move, 0, NULL, ! 495: ai_move, 0, NULL, ! 496: ai_move, 0, NULL, ! 497: ai_move, 0, NULL, ! 498: ai_move, 0, NULL, ! 499: ai_move, 0, BossExplode ! 500: }; ! 501: mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead}; ! 502: ! 503: void boss2_stand (edict_t *self) ! 504: { ! 505: self->monsterinfo.currentmove = &boss2_move_stand; ! 506: } ! 507: ! 508: void boss2_run (edict_t *self) ! 509: { ! 510: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 511: self->monsterinfo.currentmove = &boss2_move_stand; ! 512: else ! 513: self->monsterinfo.currentmove = &boss2_move_run; ! 514: } ! 515: ! 516: void boss2_walk (edict_t *self) ! 517: { ! 518: self->monsterinfo.currentmove = &boss2_move_walk; ! 519: } ! 520: ! 521: void boss2_attack (edict_t *self) ! 522: { ! 523: vec3_t vec; ! 524: float range; ! 525: ! 526: VectorSubtract (self->enemy->s.origin, self->s.origin, vec); ! 527: range = VectorLength (vec); ! 528: ! 529: if (range <= 125) ! 530: { ! 531: self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; ! 532: } ! 533: else ! 534: { ! 535: if (random() <= 0.6) ! 536: self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; ! 537: else ! 538: self->monsterinfo.currentmove = &boss2_move_attack_rocket; ! 539: } ! 540: } ! 541: ! 542: void boss2_attack_mg (edict_t *self) ! 543: { ! 544: self->monsterinfo.currentmove = &boss2_move_attack_mg; ! 545: } ! 546: ! 547: void boss2_reattack_mg (edict_t *self) ! 548: { ! 549: if ( infront(self, self->enemy) ) ! 550: if (random() <= 0.7) ! 551: self->monsterinfo.currentmove = &boss2_move_attack_mg; ! 552: else ! 553: self->monsterinfo.currentmove = &boss2_move_attack_post_mg; ! 554: else ! 555: self->monsterinfo.currentmove = &boss2_move_attack_post_mg; ! 556: } ! 557: ! 558: ! 559: void boss2_pain (edict_t *self, edict_t *other, float kick, int damage) ! 560: { ! 561: if (self->health < (self->max_health / 2)) ! 562: self->s.skinnum = 1; ! 563: ! 564: if (level.time < self->pain_debounce_time) ! 565: return; ! 566: ! 567: self->pain_debounce_time = level.time + 3; ! 568: // American wanted these at no attenuation ! 569: if (damage < 10) ! 570: { ! 571: gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); ! 572: self->monsterinfo.currentmove = &boss2_move_pain_light; ! 573: } ! 574: else if (damage < 30) ! 575: { ! 576: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); ! 577: self->monsterinfo.currentmove = &boss2_move_pain_light; ! 578: } ! 579: else ! 580: { ! 581: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); ! 582: self->monsterinfo.currentmove = &boss2_move_pain_heavy; ! 583: } ! 584: } ! 585: ! 586: void boss2_dead (edict_t *self) ! 587: { ! 588: VectorSet (self->mins, -56, -56, 0); ! 589: VectorSet (self->maxs, 56, 56, 80); ! 590: self->movetype = MOVETYPE_TOSS; ! 591: self->svflags |= SVF_DEADMONSTER; ! 592: self->nextthink = 0; ! 593: gi.linkentity (self); ! 594: } ! 595: ! 596: void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) ! 597: { ! 598: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); ! 599: self->deadflag = DEAD_DEAD; ! 600: self->takedamage = DAMAGE_NO; ! 601: self->count = 0; ! 602: self->monsterinfo.currentmove = &boss2_move_death; ! 603: #if 0 ! 604: int n; ! 605: ! 606: self->s.sound = 0; ! 607: // check for gib ! 608: if (self->health <= self->gib_health) ! 609: { ! 610: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 611: for (n= 0; n < 2; n++) ! 612: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); ! 613: for (n= 0; n < 4; n++) ! 614: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ! 615: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); ! 616: self->deadflag = DEAD_DEAD; ! 617: return; ! 618: } ! 619: ! 620: if (self->deadflag == DEAD_DEAD) ! 621: return; ! 622: ! 623: self->deadflag = DEAD_DEAD; ! 624: self->takedamage = DAMAGE_YES; ! 625: self->monsterinfo.currentmove = &boss2_move_death; ! 626: #endif ! 627: } ! 628: ! 629: qboolean Boss2_CheckAttack (edict_t *self) ! 630: { ! 631: vec3_t spot1, spot2; ! 632: vec3_t temp; ! 633: float chance; ! 634: trace_t tr; ! 635: qboolean enemy_infront; ! 636: int enemy_range; ! 637: float enemy_yaw; ! 638: ! 639: if (self->enemy->health > 0) ! 640: { ! 641: // see if any entities are in the way of the shot ! 642: VectorCopy (self->s.origin, spot1); ! 643: spot1[2] += self->viewheight; ! 644: VectorCopy (self->enemy->s.origin, spot2); ! 645: spot2[2] += self->enemy->viewheight; ! 646: ! 647: tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); ! 648: ! 649: // do we have a clear shot? ! 650: if (tr.ent != self->enemy) ! 651: { ! 652: // PGM - we want them to go ahead and shoot at info_notnulls if they can. ! 653: if(self->enemy->solid != SOLID_NOT || tr.fraction < 1.0) //PGM ! 654: return false; ! 655: } ! 656: } ! 657: ! 658: enemy_infront = infront(self, self->enemy); ! 659: enemy_range = range(self, self->enemy); ! 660: VectorSubtract (self->enemy->s.origin, self->s.origin, temp); ! 661: enemy_yaw = vectoyaw(temp); ! 662: ! 663: self->ideal_yaw = enemy_yaw; ! 664: ! 665: ! 666: // melee attack ! 667: if (enemy_range == RANGE_MELEE) ! 668: { ! 669: if (self->monsterinfo.melee) ! 670: self->monsterinfo.attack_state = AS_MELEE; ! 671: else ! 672: self->monsterinfo.attack_state = AS_MISSILE; ! 673: return true; ! 674: } ! 675: ! 676: // missile attack ! 677: if (!self->monsterinfo.attack) ! 678: return false; ! 679: ! 680: if (level.time < self->monsterinfo.attack_finished) ! 681: return false; ! 682: ! 683: if (enemy_range == RANGE_FAR) ! 684: return false; ! 685: ! 686: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 687: { ! 688: chance = 0.4; ! 689: } ! 690: else if (enemy_range == RANGE_MELEE) ! 691: { ! 692: chance = 0.8; ! 693: } ! 694: else if (enemy_range == RANGE_NEAR) ! 695: { ! 696: chance = 0.8; ! 697: } ! 698: else if (enemy_range == RANGE_MID) ! 699: { ! 700: chance = 0.8; ! 701: } ! 702: else ! 703: { ! 704: return false; ! 705: } ! 706: ! 707: // PGM - go ahead and shoot every time if it's a info_notnull ! 708: if ((random () < chance) || (self->enemy->solid == SOLID_NOT)) ! 709: { ! 710: self->monsterinfo.attack_state = AS_MISSILE; ! 711: self->monsterinfo.attack_finished = level.time + 2*random(); ! 712: return true; ! 713: } ! 714: ! 715: if (self->flags & FL_FLY) ! 716: { ! 717: if (random() < 0.3) ! 718: self->monsterinfo.attack_state = AS_SLIDING; ! 719: else ! 720: self->monsterinfo.attack_state = AS_STRAIGHT; ! 721: } ! 722: ! 723: return false; ! 724: } ! 725: ! 726: ! 727: ! 728: /*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight ! 729: */ ! 730: void SP_monster_boss2 (edict_t *self) ! 731: { ! 732: if (deathmatch->value) ! 733: { ! 734: G_FreeEdict (self); ! 735: return; ! 736: } ! 737: ! 738: sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav"); ! 739: sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav"); ! 740: sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav"); ! 741: sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav"); ! 742: sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav"); ! 743: ! 744: self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav"); ! 745: ! 746: self->movetype = MOVETYPE_STEP; ! 747: self->solid = SOLID_BBOX; ! 748: self->s.modelindex = gi.modelindex ("models/monsters/boss2/tris.md2"); ! 749: VectorSet (self->mins, -56, -56, 0); ! 750: VectorSet (self->maxs, 56, 56, 80); ! 751: ! 752: self->health = 2000; ! 753: self->gib_health = -200; ! 754: self->mass = 1000; ! 755: ! 756: self->yaw_speed = 50; ! 757: ! 758: self->flags |= FL_IMMUNE_LASER; ! 759: ! 760: self->pain = boss2_pain; ! 761: self->die = boss2_die; ! 762: ! 763: self->monsterinfo.stand = boss2_stand; ! 764: self->monsterinfo.walk = boss2_walk; ! 765: self->monsterinfo.run = boss2_run; ! 766: self->monsterinfo.attack = boss2_attack; ! 767: self->monsterinfo.search = boss2_search; ! 768: self->monsterinfo.checkattack = Boss2_CheckAttack; ! 769: gi.linkentity (self); ! 770: ! 771: self->monsterinfo.currentmove = &boss2_move_stand; ! 772: self->monsterinfo.scale = MODEL_SCALE; ! 773: ! 774: flymonster_start (self); ! 775: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.