|
|
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: TANK 24: 25: ============================================================================== 26: */ 27: 28: #include "g_local.h" 29: #include "m_tank.h" 30: 31: 32: void tank_refire_rocket (edict_t *self); 33: void tank_doattack_rocket (edict_t *self); 34: void tank_reattack_blaster (edict_t *self); 35: 36: static int sound_thud; 37: static int sound_pain; 38: static int sound_idle; 39: static int sound_die; 40: static int sound_step; 41: static int sound_sight; 42: static int sound_windup; 43: static int sound_strike; 44: 45: // 46: // misc 47: // 48: 49: void tank_sight (edict_t *self, edict_t *other) 50: { 51: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); 52: } 53: 54: 55: void tank_footstep (edict_t *self) 56: { 57: gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); 58: } 59: 60: void tank_thud (edict_t *self) 61: { 62: gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0); 63: } 64: 65: void tank_windup (edict_t *self) 66: { 67: gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0); 68: } 69: 70: void tank_idle (edict_t *self) 71: { 72: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); 73: } 74: 75: 76: // 77: // stand 78: // 79: 80: mframe_t tank_frames_stand []= 81: { 82: ai_stand, 0, NULL, 83: ai_stand, 0, NULL, 84: ai_stand, 0, NULL, 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, 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, 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: }; 113: mmove_t tank_move_stand = {FRAME_stand01, FRAME_stand30, tank_frames_stand, NULL}; 114: 115: void tank_stand (edict_t *self) 116: { 117: self->monsterinfo.currentmove = &tank_move_stand; 118: } 119: 120: 121: // 122: // walk 123: // 124: 125: void tank_walk (edict_t *self); 126: 127: mframe_t tank_frames_start_walk [] = 128: { 129: ai_walk, 0, NULL, 130: ai_walk, 6, NULL, 131: ai_walk, 6, NULL, 132: ai_walk, 11, tank_footstep 133: }; 134: mmove_t tank_move_start_walk = {FRAME_walk01, FRAME_walk04, tank_frames_start_walk, tank_walk}; 135: 136: mframe_t tank_frames_walk [] = 137: { 138: ai_walk, 4, NULL, 139: ai_walk, 5, NULL, 140: ai_walk, 3, NULL, 141: ai_walk, 2, NULL, 142: ai_walk, 5, NULL, 143: ai_walk, 5, NULL, 144: ai_walk, 4, NULL, 145: ai_walk, 4, tank_footstep, 146: ai_walk, 3, NULL, 147: ai_walk, 5, NULL, 148: ai_walk, 4, NULL, 149: ai_walk, 5, NULL, 150: ai_walk, 7, NULL, 151: ai_walk, 7, NULL, 152: ai_walk, 6, NULL, 153: ai_walk, 6, tank_footstep 154: }; 155: mmove_t tank_move_walk = {FRAME_walk05, FRAME_walk20, tank_frames_walk, NULL}; 156: 157: mframe_t tank_frames_stop_walk [] = 158: { 159: ai_walk, 3, NULL, 160: ai_walk, 3, NULL, 161: ai_walk, 2, NULL, 162: ai_walk, 2, NULL, 163: ai_walk, 4, tank_footstep 164: }; 165: mmove_t tank_move_stop_walk = {FRAME_walk21, FRAME_walk25, tank_frames_stop_walk, tank_stand}; 166: 167: void tank_walk (edict_t *self) 168: { 169: self->monsterinfo.currentmove = &tank_move_walk; 170: } 171: 172: 173: // 174: // run 175: // 176: 177: void tank_run (edict_t *self); 178: 179: mframe_t tank_frames_start_run [] = 180: { 181: ai_run, 0, NULL, 182: ai_run, 6, NULL, 183: ai_run, 6, NULL, 184: ai_run, 11, tank_footstep 185: }; 186: mmove_t tank_move_start_run = {FRAME_walk01, FRAME_walk04, tank_frames_start_run, tank_run}; 187: 188: mframe_t tank_frames_run [] = 189: { 190: ai_run, 4, NULL, 191: ai_run, 5, NULL, 192: ai_run, 3, NULL, 193: ai_run, 2, NULL, 194: ai_run, 5, NULL, 195: ai_run, 5, NULL, 196: ai_run, 4, NULL, 197: ai_run, 4, tank_footstep, 198: ai_run, 3, NULL, 199: ai_run, 5, NULL, 200: ai_run, 4, NULL, 201: ai_run, 5, NULL, 202: ai_run, 7, NULL, 203: ai_run, 7, NULL, 204: ai_run, 6, NULL, 205: ai_run, 6, tank_footstep 206: }; 207: mmove_t tank_move_run = {FRAME_walk05, FRAME_walk20, tank_frames_run, NULL}; 208: 209: mframe_t tank_frames_stop_run [] = 210: { 211: ai_run, 3, NULL, 212: ai_run, 3, NULL, 213: ai_run, 2, NULL, 214: ai_run, 2, NULL, 215: ai_run, 4, tank_footstep 216: }; 217: mmove_t tank_move_stop_run = {FRAME_walk21, FRAME_walk25, tank_frames_stop_run, tank_walk}; 218: 219: void tank_run (edict_t *self) 220: { 221: if (self->enemy && self->enemy->client) 222: self->monsterinfo.aiflags |= AI_BRUTAL; 223: else 224: self->monsterinfo.aiflags &= ~AI_BRUTAL; 225: 226: if (self->monsterinfo.aiflags & AI_STAND_GROUND) 227: { 228: self->monsterinfo.currentmove = &tank_move_stand; 229: return; 230: } 231: 232: if (self->monsterinfo.currentmove == &tank_move_walk || 233: self->monsterinfo.currentmove == &tank_move_start_run) 234: { 235: self->monsterinfo.currentmove = &tank_move_run; 236: } 237: else 238: { 239: self->monsterinfo.currentmove = &tank_move_start_run; 240: } 241: } 242: 243: // 244: // pain 245: // 246: 247: mframe_t tank_frames_pain1 [] = 248: { 249: ai_move, 0, NULL, 250: ai_move, 0, NULL, 251: ai_move, 0, NULL, 252: ai_move, 0, NULL 253: }; 254: mmove_t tank_move_pain1 = {FRAME_pain101, FRAME_pain104, tank_frames_pain1, tank_run}; 255: 256: mframe_t tank_frames_pain2 [] = 257: { 258: ai_move, 0, NULL, 259: ai_move, 0, NULL, 260: ai_move, 0, NULL, 261: ai_move, 0, NULL, 262: ai_move, 0, NULL 263: }; 264: mmove_t tank_move_pain2 = {FRAME_pain201, FRAME_pain205, tank_frames_pain2, tank_run}; 265: 266: mframe_t tank_frames_pain3 [] = 267: { 268: ai_move, -7, NULL, 269: ai_move, 0, NULL, 270: ai_move, 0, NULL, 271: ai_move, 0, NULL, 272: ai_move, 2, NULL, 273: ai_move, 0, NULL, 274: ai_move, 0, NULL, 275: ai_move, 3, NULL, 276: ai_move, 0, NULL, 277: ai_move, 2, NULL, 278: ai_move, 0, NULL, 279: ai_move, 0, NULL, 280: ai_move, 0, NULL, 281: ai_move, 0, NULL, 282: ai_move, 0, NULL, 283: ai_move, 0, tank_footstep 284: }; 285: mmove_t tank_move_pain3 = {FRAME_pain301, FRAME_pain316, tank_frames_pain3, tank_run}; 286: 287: 288: void tank_pain (edict_t *self, edict_t *other, float kick, int damage) 289: { 290: if (self->health < (self->max_health / 2)) 291: self->s.skinnum |= 1; 292: 293: if (damage <= 10) 294: return; 295: 296: if (level.time < self->pain_debounce_time) 297: return; 298: 299: if (damage <= 30) 300: if (random() > 0.2) 301: return; 302: 303: // If hard or nightmare, don't go into pain while attacking 304: if ( skill->value >= 2) 305: { 306: if ( (self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330) ) 307: return; 308: if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116) ) 309: return; 310: } 311: 312: self->pain_debounce_time = level.time + 3; 313: gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); 314: 315: if (skill->value == 3) 316: return; // no pain anims in nightmare 317: 318: if (damage <= 30) 319: self->monsterinfo.currentmove = &tank_move_pain1; 320: else if (damage <= 60) 321: self->monsterinfo.currentmove = &tank_move_pain2; 322: else 323: self->monsterinfo.currentmove = &tank_move_pain3; 324: }; 325: 326: 327: // 328: // attacks 329: // 330: 331: void TankBlaster (edict_t *self) 332: { 333: vec3_t forward, right; 334: vec3_t start; 335: vec3_t end; 336: vec3_t dir; 337: int flash_number; 338: 339: if (self->s.frame == FRAME_attak110) 340: flash_number = MZ2_TANK_BLASTER_1; 341: else if (self->s.frame == FRAME_attak113) 342: flash_number = MZ2_TANK_BLASTER_2; 343: else // (self->s.frame == FRAME_attak116) 344: flash_number = MZ2_TANK_BLASTER_3; 345: 346: AngleVectors (self->s.angles, forward, right, NULL); 347: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); 348: 349: VectorCopy (self->enemy->s.origin, end); 350: end[2] += self->enemy->viewheight; 351: VectorSubtract (end, start, dir); 352: 353: monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER); 354: } 355: 356: void TankStrike (edict_t *self) 357: { 358: gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0); 359: } 360: 361: void TankRocket (edict_t *self) 362: { 363: vec3_t forward, right; 364: vec3_t start; 365: vec3_t dir; 366: vec3_t vec; 367: int flash_number; 368: 369: if (self->s.frame == FRAME_attak324) 370: flash_number = MZ2_TANK_ROCKET_1; 371: else if (self->s.frame == FRAME_attak327) 372: flash_number = MZ2_TANK_ROCKET_2; 373: else // (self->s.frame == FRAME_attak330) 374: flash_number = MZ2_TANK_ROCKET_3; 375: 376: AngleVectors (self->s.angles, forward, right, NULL); 377: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); 378: 379: VectorCopy (self->enemy->s.origin, vec); 380: vec[2] += self->enemy->viewheight; 381: VectorSubtract (vec, start, dir); 382: VectorNormalize (dir); 383: 384: monster_fire_rocket (self, start, dir, 50, 550, flash_number); 385: } 386: 387: void TankMachineGun (edict_t *self) 388: { 389: vec3_t dir; 390: vec3_t vec; 391: vec3_t start; 392: vec3_t forward, right; 393: int flash_number; 394: 395: flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406); 396: 397: AngleVectors (self->s.angles, forward, right, NULL); 398: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); 399: 400: if (self->enemy) 401: { 402: VectorCopy (self->enemy->s.origin, vec); 403: vec[2] += self->enemy->viewheight; 404: VectorSubtract (vec, start, vec); 405: vectoangles (vec, vec); 406: dir[0] = vec[0]; 407: } 408: else 409: { 410: dir[0] = 0; 411: } 412: if (self->s.frame <= FRAME_attak415) 413: dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411); 414: else 415: dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419); 416: dir[2] = 0; 417: 418: AngleVectors (dir, forward, NULL, NULL); 419: 420: monster_fire_bullet (self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); 421: } 422: 423: 424: mframe_t tank_frames_attack_blast [] = 425: { 426: ai_charge, 0, NULL, 427: ai_charge, 0, NULL, 428: ai_charge, 0, NULL, 429: ai_charge, 0, NULL, 430: ai_charge, -1, NULL, 431: ai_charge, -2, NULL, 432: ai_charge, -1, NULL, 433: ai_charge, -1, NULL, 434: ai_charge, 0, NULL, 435: ai_charge, 0, TankBlaster, // 10 436: ai_charge, 0, NULL, 437: ai_charge, 0, NULL, 438: ai_charge, 0, TankBlaster, 439: ai_charge, 0, NULL, 440: ai_charge, 0, NULL, 441: ai_charge, 0, TankBlaster // 16 442: }; 443: mmove_t tank_move_attack_blast = {FRAME_attak101, FRAME_attak116, tank_frames_attack_blast, tank_reattack_blaster}; 444: 445: mframe_t tank_frames_reattack_blast [] = 446: { 447: ai_charge, 0, NULL, 448: ai_charge, 0, NULL, 449: ai_charge, 0, TankBlaster, 450: ai_charge, 0, NULL, 451: ai_charge, 0, NULL, 452: ai_charge, 0, TankBlaster // 16 453: }; 454: mmove_t tank_move_reattack_blast = {FRAME_attak111, FRAME_attak116, tank_frames_reattack_blast, tank_reattack_blaster}; 455: 456: mframe_t tank_frames_attack_post_blast [] = 457: { 458: ai_move, 0, NULL, // 17 459: ai_move, 0, NULL, 460: ai_move, 2, NULL, 461: ai_move, 3, NULL, 462: ai_move, 2, NULL, 463: ai_move, -2, tank_footstep // 22 464: }; 465: mmove_t tank_move_attack_post_blast = {FRAME_attak117, FRAME_attak122, tank_frames_attack_post_blast, tank_run}; 466: 467: void tank_reattack_blaster (edict_t *self) 468: { 469: if (skill->value >= 2) 470: if (visible (self, self->enemy)) 471: if (self->enemy->health > 0) 472: if (random() <= 0.6) 473: { 474: self->monsterinfo.currentmove = &tank_move_reattack_blast; 475: return; 476: } 477: self->monsterinfo.currentmove = &tank_move_attack_post_blast; 478: } 479: 480: 481: void tank_poststrike (edict_t *self) 482: { 483: self->enemy = NULL; 484: tank_run (self); 485: } 486: 487: mframe_t tank_frames_attack_strike [] = 488: { 489: ai_move, 3, NULL, 490: ai_move, 2, NULL, 491: ai_move, 2, NULL, 492: ai_move, 1, NULL, 493: ai_move, 6, NULL, 494: ai_move, 7, NULL, 495: ai_move, 9, tank_footstep, 496: ai_move, 2, NULL, 497: ai_move, 1, NULL, 498: ai_move, 2, NULL, 499: ai_move, 2, tank_footstep, 500: ai_move, 2, NULL, 501: ai_move, 0, NULL, 502: ai_move, 0, NULL, 503: ai_move, 0, NULL, 504: ai_move, 0, NULL, 505: ai_move, -2, NULL, 506: ai_move, -2, NULL, 507: ai_move, 0, tank_windup, 508: ai_move, 0, NULL, 509: ai_move, 0, NULL, 510: ai_move, 0, NULL, 511: ai_move, 0, NULL, 512: ai_move, 0, NULL, 513: ai_move, 0, NULL, 514: ai_move, 0, TankStrike, 515: ai_move, 0, NULL, 516: ai_move, -1, NULL, 517: ai_move, -1, NULL, 518: ai_move, -1, NULL, 519: ai_move, -1, NULL, 520: ai_move, -1, NULL, 521: ai_move, -3, NULL, 522: ai_move, -10, NULL, 523: ai_move, -10, NULL, 524: ai_move, -2, NULL, 525: ai_move, -3, NULL, 526: ai_move, -2, tank_footstep 527: }; 528: mmove_t tank_move_attack_strike = {FRAME_attak201, FRAME_attak238, tank_frames_attack_strike, tank_poststrike}; 529: 530: mframe_t tank_frames_attack_pre_rocket [] = 531: { 532: ai_charge, 0, NULL, 533: ai_charge, 0, NULL, 534: ai_charge, 0, NULL, 535: ai_charge, 0, NULL, 536: ai_charge, 0, NULL, 537: ai_charge, 0, NULL, 538: ai_charge, 0, NULL, 539: ai_charge, 0, NULL, 540: ai_charge, 0, NULL, 541: ai_charge, 0, NULL, // 10 542: 543: ai_charge, 0, NULL, 544: ai_charge, 1, NULL, 545: ai_charge, 2, NULL, 546: ai_charge, 7, NULL, 547: ai_charge, 7, NULL, 548: ai_charge, 7, tank_footstep, 549: ai_charge, 0, NULL, 550: ai_charge, 0, NULL, 551: ai_charge, 0, NULL, 552: ai_charge, 0, NULL, // 20 553: 554: ai_charge, -3, NULL 555: }; 556: mmove_t tank_move_attack_pre_rocket = {FRAME_attak301, FRAME_attak321, tank_frames_attack_pre_rocket, tank_doattack_rocket}; 557: 558: mframe_t tank_frames_attack_fire_rocket [] = 559: { 560: ai_charge, -3, NULL, // Loop Start 22 561: ai_charge, 0, NULL, 562: ai_charge, 0, TankRocket, // 24 563: ai_charge, 0, NULL, 564: ai_charge, 0, NULL, 565: ai_charge, 0, TankRocket, 566: ai_charge, 0, NULL, 567: ai_charge, 0, NULL, 568: ai_charge, -1, TankRocket // 30 Loop End 569: }; 570: mmove_t tank_move_attack_fire_rocket = {FRAME_attak322, FRAME_attak330, tank_frames_attack_fire_rocket, tank_refire_rocket}; 571: 572: mframe_t tank_frames_attack_post_rocket [] = 573: { 574: ai_charge, 0, NULL, // 31 575: ai_charge, -1, NULL, 576: ai_charge, -1, NULL, 577: ai_charge, 0, NULL, 578: ai_charge, 2, NULL, 579: ai_charge, 3, NULL, 580: ai_charge, 4, NULL, 581: ai_charge, 2, NULL, 582: ai_charge, 0, NULL, 583: ai_charge, 0, NULL, // 40 584: 585: ai_charge, 0, NULL, 586: ai_charge, -9, NULL, 587: ai_charge, -8, NULL, 588: ai_charge, -7, NULL, 589: ai_charge, -1, NULL, 590: ai_charge, -1, tank_footstep, 591: ai_charge, 0, NULL, 592: ai_charge, 0, NULL, 593: ai_charge, 0, NULL, 594: ai_charge, 0, NULL, // 50 595: 596: ai_charge, 0, NULL, 597: ai_charge, 0, NULL, 598: ai_charge, 0, NULL 599: }; 600: mmove_t tank_move_attack_post_rocket = {FRAME_attak331, FRAME_attak353, tank_frames_attack_post_rocket, tank_run}; 601: 602: mframe_t tank_frames_attack_chain [] = 603: { 604: ai_charge, 0, NULL, 605: ai_charge, 0, NULL, 606: ai_charge, 0, NULL, 607: ai_charge, 0, NULL, 608: ai_charge, 0, NULL, 609: NULL, 0, TankMachineGun, 610: NULL, 0, TankMachineGun, 611: NULL, 0, TankMachineGun, 612: NULL, 0, TankMachineGun, 613: NULL, 0, TankMachineGun, 614: NULL, 0, TankMachineGun, 615: NULL, 0, TankMachineGun, 616: NULL, 0, TankMachineGun, 617: NULL, 0, TankMachineGun, 618: NULL, 0, TankMachineGun, 619: NULL, 0, TankMachineGun, 620: NULL, 0, TankMachineGun, 621: NULL, 0, TankMachineGun, 622: NULL, 0, TankMachineGun, 623: NULL, 0, TankMachineGun, 624: NULL, 0, TankMachineGun, 625: NULL, 0, TankMachineGun, 626: NULL, 0, TankMachineGun, 627: NULL, 0, TankMachineGun, 628: ai_charge, 0, NULL, 629: ai_charge, 0, NULL, 630: ai_charge, 0, NULL, 631: ai_charge, 0, NULL, 632: ai_charge, 0, NULL 633: }; 634: mmove_t tank_move_attack_chain = {FRAME_attak401, FRAME_attak429, tank_frames_attack_chain, tank_run}; 635: 636: void tank_refire_rocket (edict_t *self) 637: { 638: // Only on hard or nightmare 639: if ( skill->value >= 2 ) 640: if (self->enemy->health > 0) 641: if (visible(self, self->enemy) ) 642: if (random() <= 0.4) 643: { 644: self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; 645: return; 646: } 647: self->monsterinfo.currentmove = &tank_move_attack_post_rocket; 648: } 649: 650: void tank_doattack_rocket (edict_t *self) 651: { 652: self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; 653: } 654: 655: void tank_attack(edict_t *self) 656: { 657: vec3_t vec; 658: float range; 659: float r; 660: 661: if (self->enemy->health < 0) 662: { 663: self->monsterinfo.currentmove = &tank_move_attack_strike; 664: self->monsterinfo.aiflags &= ~AI_BRUTAL; 665: return; 666: } 667: 668: VectorSubtract (self->enemy->s.origin, self->s.origin, vec); 669: range = VectorLength (vec); 670: 671: r = random(); 672: 673: if (range <= 125) 674: { 675: if (r < 0.4) 676: self->monsterinfo.currentmove = &tank_move_attack_chain; 677: else 678: self->monsterinfo.currentmove = &tank_move_attack_blast; 679: } 680: else if (range <= 250) 681: { 682: if (r < 0.5) 683: self->monsterinfo.currentmove = &tank_move_attack_chain; 684: else 685: self->monsterinfo.currentmove = &tank_move_attack_blast; 686: } 687: else 688: { 689: if (r < 0.33) 690: self->monsterinfo.currentmove = &tank_move_attack_chain; 691: else if (r < 0.66) 692: { 693: self->monsterinfo.currentmove = &tank_move_attack_pre_rocket; 694: self->pain_debounce_time = level.time + 5.0; // no pain for a while 695: } 696: else 697: self->monsterinfo.currentmove = &tank_move_attack_blast; 698: } 699: } 700: 701: 702: // 703: // death 704: // 705: 706: void tank_dead (edict_t *self) 707: { 708: VectorSet (self->mins, -16, -16, -16); 709: VectorSet (self->maxs, 16, 16, -0); 710: self->movetype = MOVETYPE_TOSS; 711: self->svflags |= SVF_DEADMONSTER; 712: self->nextthink = 0; 713: gi.linkentity (self); 714: } 715: 716: mframe_t tank_frames_death1 [] = 717: { 718: ai_move, -7, NULL, 719: ai_move, -2, NULL, 720: ai_move, -2, NULL, 721: ai_move, 1, NULL, 722: ai_move, 3, NULL, 723: ai_move, 6, NULL, 724: ai_move, 1, NULL, 725: ai_move, 1, NULL, 726: ai_move, 2, NULL, 727: ai_move, 0, NULL, 728: ai_move, 0, NULL, 729: ai_move, 0, NULL, 730: ai_move, -2, NULL, 731: ai_move, 0, NULL, 732: ai_move, 0, NULL, 733: ai_move, -3, NULL, 734: ai_move, 0, NULL, 735: ai_move, 0, NULL, 736: ai_move, 0, NULL, 737: ai_move, 0, NULL, 738: ai_move, 0, NULL, 739: ai_move, 0, NULL, 740: ai_move, -4, NULL, 741: ai_move, -6, NULL, 742: ai_move, -4, NULL, 743: ai_move, -5, NULL, 744: ai_move, -7, NULL, 745: ai_move, -15, tank_thud, 746: ai_move, -5, NULL, 747: ai_move, 0, NULL, 748: ai_move, 0, NULL, 749: ai_move, 0, NULL 750: }; 751: mmove_t tank_move_death = {FRAME_death101, FRAME_death132, tank_frames_death1, tank_dead}; 752: 753: void tank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) 754: { 755: int n; 756: 757: // check for gib 758: if (self->health <= self->gib_health) 759: { 760: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); 761: for (n= 0; n < 1 /*4*/; n++) 762: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); 763: for (n= 0; n < 4; n++) 764: ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); 765: ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); 766: ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); 767: self->deadflag = DEAD_DEAD; 768: return; 769: } 770: 771: if (self->deadflag == DEAD_DEAD) 772: return; 773: 774: // regular death 775: gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); 776: self->deadflag = DEAD_DEAD; 777: self->takedamage = DAMAGE_YES; 778: 779: self->monsterinfo.currentmove = &tank_move_death; 780: 781: } 782: 783: 784: // 785: // monster_tank 786: // 787: 788: /*QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight 789: */ 790: /*QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight 791: */ 792: void SP_monster_tank (edict_t *self) 793: { 794: if (deathmatch->value) 795: { 796: G_FreeEdict (self); 797: return; 798: } 799: 800: self->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2"); 801: VectorSet (self->mins, -32, -32, -16); 802: VectorSet (self->maxs, 32, 32, 72); 803: self->movetype = MOVETYPE_STEP; 804: self->solid = SOLID_BBOX; 805: 806: sound_pain = gi.soundindex ("tank/tnkpain2.wav"); 807: sound_thud = gi.soundindex ("tank/tnkdeth2.wav"); 808: sound_idle = gi.soundindex ("tank/tnkidle1.wav"); 809: sound_die = gi.soundindex ("tank/death.wav"); 810: sound_step = gi.soundindex ("tank/step.wav"); 811: sound_windup = gi.soundindex ("tank/tnkatck4.wav"); 812: sound_strike = gi.soundindex ("tank/tnkatck5.wav"); 813: sound_sight = gi.soundindex ("tank/sight1.wav"); 814: 815: gi.soundindex ("tank/tnkatck1.wav"); 816: gi.soundindex ("tank/tnkatk2a.wav"); 817: gi.soundindex ("tank/tnkatk2b.wav"); 818: gi.soundindex ("tank/tnkatk2c.wav"); 819: gi.soundindex ("tank/tnkatk2d.wav"); 820: gi.soundindex ("tank/tnkatk2e.wav"); 821: gi.soundindex ("tank/tnkatck3.wav"); 822: 823: if (strcmp(self->classname, "monster_tank_commander") == 0) 824: { 825: self->health = 1000; 826: self->gib_health = -225; 827: } 828: else 829: { 830: self->health = 750; 831: self->gib_health = -200; 832: } 833: 834: self->mass = 500; 835: 836: self->pain = tank_pain; 837: self->die = tank_die; 838: self->monsterinfo.stand = tank_stand; 839: self->monsterinfo.walk = tank_walk; 840: self->monsterinfo.run = tank_run; 841: self->monsterinfo.dodge = NULL; 842: self->monsterinfo.attack = tank_attack; 843: self->monsterinfo.melee = NULL; 844: self->monsterinfo.sight = tank_sight; 845: self->monsterinfo.idle = tank_idle; 846: 847: gi.linkentity (self); 848: 849: self->monsterinfo.currentmove = &tank_move_stand; 850: self->monsterinfo.scale = MODEL_SCALE; 851: 852: walkmonster_start(self); 853: 854: if (strcmp(self->classname, "monster_tank_commander") == 0) 855: self->s.skinnum = 2; 856: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.