|
|
1.1 ! root 1: /* ! 2: ============================================================================== ! 3: ! 4: GUNNER ! 5: ! 6: ============================================================================== ! 7: */ ! 8: ! 9: #include "g_local.h" ! 10: #include "m_gunner.h" ! 11: ! 12: ! 13: static int sound_pain; ! 14: static int sound_pain2; ! 15: static int sound_death; ! 16: static int sound_idle; ! 17: static int sound_open; ! 18: static int sound_search; ! 19: static int sound_sight; ! 20: ! 21: ! 22: void gunner_idlesound (edict_t *self) ! 23: { ! 24: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); ! 25: } ! 26: ! 27: void gunner_sight (edict_t *self, edict_t *other) ! 28: { ! 29: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); ! 30: } ! 31: ! 32: void gunner_search (edict_t *self) ! 33: { ! 34: gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); ! 35: } ! 36: ! 37: ! 38: qboolean visible (edict_t *self, edict_t *other); ! 39: void GunnerGrenade (edict_t *self); ! 40: void GunnerFire (edict_t *self); ! 41: void gunner_fire_chain(edict_t *self); ! 42: void gunner_refire_chain(edict_t *self); ! 43: ! 44: ! 45: void gunner_stand (edict_t *self); ! 46: ! 47: mframe_t gunner_frames_fidget [] = ! 48: { ! 49: ai_stand, 0, NULL, ! 50: ai_stand, 0, NULL, ! 51: ai_stand, 0, NULL, ! 52: ai_stand, 0, NULL, ! 53: ai_stand, 0, NULL, ! 54: ai_stand, 0, NULL, ! 55: ai_stand, 0, NULL, ! 56: ai_stand, 0, gunner_idlesound, ! 57: ai_stand, 0, NULL, ! 58: ! 59: ai_stand, 0, NULL, ! 60: ai_stand, 0, NULL, ! 61: ai_stand, 0, NULL, ! 62: ai_stand, 0, NULL, ! 63: ai_stand, 0, NULL, ! 64: ai_stand, 0, NULL, ! 65: ai_stand, 0, NULL, ! 66: ai_stand, 0, NULL, ! 67: ai_stand, 0, NULL, ! 68: ai_stand, 0, NULL, ! 69: ! 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: 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: ! 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: 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: ! 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: }; ! 103: mmove_t gunner_move_fidget = {FRAME_stand31, FRAME_stand70, gunner_frames_fidget, gunner_stand}; ! 104: ! 105: void gunner_fidget (edict_t *self) ! 106: { ! 107: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 108: return; ! 109: if (random() <= 0.05) ! 110: self->monsterinfo.currentmove = &gunner_move_fidget; ! 111: } ! 112: ! 113: mframe_t gunner_frames_stand [] = ! 114: { ! 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, gunner_fidget, ! 125: ! 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, ! 135: ai_stand, 0, gunner_fidget, ! 136: ! 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: ai_stand, 0, NULL, ! 145: ai_stand, 0, NULL, ! 146: ai_stand, 0, gunner_fidget ! 147: }; ! 148: mmove_t gunner_move_stand = {FRAME_stand01, FRAME_stand30, gunner_frames_stand, NULL}; ! 149: ! 150: void gunner_stand (edict_t *self) ! 151: { ! 152: self->monsterinfo.currentmove = &gunner_move_stand; ! 153: } ! 154: ! 155: ! 156: mframe_t gunner_frames_walk [] = ! 157: { ! 158: ai_walk, 0, NULL, ! 159: ai_walk, 3, NULL, ! 160: ai_walk, 4, NULL, ! 161: ai_walk, 5, NULL, ! 162: ai_walk, 7, NULL, ! 163: ai_walk, 2, NULL, ! 164: ai_walk, 6, NULL, ! 165: ai_walk, 4, NULL, ! 166: ai_walk, 2, NULL, ! 167: ai_walk, 7, NULL, ! 168: ai_walk, 5, NULL, ! 169: ai_walk, 7, NULL, ! 170: ai_walk, 4, NULL ! 171: }; ! 172: mmove_t gunner_move_walk = {FRAME_walk07, FRAME_walk19, gunner_frames_walk, NULL}; ! 173: ! 174: void gunner_walk (edict_t *self) ! 175: { ! 176: self->monsterinfo.currentmove = &gunner_move_walk; ! 177: } ! 178: ! 179: mframe_t gunner_frames_run [] = ! 180: { ! 181: ai_run, 26, NULL, ! 182: ai_run, 9, NULL, ! 183: ai_run, 9, NULL, ! 184: ai_run, 9, NULL, ! 185: ai_run, 15, NULL, ! 186: ai_run, 10, NULL, ! 187: ai_run, 13, NULL, ! 188: ai_run, 6, NULL ! 189: }; ! 190: ! 191: mmove_t gunner_move_run = {FRAME_run01, FRAME_run08, gunner_frames_run, NULL}; ! 192: ! 193: void gunner_run (edict_t *self) ! 194: { ! 195: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 196: self->monsterinfo.currentmove = &gunner_move_stand; ! 197: else ! 198: self->monsterinfo.currentmove = &gunner_move_run; ! 199: } ! 200: ! 201: mframe_t gunner_frames_runandshoot [] = ! 202: { ! 203: ai_run, 32, NULL, ! 204: ai_run, 15, NULL, ! 205: ai_run, 10, NULL, ! 206: ai_run, 18, NULL, ! 207: ai_run, 8, NULL, ! 208: ai_run, 20, NULL ! 209: }; ! 210: ! 211: mmove_t gunner_move_runandshoot = {FRAME_runs01, FRAME_runs06, gunner_frames_runandshoot, NULL}; ! 212: ! 213: void gunner_runandshoot (edict_t *self) ! 214: { ! 215: self->monsterinfo.currentmove = &gunner_move_runandshoot; ! 216: } ! 217: ! 218: mframe_t gunner_frames_pain3 [] = ! 219: { ! 220: ai_move, -3, NULL, ! 221: ai_move, 1, NULL, ! 222: ai_move, 1, NULL, ! 223: ai_move, 0, NULL, ! 224: ai_move, 1, NULL ! 225: }; ! 226: mmove_t gunner_move_pain3 = {FRAME_pain301, FRAME_pain305, gunner_frames_pain3, gunner_run}; ! 227: ! 228: mframe_t gunner_frames_pain2 [] = ! 229: { ! 230: ai_move, -2, NULL, ! 231: ai_move, 11, NULL, ! 232: ai_move, 6, NULL, ! 233: ai_move, 2, NULL, ! 234: ai_move, -1, NULL, ! 235: ai_move, -7, NULL, ! 236: ai_move, -2, NULL, ! 237: ai_move, -7, NULL ! 238: }; ! 239: mmove_t gunner_move_pain2 = {FRAME_pain201, FRAME_pain208, gunner_frames_pain2, gunner_run}; ! 240: ! 241: mframe_t gunner_frames_pain1 [] = ! 242: { ! 243: ai_move, 2, NULL, ! 244: ai_move, 0, NULL, ! 245: ai_move, -5, NULL, ! 246: ai_move, 3, NULL, ! 247: ai_move, -1, NULL, ! 248: ai_move, 0, NULL, ! 249: ai_move, 0, NULL, ! 250: ai_move, 0, NULL, ! 251: ai_move, 0, NULL, ! 252: ai_move, 1, NULL, ! 253: ai_move, 1, NULL, ! 254: ai_move, 2, NULL, ! 255: ai_move, 1, NULL, ! 256: ai_move, 0, NULL, ! 257: ai_move, -2, NULL, ! 258: ai_move, -2, NULL, ! 259: ai_move, 0, NULL, ! 260: ai_move, 0, NULL ! 261: }; ! 262: mmove_t gunner_move_pain1 = {FRAME_pain101, FRAME_pain118, gunner_frames_pain1, gunner_run}; ! 263: ! 264: void gunner_pain (edict_t *self, edict_t *other, float kick, int damage) ! 265: { ! 266: if (self->health < (self->max_health / 2)) ! 267: self->s.skinnum = 1; ! 268: ! 269: if (level.time < self->pain_debounce_time) ! 270: return; ! 271: ! 272: self->pain_debounce_time = level.time + 3; ! 273: ! 274: if (rand()&1) ! 275: gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); ! 276: else ! 277: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); ! 278: ! 279: if (skill->value == 3) ! 280: return; // no pain anims in nightmare ! 281: ! 282: if (damage <= 10) ! 283: self->monsterinfo.currentmove = &gunner_move_pain3; ! 284: else if (damage <= 25) ! 285: self->monsterinfo.currentmove = &gunner_move_pain2; ! 286: else ! 287: self->monsterinfo.currentmove = &gunner_move_pain1; ! 288: } ! 289: ! 290: void gunner_dead (edict_t *self) ! 291: { ! 292: VectorSet (self->mins, -16, -16, -24); ! 293: VectorSet (self->maxs, 16, 16, -8); ! 294: self->movetype = MOVETYPE_TOSS; ! 295: self->svflags |= SVF_DEADMONSTER; ! 296: self->nextthink = 0; ! 297: gi.linkentity (self); ! 298: } ! 299: ! 300: mframe_t gunner_frames_death [] = ! 301: { ! 302: ai_move, 0, NULL, ! 303: ai_move, 0, NULL, ! 304: ai_move, 0, NULL, ! 305: ai_move, -7, NULL, ! 306: ai_move, -3, NULL, ! 307: ai_move, -5, NULL, ! 308: ai_move, 8, NULL, ! 309: ai_move, 6, NULL, ! 310: ai_move, 0, NULL, ! 311: ai_move, 0, NULL, ! 312: ai_move, 0, NULL ! 313: }; ! 314: mmove_t gunner_move_death = {FRAME_death01, FRAME_death11, gunner_frames_death, gunner_dead}; ! 315: ! 316: void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) ! 317: { ! 318: int n; ! 319: ! 320: // check for gib ! 321: if (self->health <= self->gib_health) ! 322: { ! 323: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 324: for (n= 0; n < 2; n++) ! 325: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); ! 326: for (n= 0; n < 4; n++) ! 327: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ! 328: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); ! 329: self->deadflag = DEAD_DEAD; ! 330: return; ! 331: } ! 332: ! 333: if (self->deadflag == DEAD_DEAD) ! 334: return; ! 335: ! 336: // regular death ! 337: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); ! 338: self->deadflag = DEAD_DEAD; ! 339: self->takedamage = DAMAGE_YES; ! 340: self->monsterinfo.currentmove = &gunner_move_death; ! 341: } ! 342: ! 343: ! 344: void gunner_duck_down (edict_t *self) ! 345: { ! 346: if (self->monsterinfo.aiflags & AI_DUCKED) ! 347: return; ! 348: self->monsterinfo.aiflags |= AI_DUCKED; ! 349: if (skill->value >= 2) ! 350: { ! 351: if (random() > 0.5) ! 352: GunnerGrenade (self); ! 353: } ! 354: ! 355: self->maxs[2] -= 32; ! 356: self->takedamage = DAMAGE_YES; ! 357: self->monsterinfo.pausetime = level.time + 1; ! 358: gi.linkentity (self); ! 359: } ! 360: ! 361: void gunner_duck_hold (edict_t *self) ! 362: { ! 363: if (level.time >= self->monsterinfo.pausetime) ! 364: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; ! 365: else ! 366: self->monsterinfo.aiflags |= AI_HOLD_FRAME; ! 367: } ! 368: ! 369: void gunner_duck_up (edict_t *self) ! 370: { ! 371: self->monsterinfo.aiflags &= ~AI_DUCKED; ! 372: self->maxs[2] += 32; ! 373: self->takedamage = DAMAGE_AIM; ! 374: gi.linkentity (self); ! 375: } ! 376: ! 377: mframe_t gunner_frames_duck [] = ! 378: { ! 379: ai_move, 1, gunner_duck_down, ! 380: ai_move, 1, NULL, ! 381: ai_move, 1, gunner_duck_hold, ! 382: ai_move, 0, NULL, ! 383: ai_move, -1, NULL, ! 384: ai_move, -1, NULL, ! 385: ai_move, 0, gunner_duck_up, ! 386: ai_move, -1, NULL ! 387: }; ! 388: mmove_t gunner_move_duck = {FRAME_duck01, FRAME_duck08, gunner_frames_duck, gunner_run}; ! 389: ! 390: void gunner_dodge (edict_t *self, edict_t *attacker, float eta) ! 391: { ! 392: if (random() > 0.25) ! 393: return; ! 394: ! 395: if (!self->enemy) ! 396: self->enemy = attacker; ! 397: ! 398: self->monsterinfo.currentmove = &gunner_move_duck; ! 399: } ! 400: ! 401: ! 402: void gunner_opengun (edict_t *self) ! 403: { ! 404: gi.sound (self, CHAN_VOICE, sound_open, 1, ATTN_IDLE, 0); ! 405: } ! 406: ! 407: void GunnerFire (edict_t *self) ! 408: { ! 409: vec3_t start; ! 410: vec3_t forward, right; ! 411: vec3_t target; ! 412: vec3_t aim; ! 413: int flash_number; ! 414: ! 415: flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216); ! 416: ! 417: AngleVectors (self->s.angles, forward, right, NULL); ! 418: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); ! 419: ! 420: // project enemy back a bit and target there ! 421: VectorCopy (self->enemy->s.origin, target); ! 422: VectorMA (target, -0.2, self->enemy->velocity, target); ! 423: target[2] += self->enemy->viewheight; ! 424: ! 425: VectorSubtract (target, start, aim); ! 426: VectorNormalize (aim); ! 427: monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); ! 428: } ! 429: ! 430: void GunnerGrenade (edict_t *self) ! 431: { ! 432: vec3_t start; ! 433: vec3_t forward, right; ! 434: vec3_t aim; ! 435: int flash_number; ! 436: ! 437: if (self->s.frame == FRAME_attak105) ! 438: flash_number = MZ2_GUNNER_GRENADE_1; ! 439: else if (self->s.frame == FRAME_attak108) ! 440: flash_number = MZ2_GUNNER_GRENADE_2; ! 441: else if (self->s.frame == FRAME_attak111) ! 442: flash_number = MZ2_GUNNER_GRENADE_3; ! 443: else // (self->s.frame == FRAME_attak114) ! 444: flash_number = MZ2_GUNNER_GRENADE_4; ! 445: ! 446: AngleVectors (self->s.angles, forward, right, NULL); ! 447: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); ! 448: ! 449: //FIXME : do a spread -225 -75 75 225 degrees around forward ! 450: VectorCopy (forward, aim); ! 451: ! 452: monster_fire_grenade (self, start, aim, 50, 600, flash_number); ! 453: } ! 454: ! 455: mframe_t gunner_frames_attack_chain [] = ! 456: { ! 457: /* ! 458: ai_charge, 0, NULL, ! 459: ai_charge, 0, NULL, ! 460: ai_charge, 0, NULL, ! 461: ai_charge, 0, NULL, ! 462: ai_charge, 0, NULL, ! 463: ai_charge, 0, NULL, ! 464: ai_charge, 0, NULL, ! 465: ai_charge, 0, NULL, ! 466: */ ! 467: ai_charge, 0, gunner_opengun, ! 468: ai_charge, 0, NULL, ! 469: ai_charge, 0, NULL, ! 470: ai_charge, 0, NULL, ! 471: ai_charge, 0, NULL, ! 472: ai_charge, 0, NULL, ! 473: ai_charge, 0, NULL ! 474: }; ! 475: mmove_t gunner_move_attack_chain = {FRAME_attak209, FRAME_attak215, gunner_frames_attack_chain, gunner_fire_chain}; ! 476: ! 477: mframe_t gunner_frames_fire_chain [] = ! 478: { ! 479: ai_charge, 0, GunnerFire, ! 480: ai_charge, 0, GunnerFire, ! 481: ai_charge, 0, GunnerFire, ! 482: ai_charge, 0, GunnerFire, ! 483: ai_charge, 0, GunnerFire, ! 484: ai_charge, 0, GunnerFire, ! 485: ai_charge, 0, GunnerFire, ! 486: ai_charge, 0, GunnerFire ! 487: }; ! 488: mmove_t gunner_move_fire_chain = {FRAME_attak216, FRAME_attak223, gunner_frames_fire_chain, gunner_refire_chain}; ! 489: ! 490: mframe_t gunner_frames_endfire_chain [] = ! 491: { ! 492: ai_charge, 0, NULL, ! 493: ai_charge, 0, NULL, ! 494: ai_charge, 0, NULL, ! 495: ai_charge, 0, NULL, ! 496: ai_charge, 0, NULL, ! 497: ai_charge, 0, NULL, ! 498: ai_charge, 0, NULL ! 499: }; ! 500: mmove_t gunner_move_endfire_chain = {FRAME_attak224, FRAME_attak230, gunner_frames_endfire_chain, gunner_run}; ! 501: ! 502: mframe_t gunner_frames_attack_grenade [] = ! 503: { ! 504: ai_charge, 0, NULL, ! 505: ai_charge, 0, NULL, ! 506: ai_charge, 0, NULL, ! 507: ai_charge, 0, NULL, ! 508: ai_charge, 0, GunnerGrenade, ! 509: ai_charge, 0, NULL, ! 510: ai_charge, 0, NULL, ! 511: ai_charge, 0, GunnerGrenade, ! 512: ai_charge, 0, NULL, ! 513: ai_charge, 0, NULL, ! 514: ai_charge, 0, GunnerGrenade, ! 515: ai_charge, 0, NULL, ! 516: ai_charge, 0, NULL, ! 517: ai_charge, 0, GunnerGrenade, ! 518: ai_charge, 0, NULL, ! 519: ai_charge, 0, NULL, ! 520: ai_charge, 0, NULL, ! 521: ai_charge, 0, NULL, ! 522: ai_charge, 0, NULL, ! 523: ai_charge, 0, NULL, ! 524: ai_charge, 0, NULL ! 525: }; ! 526: mmove_t gunner_move_attack_grenade = {FRAME_attak101, FRAME_attak121, gunner_frames_attack_grenade, gunner_run}; ! 527: ! 528: void gunner_attack(edict_t *self) ! 529: { ! 530: if (range (self, self->enemy) == RANGE_MELEE) ! 531: { ! 532: self->monsterinfo.currentmove = &gunner_move_attack_chain; ! 533: } ! 534: else ! 535: { ! 536: if (random() <= 0.5) ! 537: self->monsterinfo.currentmove = &gunner_move_attack_grenade; ! 538: else ! 539: self->monsterinfo.currentmove = &gunner_move_attack_chain; ! 540: } ! 541: } ! 542: ! 543: void gunner_fire_chain(edict_t *self) ! 544: { ! 545: self->monsterinfo.currentmove = &gunner_move_fire_chain; ! 546: } ! 547: ! 548: void gunner_refire_chain(edict_t *self) ! 549: { ! 550: if (self->enemy->health > 0) ! 551: if ( visible (self, self->enemy) ) ! 552: if (random() <= 0.5) ! 553: { ! 554: self->monsterinfo.currentmove = &gunner_move_fire_chain; ! 555: return; ! 556: } ! 557: self->monsterinfo.currentmove = &gunner_move_endfire_chain; ! 558: } ! 559: ! 560: /*QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight ! 561: */ ! 562: void SP_monster_gunner (edict_t *self) ! 563: { ! 564: if (deathmatch->value) ! 565: { ! 566: G_FreeEdict (self); ! 567: return; ! 568: } ! 569: ! 570: sound_death = gi.soundindex ("gunner/death1.wav"); ! 571: sound_pain = gi.soundindex ("gunner/gunpain2.wav"); ! 572: sound_pain2 = gi.soundindex ("gunner/gunpain1.wav"); ! 573: sound_idle = gi.soundindex ("gunner/gunidle1.wav"); ! 574: sound_open = gi.soundindex ("gunner/gunatck1.wav"); ! 575: sound_search = gi.soundindex ("gunner/gunsrch1.wav"); ! 576: sound_sight = gi.soundindex ("gunner/sight1.wav"); ! 577: ! 578: gi.soundindex ("gunner/gunatck2.wav"); ! 579: gi.soundindex ("gunner/gunatck3.wav"); ! 580: ! 581: self->movetype = MOVETYPE_STEP; ! 582: self->solid = SOLID_BBOX; ! 583: self->s.modelindex = gi.modelindex ("models/monsters/gunner/tris.md2"); ! 584: VectorSet (self->mins, -16, -16, -24); ! 585: VectorSet (self->maxs, 16, 16, 32); ! 586: ! 587: self->health = 175; ! 588: self->gib_health = -70; ! 589: self->mass = 200; ! 590: ! 591: self->pain = gunner_pain; ! 592: self->die = gunner_die; ! 593: ! 594: self->monsterinfo.stand = gunner_stand; ! 595: self->monsterinfo.walk = gunner_walk; ! 596: self->monsterinfo.run = gunner_run; ! 597: self->monsterinfo.dodge = gunner_dodge; ! 598: self->monsterinfo.attack = gunner_attack; ! 599: self->monsterinfo.melee = NULL; ! 600: self->monsterinfo.sight = gunner_sight; ! 601: self->monsterinfo.search = gunner_search; ! 602: ! 603: gi.linkentity (self); ! 604: ! 605: self->monsterinfo.currentmove = &gunner_move_stand; ! 606: self->monsterinfo.scale = MODEL_SCALE; ! 607: ! 608: walkmonster_start (self); ! 609: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.