|
|
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: SOLDIER 24: 25: ============================================================================== 26: */ 27: 28: #include "g_local.h" 29: #include "m_soldier.h" 30: 31: 32: static int sound_idle; 33: static int sound_sight1; 34: static int sound_sight2; 35: static int sound_pain_light; 36: static int sound_pain; 37: static int sound_pain_ss; 38: static int sound_death_light; 39: static int sound_death; 40: static int sound_death_ss; 41: static int sound_cock; 42: 43: 44: void soldier_idle (edict_t *self) 45: { 46: if (random() > 0.8) 47: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); 48: } 49: 50: void soldier_cock (edict_t *self) 51: { 52: if (self->s.frame == FRAME_stand322) 53: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0); 54: else 55: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0); 56: } 57: 58: 59: // STAND 60: 61: void soldier_stand (edict_t *self); 62: 63: mframe_t soldier_frames_stand1 [] = 64: { 65: ai_stand, 0, soldier_idle, 66: ai_stand, 0, NULL, 67: ai_stand, 0, NULL, 68: ai_stand, 0, NULL, 69: ai_stand, 0, NULL, 70: ai_stand, 0, NULL, 71: ai_stand, 0, NULL, 72: ai_stand, 0, NULL, 73: ai_stand, 0, NULL, 74: ai_stand, 0, NULL, 75: 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, 85: ai_stand, 0, NULL, 86: 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: }; 98: mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand}; 99: 100: mframe_t soldier_frames_stand3 [] = 101: { 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: ai_stand, 0, NULL, 114: ai_stand, 0, NULL, 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: 124: ai_stand, 0, NULL, 125: ai_stand, 0, soldier_cock, 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: 135: ai_stand, 0, NULL, 136: ai_stand, 0, NULL, 137: ai_stand, 0, NULL, 138: ai_stand, 0, NULL, 139: ai_stand, 0, NULL, 140: ai_stand, 0, NULL, 141: ai_stand, 0, NULL, 142: ai_stand, 0, NULL, 143: ai_stand, 0, NULL 144: }; 145: mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand}; 146: 147: #if 0 148: mframe_t soldier_frames_stand4 [] = 149: { 150: ai_stand, 0, NULL, 151: ai_stand, 0, NULL, 152: ai_stand, 0, NULL, 153: ai_stand, 0, NULL, 154: ai_stand, 0, NULL, 155: ai_stand, 0, NULL, 156: ai_stand, 0, NULL, 157: ai_stand, 0, NULL, 158: ai_stand, 0, NULL, 159: ai_stand, 0, NULL, 160: 161: ai_stand, 0, NULL, 162: ai_stand, 0, NULL, 163: ai_stand, 0, NULL, 164: ai_stand, 0, NULL, 165: ai_stand, 0, NULL, 166: ai_stand, 0, NULL, 167: ai_stand, 0, NULL, 168: ai_stand, 0, NULL, 169: ai_stand, 0, NULL, 170: ai_stand, 0, NULL, 171: 172: ai_stand, 0, NULL, 173: ai_stand, 0, NULL, 174: ai_stand, 0, NULL, 175: ai_stand, 0, NULL, 176: ai_stand, 0, NULL, 177: ai_stand, 0, NULL, 178: ai_stand, 0, NULL, 179: ai_stand, 0, NULL, 180: ai_stand, 0, NULL, 181: ai_stand, 0, NULL, 182: 183: ai_stand, 0, NULL, 184: ai_stand, 0, NULL, 185: ai_stand, 0, NULL, 186: ai_stand, 0, NULL, 187: ai_stand, 0, NULL, 188: ai_stand, 0, NULL, 189: ai_stand, 0, NULL, 190: ai_stand, 0, NULL, 191: ai_stand, 0, NULL, 192: ai_stand, 0, NULL, 193: 194: ai_stand, 0, NULL, 195: ai_stand, 0, NULL, 196: ai_stand, 0, NULL, 197: ai_stand, 0, NULL, 198: ai_stand, 0, NULL, 199: ai_stand, 0, NULL, 200: ai_stand, 4, NULL, 201: ai_stand, 1, NULL, 202: ai_stand, -1, NULL, 203: ai_stand, -2, NULL, 204: 205: ai_stand, 0, NULL, 206: ai_stand, 0, NULL 207: }; 208: mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL}; 209: #endif 210: 211: void soldier_stand (edict_t *self) 212: { 213: if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8)) 214: self->monsterinfo.currentmove = &soldier_move_stand1; 215: else 216: self->monsterinfo.currentmove = &soldier_move_stand3; 217: } 218: 219: 220: // 221: // WALK 222: // 223: 224: void soldier_walk1_random (edict_t *self) 225: { 226: if (random() > 0.1) 227: self->monsterinfo.nextframe = FRAME_walk101; 228: } 229: 230: mframe_t soldier_frames_walk1 [] = 231: { 232: ai_walk, 3, NULL, 233: ai_walk, 6, NULL, 234: ai_walk, 2, NULL, 235: ai_walk, 2, NULL, 236: ai_walk, 2, NULL, 237: ai_walk, 1, NULL, 238: ai_walk, 6, NULL, 239: ai_walk, 5, NULL, 240: ai_walk, 3, NULL, 241: ai_walk, -1, soldier_walk1_random, 242: ai_walk, 0, NULL, 243: ai_walk, 0, NULL, 244: ai_walk, 0, NULL, 245: ai_walk, 0, NULL, 246: ai_walk, 0, NULL, 247: ai_walk, 0, NULL, 248: ai_walk, 0, NULL, 249: ai_walk, 0, NULL, 250: ai_walk, 0, NULL, 251: ai_walk, 0, NULL, 252: ai_walk, 0, NULL, 253: ai_walk, 0, NULL, 254: ai_walk, 0, NULL, 255: ai_walk, 0, NULL, 256: ai_walk, 0, NULL, 257: ai_walk, 0, NULL, 258: ai_walk, 0, NULL, 259: ai_walk, 0, NULL, 260: ai_walk, 0, NULL, 261: ai_walk, 0, NULL, 262: ai_walk, 0, NULL, 263: ai_walk, 0, NULL, 264: ai_walk, 0, NULL 265: }; 266: mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL}; 267: 268: mframe_t soldier_frames_walk2 [] = 269: { 270: ai_walk, 4, NULL, 271: ai_walk, 4, NULL, 272: ai_walk, 9, NULL, 273: ai_walk, 8, NULL, 274: ai_walk, 5, NULL, 275: ai_walk, 1, NULL, 276: ai_walk, 3, NULL, 277: ai_walk, 7, NULL, 278: ai_walk, 6, NULL, 279: ai_walk, 7, NULL 280: }; 281: mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL}; 282: 283: void soldier_walk (edict_t *self) 284: { 285: if (random() < 0.5) 286: self->monsterinfo.currentmove = &soldier_move_walk1; 287: else 288: self->monsterinfo.currentmove = &soldier_move_walk2; 289: } 290: 291: 292: // 293: // RUN 294: // 295: 296: void soldier_run (edict_t *self); 297: 298: mframe_t soldier_frames_start_run [] = 299: { 300: ai_run, 7, NULL, 301: ai_run, 5, NULL 302: }; 303: mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run}; 304: 305: mframe_t soldier_frames_run [] = 306: { 307: ai_run, 10, NULL, 308: ai_run, 11, NULL, 309: ai_run, 11, NULL, 310: ai_run, 16, NULL, 311: ai_run, 10, NULL, 312: ai_run, 15, NULL 313: }; 314: mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL}; 315: 316: void soldier_run (edict_t *self) 317: { 318: if (self->monsterinfo.aiflags & AI_STAND_GROUND) 319: { 320: self->monsterinfo.currentmove = &soldier_move_stand1; 321: return; 322: } 323: 324: if (self->monsterinfo.currentmove == &soldier_move_walk1 || 325: self->monsterinfo.currentmove == &soldier_move_walk2 || 326: self->monsterinfo.currentmove == &soldier_move_start_run) 327: { 328: self->monsterinfo.currentmove = &soldier_move_run; 329: } 330: else 331: { 332: self->monsterinfo.currentmove = &soldier_move_start_run; 333: } 334: } 335: 336: 337: // 338: // PAIN 339: // 340: 341: mframe_t soldier_frames_pain1 [] = 342: { 343: ai_move, -3, NULL, 344: ai_move, 4, NULL, 345: ai_move, 1, NULL, 346: ai_move, 1, NULL, 347: ai_move, 0, NULL 348: }; 349: mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run}; 350: 351: mframe_t soldier_frames_pain2 [] = 352: { 353: ai_move, -13, NULL, 354: ai_move, -1, NULL, 355: ai_move, 2, NULL, 356: ai_move, 4, NULL, 357: ai_move, 2, NULL, 358: ai_move, 3, NULL, 359: ai_move, 2, NULL 360: }; 361: mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run}; 362: 363: mframe_t soldier_frames_pain3 [] = 364: { 365: ai_move, -8, NULL, 366: ai_move, 10, NULL, 367: ai_move, -4, NULL, 368: ai_move, -1, NULL, 369: ai_move, -3, NULL, 370: ai_move, 0, NULL, 371: ai_move, 3, NULL, 372: ai_move, 0, NULL, 373: ai_move, 0, NULL, 374: ai_move, 0, NULL, 375: ai_move, 0, NULL, 376: ai_move, 1, NULL, 377: ai_move, 0, NULL, 378: ai_move, 1, NULL, 379: ai_move, 2, NULL, 380: ai_move, 4, NULL, 381: ai_move, 3, NULL, 382: ai_move, 2, NULL 383: }; 384: mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run}; 385: 386: mframe_t soldier_frames_pain4 [] = 387: { 388: ai_move, 0, NULL, 389: ai_move, 0, NULL, 390: ai_move, 0, NULL, 391: ai_move, -10, NULL, 392: ai_move, -6, NULL, 393: ai_move, 8, NULL, 394: ai_move, 4, NULL, 395: ai_move, 1, NULL, 396: ai_move, 0, NULL, 397: ai_move, 2, NULL, 398: ai_move, 5, NULL, 399: ai_move, 2, NULL, 400: ai_move, -1, NULL, 401: ai_move, -1, NULL, 402: ai_move, 3, NULL, 403: ai_move, 2, NULL, 404: ai_move, 0, NULL 405: }; 406: mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run}; 407: 408: 409: void soldier_pain (edict_t *self, edict_t *other, float kick, int damage) 410: { 411: float r; 412: int n; 413: 414: if (self->health < (self->max_health / 2)) 415: self->s.skinnum |= 1; 416: 417: if (level.time < self->pain_debounce_time) 418: { 419: if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3))) 420: self->monsterinfo.currentmove = &soldier_move_pain4; 421: return; 422: } 423: 424: self->pain_debounce_time = level.time + 3; 425: 426: n = self->s.skinnum | 1; 427: if (n == 1) 428: gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0); 429: else if (n == 3) 430: gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); 431: else 432: gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0); 433: 434: if (self->velocity[2] > 100) 435: { 436: self->monsterinfo.currentmove = &soldier_move_pain4; 437: return; 438: } 439: 440: if (skill->value == 3) 441: return; // no pain anims in nightmare 442: 443: r = random(); 444: 445: if (r < 0.33) 446: self->monsterinfo.currentmove = &soldier_move_pain1; 447: else if (r < 0.66) 448: self->monsterinfo.currentmove = &soldier_move_pain2; 449: else 450: self->monsterinfo.currentmove = &soldier_move_pain3; 451: } 452: 453: 454: // 455: // ATTACK 456: // 457: 458: static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8}; 459: static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8}; 460: static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8}; 461: 462: void soldier_fire (edict_t *self, int flash_number) 463: { 464: vec3_t start; 465: vec3_t forward, right, up; 466: vec3_t aim; 467: vec3_t dir; 468: vec3_t end; 469: float r, u; 470: int flash_index; 471: 472: if (self->s.skinnum < 2) 473: flash_index = blaster_flash[flash_number]; 474: else if (self->s.skinnum < 4) 475: flash_index = shotgun_flash[flash_number]; 476: else 477: flash_index = machinegun_flash[flash_number]; 478: 479: AngleVectors (self->s.angles, forward, right, NULL); 480: G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start); 481: 482: if (flash_number == 5 || flash_number == 6) 483: { 484: VectorCopy (forward, aim); 485: } 486: else 487: { 488: VectorCopy (self->enemy->s.origin, end); 489: end[2] += self->enemy->viewheight; 490: VectorSubtract (end, start, aim); 491: vectoangles (aim, dir); 492: AngleVectors (dir, forward, right, up); 493: 494: r = crandom()*1000; 495: u = crandom()*500; 496: VectorMA (start, 8192, forward, end); 497: VectorMA (end, r, right, end); 498: VectorMA (end, u, up, end); 499: 500: VectorSubtract (end, start, aim); 501: VectorNormalize (aim); 502: } 503: 504: if (self->s.skinnum <= 1) 505: { 506: monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER); 507: } 508: else if (self->s.skinnum <= 3) 509: { 510: monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index); 511: } 512: else 513: { 514: if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) 515: self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME; 516: 517: monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index); 518: 519: if (level.time >= self->monsterinfo.pausetime) 520: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; 521: else 522: self->monsterinfo.aiflags |= AI_HOLD_FRAME; 523: } 524: } 525: 526: // ATTACK1 (blaster/shotgun) 527: 528: void soldier_fire1 (edict_t *self) 529: { 530: soldier_fire (self, 0); 531: } 532: 533: void soldier_attack1_refire1 (edict_t *self) 534: { 535: if (self->s.skinnum > 1) 536: return; 537: 538: if (self->enemy->health <= 0) 539: return; 540: 541: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 542: self->monsterinfo.nextframe = FRAME_attak102; 543: else 544: self->monsterinfo.nextframe = FRAME_attak110; 545: } 546: 547: void soldier_attack1_refire2 (edict_t *self) 548: { 549: if (self->s.skinnum < 2) 550: return; 551: 552: if (self->enemy->health <= 0) 553: return; 554: 555: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 556: self->monsterinfo.nextframe = FRAME_attak102; 557: } 558: 559: mframe_t soldier_frames_attack1 [] = 560: { 561: ai_charge, 0, NULL, 562: ai_charge, 0, NULL, 563: ai_charge, 0, soldier_fire1, 564: ai_charge, 0, NULL, 565: ai_charge, 0, NULL, 566: ai_charge, 0, soldier_attack1_refire1, 567: ai_charge, 0, NULL, 568: ai_charge, 0, soldier_cock, 569: ai_charge, 0, soldier_attack1_refire2, 570: ai_charge, 0, NULL, 571: ai_charge, 0, NULL, 572: ai_charge, 0, NULL 573: }; 574: mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run}; 575: 576: // ATTACK2 (blaster/shotgun) 577: 578: void soldier_fire2 (edict_t *self) 579: { 580: soldier_fire (self, 1); 581: } 582: 583: void soldier_attack2_refire1 (edict_t *self) 584: { 585: if (self->s.skinnum > 1) 586: return; 587: 588: if (self->enemy->health <= 0) 589: return; 590: 591: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 592: self->monsterinfo.nextframe = FRAME_attak204; 593: else 594: self->monsterinfo.nextframe = FRAME_attak216; 595: } 596: 597: void soldier_attack2_refire2 (edict_t *self) 598: { 599: if (self->s.skinnum < 2) 600: return; 601: 602: if (self->enemy->health <= 0) 603: return; 604: 605: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 606: self->monsterinfo.nextframe = FRAME_attak204; 607: } 608: 609: mframe_t soldier_frames_attack2 [] = 610: { 611: ai_charge, 0, NULL, 612: ai_charge, 0, NULL, 613: ai_charge, 0, NULL, 614: ai_charge, 0, NULL, 615: ai_charge, 0, soldier_fire2, 616: ai_charge, 0, NULL, 617: ai_charge, 0, NULL, 618: ai_charge, 0, soldier_attack2_refire1, 619: ai_charge, 0, NULL, 620: ai_charge, 0, NULL, 621: ai_charge, 0, NULL, 622: ai_charge, 0, NULL, 623: ai_charge, 0, soldier_cock, 624: ai_charge, 0, NULL, 625: ai_charge, 0, soldier_attack2_refire2, 626: ai_charge, 0, NULL, 627: ai_charge, 0, NULL, 628: ai_charge, 0, NULL 629: }; 630: mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run}; 631: 632: // ATTACK3 (duck and shoot) 633: 634: void soldier_duck_down (edict_t *self) 635: { 636: if (self->monsterinfo.aiflags & AI_DUCKED) 637: return; 638: self->monsterinfo.aiflags |= AI_DUCKED; 639: self->maxs[2] -= 32; 640: self->takedamage = DAMAGE_YES; 641: self->monsterinfo.pausetime = level.time + 1; 642: gi.linkentity (self); 643: } 644: 645: void soldier_duck_up (edict_t *self) 646: { 647: self->monsterinfo.aiflags &= ~AI_DUCKED; 648: self->maxs[2] += 32; 649: self->takedamage = DAMAGE_AIM; 650: gi.linkentity (self); 651: } 652: 653: void soldier_fire3 (edict_t *self) 654: { 655: soldier_duck_down (self); 656: soldier_fire (self, 2); 657: } 658: 659: void soldier_attack3_refire (edict_t *self) 660: { 661: if ((level.time + 0.4) < self->monsterinfo.pausetime) 662: self->monsterinfo.nextframe = FRAME_attak303; 663: } 664: 665: mframe_t soldier_frames_attack3 [] = 666: { 667: ai_charge, 0, NULL, 668: ai_charge, 0, NULL, 669: ai_charge, 0, soldier_fire3, 670: ai_charge, 0, NULL, 671: ai_charge, 0, NULL, 672: ai_charge, 0, soldier_attack3_refire, 673: ai_charge, 0, soldier_duck_up, 674: ai_charge, 0, NULL, 675: ai_charge, 0, NULL 676: }; 677: mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run}; 678: 679: // ATTACK4 (machinegun) 680: 681: void soldier_fire4 (edict_t *self) 682: { 683: soldier_fire (self, 3); 684: // 685: // if (self->enemy->health <= 0) 686: // return; 687: // 688: // if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 689: // self->monsterinfo.nextframe = FRAME_attak402; 690: } 691: 692: mframe_t soldier_frames_attack4 [] = 693: { 694: ai_charge, 0, NULL, 695: ai_charge, 0, NULL, 696: ai_charge, 0, soldier_fire4, 697: ai_charge, 0, NULL, 698: ai_charge, 0, NULL, 699: ai_charge, 0, NULL 700: }; 701: mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run}; 702: 703: #if 0 704: // ATTACK5 (prone) 705: 706: void soldier_fire5 (edict_t *self) 707: { 708: soldier_fire (self, 4); 709: } 710: 711: void soldier_attack5_refire (edict_t *self) 712: { 713: if (self->enemy->health <= 0) 714: return; 715: 716: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) 717: self->monsterinfo.nextframe = FRAME_attak505; 718: } 719: 720: mframe_t soldier_frames_attack5 [] = 721: { 722: ai_charge, 8, NULL, 723: ai_charge, 8, NULL, 724: ai_charge, 0, NULL, 725: ai_charge, 0, NULL, 726: ai_charge, 0, soldier_fire5, 727: ai_charge, 0, NULL, 728: ai_charge, 0, NULL, 729: ai_charge, 0, soldier_attack5_refire 730: }; 731: mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run}; 732: #endif 733: 734: // ATTACK6 (run & shoot) 735: 736: void soldier_fire8 (edict_t *self) 737: { 738: soldier_fire (self, 7); 739: } 740: 741: void soldier_attack6_refire (edict_t *self) 742: { 743: if (self->enemy->health <= 0) 744: return; 745: 746: if (range(self, self->enemy) < RANGE_MID) 747: return; 748: 749: if (skill->value == 3) 750: self->monsterinfo.nextframe = FRAME_runs03; 751: } 752: 753: mframe_t soldier_frames_attack6 [] = 754: { 755: ai_charge, 10, NULL, 756: ai_charge, 4, NULL, 757: ai_charge, 12, NULL, 758: ai_charge, 11, soldier_fire8, 759: ai_charge, 13, NULL, 760: ai_charge, 18, NULL, 761: ai_charge, 15, NULL, 762: ai_charge, 14, NULL, 763: ai_charge, 11, NULL, 764: ai_charge, 8, NULL, 765: ai_charge, 11, NULL, 766: ai_charge, 12, NULL, 767: ai_charge, 12, NULL, 768: ai_charge, 17, soldier_attack6_refire 769: }; 770: mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run}; 771: 772: void soldier_attack(edict_t *self) 773: { 774: if (self->s.skinnum < 4) 775: { 776: if (random() < 0.5) 777: self->monsterinfo.currentmove = &soldier_move_attack1; 778: else 779: self->monsterinfo.currentmove = &soldier_move_attack2; 780: } 781: else 782: { 783: self->monsterinfo.currentmove = &soldier_move_attack4; 784: } 785: } 786: 787: 788: // 789: // SIGHT 790: // 791: 792: void soldier_sight(edict_t *self, edict_t *other) 793: { 794: if (random() < 0.5) 795: gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0); 796: else 797: gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0); 798: 799: if ((skill->value > 0) && (range(self, self->enemy) >= RANGE_MID)) 800: { 801: if (random() > 0.5) 802: self->monsterinfo.currentmove = &soldier_move_attack6; 803: } 804: } 805: 806: // 807: // DUCK 808: // 809: 810: void soldier_duck_hold (edict_t *self) 811: { 812: if (level.time >= self->monsterinfo.pausetime) 813: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; 814: else 815: self->monsterinfo.aiflags |= AI_HOLD_FRAME; 816: } 817: 818: mframe_t soldier_frames_duck [] = 819: { 820: ai_move, 5, soldier_duck_down, 821: ai_move, -1, soldier_duck_hold, 822: ai_move, 1, NULL, 823: ai_move, 0, soldier_duck_up, 824: ai_move, 5, NULL 825: }; 826: mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run}; 827: 828: void soldier_dodge (edict_t *self, edict_t *attacker, float eta) 829: { 830: float r; 831: 832: r = random(); 833: if (r > 0.25) 834: return; 835: 836: if (!self->enemy) 837: self->enemy = attacker; 838: 839: if (skill->value == 0) 840: { 841: self->monsterinfo.currentmove = &soldier_move_duck; 842: return; 843: } 844: 845: self->monsterinfo.pausetime = level.time + eta + 0.3; 846: r = random(); 847: 848: if (skill->value == 1) 849: { 850: if (r > 0.33) 851: self->monsterinfo.currentmove = &soldier_move_duck; 852: else 853: self->monsterinfo.currentmove = &soldier_move_attack3; 854: return; 855: } 856: 857: if (skill->value >= 2) 858: { 859: if (r > 0.66) 860: self->monsterinfo.currentmove = &soldier_move_duck; 861: else 862: self->monsterinfo.currentmove = &soldier_move_attack3; 863: return; 864: } 865: 866: self->monsterinfo.currentmove = &soldier_move_attack3; 867: } 868: 869: 870: // 871: // DEATH 872: // 873: 874: void soldier_fire6 (edict_t *self) 875: { 876: soldier_fire (self, 5); 877: } 878: 879: void soldier_fire7 (edict_t *self) 880: { 881: soldier_fire (self, 6); 882: } 883: 884: void soldier_dead (edict_t *self) 885: { 886: VectorSet (self->mins, -16, -16, -24); 887: VectorSet (self->maxs, 16, 16, -8); 888: self->movetype = MOVETYPE_TOSS; 889: self->svflags |= SVF_DEADMONSTER; 890: self->nextthink = 0; 891: gi.linkentity (self); 892: } 893: 894: mframe_t soldier_frames_death1 [] = 895: { 896: ai_move, 0, NULL, 897: ai_move, -10, NULL, 898: ai_move, -10, NULL, 899: ai_move, -10, NULL, 900: ai_move, -5, NULL, 901: ai_move, 0, NULL, 902: ai_move, 0, NULL, 903: ai_move, 0, NULL, 904: ai_move, 0, NULL, 905: ai_move, 0, NULL, 906: 907: ai_move, 0, NULL, 908: ai_move, 0, NULL, 909: ai_move, 0, NULL, 910: ai_move, 0, NULL, 911: ai_move, 0, NULL, 912: ai_move, 0, NULL, 913: ai_move, 0, NULL, 914: ai_move, 0, NULL, 915: ai_move, 0, NULL, 916: ai_move, 0, NULL, 917: 918: ai_move, 0, NULL, 919: ai_move, 0, soldier_fire6, 920: ai_move, 0, NULL, 921: ai_move, 0, NULL, 922: ai_move, 0, soldier_fire7, 923: ai_move, 0, NULL, 924: ai_move, 0, NULL, 925: ai_move, 0, NULL, 926: ai_move, 0, NULL, 927: ai_move, 0, NULL, 928: 929: ai_move, 0, NULL, 930: ai_move, 0, NULL, 931: ai_move, 0, NULL, 932: ai_move, 0, NULL, 933: ai_move, 0, NULL, 934: ai_move, 0, NULL 935: }; 936: mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead}; 937: 938: mframe_t soldier_frames_death2 [] = 939: { 940: ai_move, -5, NULL, 941: ai_move, -5, NULL, 942: ai_move, -5, NULL, 943: ai_move, 0, NULL, 944: ai_move, 0, NULL, 945: ai_move, 0, NULL, 946: ai_move, 0, NULL, 947: ai_move, 0, NULL, 948: ai_move, 0, NULL, 949: ai_move, 0, NULL, 950: 951: ai_move, 0, NULL, 952: ai_move, 0, NULL, 953: ai_move, 0, NULL, 954: ai_move, 0, NULL, 955: ai_move, 0, NULL, 956: ai_move, 0, NULL, 957: ai_move, 0, NULL, 958: ai_move, 0, NULL, 959: ai_move, 0, NULL, 960: ai_move, 0, NULL, 961: 962: ai_move, 0, NULL, 963: ai_move, 0, NULL, 964: ai_move, 0, NULL, 965: ai_move, 0, NULL, 966: ai_move, 0, NULL, 967: ai_move, 0, NULL, 968: ai_move, 0, NULL, 969: ai_move, 0, NULL, 970: ai_move, 0, NULL, 971: ai_move, 0, NULL, 972: 973: ai_move, 0, NULL, 974: ai_move, 0, NULL, 975: ai_move, 0, NULL, 976: ai_move, 0, NULL, 977: ai_move, 0, NULL 978: }; 979: mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead}; 980: 981: mframe_t soldier_frames_death3 [] = 982: { 983: ai_move, -5, NULL, 984: ai_move, -5, NULL, 985: ai_move, -5, NULL, 986: ai_move, 0, NULL, 987: ai_move, 0, NULL, 988: ai_move, 0, NULL, 989: ai_move, 0, NULL, 990: ai_move, 0, NULL, 991: ai_move, 0, NULL, 992: ai_move, 0, NULL, 993: 994: ai_move, 0, NULL, 995: ai_move, 0, NULL, 996: ai_move, 0, NULL, 997: ai_move, 0, NULL, 998: ai_move, 0, NULL, 999: ai_move, 0, NULL, 1000: ai_move, 0, NULL, 1001: ai_move, 0, NULL, 1002: ai_move, 0, NULL, 1003: ai_move, 0, NULL, 1004: 1005: ai_move, 0, NULL, 1006: ai_move, 0, NULL, 1007: ai_move, 0, NULL, 1008: ai_move, 0, NULL, 1009: ai_move, 0, NULL, 1010: ai_move, 0, NULL, 1011: ai_move, 0, NULL, 1012: ai_move, 0, NULL, 1013: ai_move, 0, NULL, 1014: ai_move, 0, NULL, 1015: 1016: ai_move, 0, NULL, 1017: ai_move, 0, NULL, 1018: ai_move, 0, NULL, 1019: ai_move, 0, NULL, 1020: ai_move, 0, NULL, 1021: ai_move, 0, NULL, 1022: ai_move, 0, NULL, 1023: ai_move, 0, NULL, 1024: ai_move, 0, NULL, 1025: ai_move, 0, NULL, 1026: 1027: ai_move, 0, NULL, 1028: ai_move, 0, NULL, 1029: ai_move, 0, NULL, 1030: ai_move, 0, NULL, 1031: ai_move, 0, NULL, 1032: }; 1033: mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead}; 1034: 1035: mframe_t soldier_frames_death4 [] = 1036: { 1037: ai_move, 0, NULL, 1038: ai_move, 0, NULL, 1039: ai_move, 0, NULL, 1040: ai_move, 0, NULL, 1041: ai_move, 0, NULL, 1042: ai_move, 0, NULL, 1043: ai_move, 0, NULL, 1044: ai_move, 0, NULL, 1045: ai_move, 0, NULL, 1046: ai_move, 0, NULL, 1047: 1048: ai_move, 0, NULL, 1049: ai_move, 0, NULL, 1050: ai_move, 0, NULL, 1051: ai_move, 0, NULL, 1052: ai_move, 0, NULL, 1053: ai_move, 0, NULL, 1054: ai_move, 0, NULL, 1055: ai_move, 0, NULL, 1056: ai_move, 0, NULL, 1057: ai_move, 0, NULL, 1058: 1059: ai_move, 0, NULL, 1060: ai_move, 0, NULL, 1061: ai_move, 0, NULL, 1062: ai_move, 0, NULL, 1063: ai_move, 0, NULL, 1064: ai_move, 0, NULL, 1065: ai_move, 0, NULL, 1066: ai_move, 0, NULL, 1067: ai_move, 0, NULL, 1068: ai_move, 0, NULL, 1069: 1070: ai_move, 0, NULL, 1071: ai_move, 0, NULL, 1072: ai_move, 0, NULL, 1073: ai_move, 0, NULL, 1074: ai_move, 0, NULL, 1075: ai_move, 0, NULL, 1076: ai_move, 0, NULL, 1077: ai_move, 0, NULL, 1078: ai_move, 0, NULL, 1079: ai_move, 0, NULL, 1080: 1081: ai_move, 0, NULL, 1082: ai_move, 0, NULL, 1083: ai_move, 0, NULL, 1084: ai_move, 0, NULL, 1085: ai_move, 0, NULL, 1086: ai_move, 0, NULL, 1087: ai_move, 0, NULL, 1088: ai_move, 0, NULL, 1089: ai_move, 0, NULL, 1090: ai_move, 0, NULL, 1091: 1092: ai_move, 0, NULL, 1093: ai_move, 0, NULL, 1094: ai_move, 0, NULL 1095: }; 1096: mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead}; 1097: 1098: mframe_t soldier_frames_death5 [] = 1099: { 1100: ai_move, -5, NULL, 1101: ai_move, -5, NULL, 1102: ai_move, -5, NULL, 1103: ai_move, 0, NULL, 1104: ai_move, 0, NULL, 1105: ai_move, 0, NULL, 1106: ai_move, 0, NULL, 1107: ai_move, 0, NULL, 1108: ai_move, 0, NULL, 1109: ai_move, 0, NULL, 1110: 1111: ai_move, 0, NULL, 1112: ai_move, 0, NULL, 1113: ai_move, 0, NULL, 1114: ai_move, 0, NULL, 1115: ai_move, 0, NULL, 1116: ai_move, 0, NULL, 1117: ai_move, 0, NULL, 1118: ai_move, 0, NULL, 1119: ai_move, 0, NULL, 1120: ai_move, 0, NULL, 1121: 1122: ai_move, 0, NULL, 1123: ai_move, 0, NULL, 1124: ai_move, 0, NULL, 1125: ai_move, 0, NULL 1126: }; 1127: mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead}; 1128: 1129: mframe_t soldier_frames_death6 [] = 1130: { 1131: ai_move, 0, NULL, 1132: ai_move, 0, NULL, 1133: ai_move, 0, NULL, 1134: ai_move, 0, NULL, 1135: ai_move, 0, NULL, 1136: ai_move, 0, NULL, 1137: ai_move, 0, NULL, 1138: ai_move, 0, NULL, 1139: ai_move, 0, NULL, 1140: ai_move, 0, NULL 1141: }; 1142: mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead}; 1143: 1144: void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) 1145: { 1146: int n; 1147: 1148: // check for gib 1149: if (self->health <= self->gib_health) 1150: { 1151: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); 1152: for (n= 0; n < 3; n++) 1153: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); 1154: ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); 1155: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); 1156: self->deadflag = DEAD_DEAD; 1157: return; 1158: } 1159: 1160: if (self->deadflag == DEAD_DEAD) 1161: return; 1162: 1163: // regular death 1164: self->deadflag = DEAD_DEAD; 1165: self->takedamage = DAMAGE_YES; 1166: self->s.skinnum |= 1; 1167: 1168: if (self->s.skinnum == 1) 1169: gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0); 1170: else if (self->s.skinnum == 3) 1171: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); 1172: else // (self->s.skinnum == 5) 1173: gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0); 1174: 1175: if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4) 1176: { 1177: // head shot 1178: self->monsterinfo.currentmove = &soldier_move_death3; 1179: return; 1180: } 1181: 1182: n = rand() % 5; 1183: if (n == 0) 1184: self->monsterinfo.currentmove = &soldier_move_death1; 1185: else if (n == 1) 1186: self->monsterinfo.currentmove = &soldier_move_death2; 1187: else if (n == 2) 1188: self->monsterinfo.currentmove = &soldier_move_death4; 1189: else if (n == 3) 1190: self->monsterinfo.currentmove = &soldier_move_death5; 1191: else 1192: self->monsterinfo.currentmove = &soldier_move_death6; 1193: } 1194: 1195: 1196: // 1197: // SPAWN 1198: // 1199: 1200: void SP_monster_soldier_x (edict_t *self) 1201: { 1202: 1203: self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2"); 1204: self->monsterinfo.scale = MODEL_SCALE; 1205: VectorSet (self->mins, -16, -16, -24); 1206: VectorSet (self->maxs, 16, 16, 32); 1207: self->movetype = MOVETYPE_STEP; 1208: self->solid = SOLID_BBOX; 1209: 1210: sound_idle = gi.soundindex ("soldier/solidle1.wav"); 1211: sound_sight1 = gi.soundindex ("soldier/solsght1.wav"); 1212: sound_sight2 = gi.soundindex ("soldier/solsrch1.wav"); 1213: sound_cock = gi.soundindex ("infantry/infatck3.wav"); 1214: 1215: self->mass = 100; 1216: 1217: self->pain = soldier_pain; 1218: self->die = soldier_die; 1219: 1220: self->monsterinfo.stand = soldier_stand; 1221: self->monsterinfo.walk = soldier_walk; 1222: self->monsterinfo.run = soldier_run; 1223: self->monsterinfo.dodge = soldier_dodge; 1224: self->monsterinfo.attack = soldier_attack; 1225: self->monsterinfo.melee = NULL; 1226: self->monsterinfo.sight = soldier_sight; 1227: 1228: gi.linkentity (self); 1229: 1230: self->monsterinfo.stand (self); 1231: 1232: walkmonster_start (self); 1233: } 1234: 1235: 1236: /*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight 1237: */ 1238: void SP_monster_soldier_light (edict_t *self) 1239: { 1240: if (deathmatch->value) 1241: { 1242: G_FreeEdict (self); 1243: return; 1244: } 1245: 1246: SP_monster_soldier_x (self); 1247: 1248: sound_pain_light = gi.soundindex ("soldier/solpain2.wav"); 1249: sound_death_light = gi.soundindex ("soldier/soldeth2.wav"); 1250: gi.modelindex ("models/objects/laser/tris.md2"); 1251: gi.soundindex ("misc/lasfly.wav"); 1252: gi.soundindex ("soldier/solatck2.wav"); 1253: 1254: self->s.skinnum = 0; 1255: self->health = 20; 1256: self->gib_health = -30; 1257: } 1258: 1259: /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight 1260: */ 1261: void SP_monster_soldier (edict_t *self) 1262: { 1263: if (deathmatch->value) 1264: { 1265: G_FreeEdict (self); 1266: return; 1267: } 1268: 1269: SP_monster_soldier_x (self); 1270: 1271: sound_pain = gi.soundindex ("soldier/solpain1.wav"); 1272: sound_death = gi.soundindex ("soldier/soldeth1.wav"); 1273: gi.soundindex ("soldier/solatck1.wav"); 1274: 1275: self->s.skinnum = 2; 1276: self->health = 30; 1277: self->gib_health = -30; 1278: } 1279: 1280: /*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight 1281: */ 1282: void SP_monster_soldier_ss (edict_t *self) 1283: { 1284: if (deathmatch->value) 1285: { 1286: G_FreeEdict (self); 1287: return; 1288: } 1289: 1290: SP_monster_soldier_x (self); 1291: 1292: sound_pain_ss = gi.soundindex ("soldier/solpain3.wav"); 1293: sound_death_ss = gi.soundindex ("soldier/soldeth3.wav"); 1294: gi.soundindex ("soldier/solatck3.wav"); 1295: 1296: self->s.skinnum = 4; 1297: self->health = 40; 1298: self->gib_health = -30; 1299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.