|
|
1.1 ! root 1: /* ! 2: ============================================================================== ! 3: ! 4: chick ! 5: ! 6: ============================================================================== ! 7: */ ! 8: ! 9: #include "g_local.h" ! 10: #include "m_chick.h" ! 11: ! 12: // ROGUE ! 13: #define LEAD_TARGET 1 ! 14: // ROGUE ! 15: ! 16: qboolean visible (edict_t *self, edict_t *other); ! 17: ! 18: void chick_stand (edict_t *self); ! 19: void chick_run (edict_t *self); ! 20: void chick_reslash(edict_t *self); ! 21: void chick_rerocket(edict_t *self); ! 22: void chick_attack1(edict_t *self); ! 23: ! 24: static int sound_missile_prelaunch; ! 25: static int sound_missile_launch; ! 26: static int sound_melee_swing; ! 27: static int sound_melee_hit; ! 28: static int sound_missile_reload; ! 29: static int sound_death1; ! 30: static int sound_death2; ! 31: static int sound_fall_down; ! 32: static int sound_idle1; ! 33: static int sound_idle2; ! 34: static int sound_pain1; ! 35: static int sound_pain2; ! 36: static int sound_pain3; ! 37: static int sound_sight; ! 38: static int sound_search; ! 39: ! 40: void ChickMoan (edict_t *self) ! 41: { ! 42: if (random() < 0.5) ! 43: gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); ! 44: else ! 45: gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0); ! 46: } ! 47: ! 48: mframe_t chick_frames_fidget [] = ! 49: { ! 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, NULL, ! 57: ai_stand, 0, NULL, ! 58: ai_stand, 0, ChickMoan, ! 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: 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: 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: mmove_t chick_move_fidget = {FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand}; ! 82: ! 83: void chick_fidget (edict_t *self) ! 84: { ! 85: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 86: return; ! 87: if (random() <= 0.3) ! 88: self->monsterinfo.currentmove = &chick_move_fidget; ! 89: } ! 90: ! 91: mframe_t chick_frames_stand [] = ! 92: { ! 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: ai_stand, 0, NULL, ! 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, chick_fidget, ! 123: ! 124: }; ! 125: mmove_t chick_move_stand = {FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL}; ! 126: ! 127: void chick_stand (edict_t *self) ! 128: { ! 129: self->monsterinfo.currentmove = &chick_move_stand; ! 130: } ! 131: ! 132: mframe_t chick_frames_start_run [] = ! 133: { ! 134: ai_run, 1, NULL, ! 135: ai_run, 0, NULL, ! 136: ai_run, 0, NULL, ! 137: ai_run, -1, NULL, ! 138: ai_run, -1, NULL, ! 139: ai_run, 0, NULL, ! 140: ai_run, 1, NULL, ! 141: ai_run, 3, NULL, ! 142: ai_run, 6, NULL, ! 143: ai_run, 3, NULL ! 144: }; ! 145: mmove_t chick_move_start_run = {FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run}; ! 146: ! 147: mframe_t chick_frames_run [] = ! 148: { ! 149: ai_run, 6, NULL, ! 150: ai_run, 8, NULL, ! 151: ai_run, 13, NULL, ! 152: ai_run, 5, monster_done_dodge, // make sure to clear dodge bit ! 153: ai_run, 7, NULL, ! 154: ai_run, 4, NULL, ! 155: ai_run, 11, NULL, ! 156: ai_run, 5, NULL, ! 157: ai_run, 9, NULL, ! 158: ai_run, 7, NULL ! 159: }; ! 160: ! 161: mmove_t chick_move_run = {FRAME_walk11, FRAME_walk20, chick_frames_run, NULL}; ! 162: ! 163: mframe_t chick_frames_walk [] = ! 164: { ! 165: ai_walk, 6, NULL, ! 166: ai_walk, 8, NULL, ! 167: ai_walk, 13, NULL, ! 168: ai_walk, 5, NULL, ! 169: ai_walk, 7, NULL, ! 170: ai_walk, 4, NULL, ! 171: ai_walk, 11, NULL, ! 172: ai_walk, 5, NULL, ! 173: ai_walk, 9, NULL, ! 174: ai_walk, 7, NULL ! 175: }; ! 176: ! 177: mmove_t chick_move_walk = {FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL}; ! 178: ! 179: void chick_walk (edict_t *self) ! 180: { ! 181: self->monsterinfo.currentmove = &chick_move_walk; ! 182: } ! 183: ! 184: void chick_run (edict_t *self) ! 185: { ! 186: monster_done_dodge (self); ! 187: ! 188: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 189: { ! 190: self->monsterinfo.currentmove = &chick_move_stand; ! 191: return; ! 192: } ! 193: ! 194: if (self->monsterinfo.currentmove == &chick_move_walk || ! 195: self->monsterinfo.currentmove == &chick_move_start_run) ! 196: { ! 197: self->monsterinfo.currentmove = &chick_move_run; ! 198: } ! 199: else ! 200: { ! 201: self->monsterinfo.currentmove = &chick_move_start_run; ! 202: } ! 203: } ! 204: ! 205: mframe_t chick_frames_pain1 [] = ! 206: { ! 207: ai_move, 0, NULL, ! 208: ai_move, 0, NULL, ! 209: ai_move, 0, NULL, ! 210: ai_move, 0, NULL, ! 211: ai_move, 0, NULL ! 212: }; ! 213: mmove_t chick_move_pain1 = {FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run}; ! 214: ! 215: mframe_t chick_frames_pain2 [] = ! 216: { ! 217: ai_move, 0, NULL, ! 218: ai_move, 0, NULL, ! 219: ai_move, 0, NULL, ! 220: ai_move, 0, NULL, ! 221: ai_move, 0, NULL ! 222: }; ! 223: mmove_t chick_move_pain2 = {FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run}; ! 224: ! 225: mframe_t chick_frames_pain3 [] = ! 226: { ! 227: ai_move, 0, NULL, ! 228: ai_move, 0, NULL, ! 229: ai_move, -6, NULL, ! 230: ai_move, 3, NULL, ! 231: ai_move, 11, NULL, ! 232: ai_move, 3, NULL, ! 233: ai_move, 0, NULL, ! 234: ai_move, 0, NULL, ! 235: ai_move, 4, NULL, ! 236: ai_move, 1, NULL, ! 237: ai_move, 0, NULL, ! 238: ai_move, -3, NULL, ! 239: ai_move, -4, NULL, ! 240: ai_move, 5, NULL, ! 241: ai_move, 7, NULL, ! 242: ai_move, -2, NULL, ! 243: ai_move, 3, NULL, ! 244: ai_move, -5, NULL, ! 245: ai_move, -2, NULL, ! 246: ai_move, -8, NULL, ! 247: ai_move, 2, NULL ! 248: }; ! 249: mmove_t chick_move_pain3 = {FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run}; ! 250: ! 251: void chick_pain (edict_t *self, edict_t *other, float kick, int damage) ! 252: { ! 253: float r; ! 254: ! 255: monster_done_dodge(self); ! 256: ! 257: if (self->health < (self->max_health / 2)) ! 258: self->s.skinnum = 1; ! 259: ! 260: if (level.time < self->pain_debounce_time) ! 261: return; ! 262: ! 263: self->pain_debounce_time = level.time + 3; ! 264: ! 265: r = random(); ! 266: if (r < 0.33) ! 267: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); ! 268: else if (r < 0.66) ! 269: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); ! 270: else ! 271: gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); ! 272: ! 273: if (skill->value == 3) ! 274: return; // no pain anims in nightmare ! 275: ! 276: // PMM - clear this from blindfire ! 277: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; ! 278: ! 279: if (damage <= 10) ! 280: self->monsterinfo.currentmove = &chick_move_pain1; ! 281: else if (damage <= 25) ! 282: self->monsterinfo.currentmove = &chick_move_pain2; ! 283: else ! 284: self->monsterinfo.currentmove = &chick_move_pain3; ! 285: ! 286: // PMM - clear duck flag ! 287: if (self->monsterinfo.aiflags & AI_DUCKED) ! 288: monster_duck_up(self); ! 289: } ! 290: ! 291: void chick_dead (edict_t *self) ! 292: { ! 293: VectorSet (self->mins, -16, -16, 0); ! 294: VectorSet (self->maxs, 16, 16, 16); ! 295: self->movetype = MOVETYPE_TOSS; ! 296: self->svflags |= SVF_DEADMONSTER; ! 297: self->nextthink = 0; ! 298: gi.linkentity (self); ! 299: } ! 300: ! 301: mframe_t chick_frames_death2 [] = ! 302: { ! 303: ai_move, -6, NULL, ! 304: ai_move, 0, NULL, ! 305: ai_move, -1, NULL, ! 306: ai_move, -5, NULL, ! 307: ai_move, 0, NULL, ! 308: ai_move, -1, NULL, ! 309: ai_move, -2, NULL, ! 310: ai_move, 1, NULL, ! 311: ai_move, 10, NULL, ! 312: ai_move, 2, NULL, ! 313: ai_move, 3, NULL, ! 314: ai_move, 1, NULL, ! 315: ai_move, 2, NULL, ! 316: ai_move, 0, NULL, ! 317: ai_move, 3, NULL, ! 318: ai_move, 3, NULL, ! 319: ai_move, 1, NULL, ! 320: ai_move, -3, NULL, ! 321: ai_move, -5, NULL, ! 322: ai_move, 4, NULL, ! 323: ai_move, 15, NULL, ! 324: ai_move, 14, NULL, ! 325: ai_move, 1, NULL ! 326: }; ! 327: mmove_t chick_move_death2 = {FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead}; ! 328: ! 329: mframe_t chick_frames_death1 [] = ! 330: { ! 331: ai_move, 0, NULL, ! 332: ai_move, 0, NULL, ! 333: ai_move, -7, NULL, ! 334: ai_move, 4, NULL, ! 335: ai_move, 11, NULL, ! 336: ai_move, 0, NULL, ! 337: ai_move, 0, NULL, ! 338: ai_move, 0, NULL, ! 339: ai_move, 0, NULL, ! 340: ai_move, 0, NULL, ! 341: ai_move, 0, NULL, ! 342: ai_move, 0, NULL ! 343: ! 344: }; ! 345: mmove_t chick_move_death1 = {FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead}; ! 346: ! 347: void chick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) ! 348: { ! 349: int n; ! 350: ! 351: // check for gib ! 352: if (self->health <= self->gib_health) ! 353: { ! 354: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 355: for (n= 0; n < 2; n++) ! 356: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); ! 357: for (n= 0; n < 4; n++) ! 358: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ! 359: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); ! 360: self->deadflag = DEAD_DEAD; ! 361: return; ! 362: } ! 363: ! 364: if (self->deadflag == DEAD_DEAD) ! 365: return; ! 366: ! 367: // regular death ! 368: self->deadflag = DEAD_DEAD; ! 369: self->takedamage = DAMAGE_YES; ! 370: ! 371: n = rand() % 2; ! 372: if (n == 0) ! 373: { ! 374: self->monsterinfo.currentmove = &chick_move_death1; ! 375: gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); ! 376: } ! 377: else ! 378: { ! 379: self->monsterinfo.currentmove = &chick_move_death2; ! 380: gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); ! 381: } ! 382: } ! 383: ! 384: // PMM - changes to duck code for new dodge ! 385: ! 386: mframe_t chick_frames_duck [] = ! 387: { ! 388: ai_move, 0, monster_duck_down, ! 389: ai_move, 1, NULL, ! 390: ai_move, 4, monster_duck_hold, ! 391: ai_move, -4, NULL, ! 392: ai_move, -5, monster_duck_up, ! 393: ai_move, 3, NULL, ! 394: ai_move, 1, NULL ! 395: }; ! 396: mmove_t chick_move_duck = {FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run}; ! 397: ! 398: /* ! 399: void chick_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr) ! 400: { ! 401: // begin orig code ! 402: if (random() > 0.25) ! 403: return; ! 404: ! 405: if (!self->enemy) ! 406: self->enemy = attacker; ! 407: ! 408: self->monsterinfo.currentmove = &chick_move_duck; ! 409: // end ! 410: ! 411: float r; ! 412: float height; ! 413: int shooting = 0; ! 414: ! 415: if (!self->enemy) ! 416: { ! 417: self->enemy = attacker; ! 418: FoundTarget (self); ! 419: } ! 420: ! 421: // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was ! 422: // seeing numbers like 13 and 14) ! 423: if ((eta < 0.1) || (eta > 5)) ! 424: return; ! 425: ! 426: r = random(); ! 427: if (r > (0.25*((skill->value)+1))) ! 428: return; ! 429: ! 430: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) || ! 431: (self->monsterinfo.currentmove == &chick_move_attack1)) ! 432: { ! 433: shooting = 1; ! 434: } ! 435: if (self->monsterinfo.aiflags & AI_DODGING) ! 436: { ! 437: height = self->absmax[2]; ! 438: } ! 439: else ! 440: { ! 441: height = self->absmax[2]-32-1; // the -1 is because the absmax is s.origin + maxs + 1 ! 442: } ! 443: ! 444: // check to see if it makes sense to duck ! 445: if (tr->endpos[2] <= height) ! 446: { ! 447: vec3_t right, diff; ! 448: if (shooting) ! 449: { ! 450: self->monsterinfo.attack_state = AS_SLIDING; ! 451: return; ! 452: } ! 453: AngleVectors (self->s.angles, NULL, right, NULL); ! 454: VectorSubtract (tr->endpos, self->s.origin, diff); ! 455: if (DotProduct (right, diff) < 0) ! 456: { ! 457: self->monsterinfo.lefty = 1; ! 458: } ! 459: // if it doesn't sense to duck, try to strafe away ! 460: monster_done_dodge (self); ! 461: self->monsterinfo.currentmove = &chick_move_run; ! 462: self->monsterinfo.attack_state = AS_SLIDING; ! 463: return; ! 464: } ! 465: ! 466: if (skill->value == 0) ! 467: { ! 468: self->monsterinfo.currentmove = &chick_move_duck; ! 469: // PMM - stupid dodge ! 470: self->monsterinfo.duck_wait_time = level.time + eta + 1; ! 471: self->monsterinfo.aiflags |= AI_DODGING; ! 472: return; ! 473: } ! 474: ! 475: if (!shooting) ! 476: { ! 477: self->monsterinfo.currentmove = &chick_move_duck; ! 478: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); ! 479: self->monsterinfo.aiflags |= AI_DODGING; ! 480: } ! 481: return; ! 482: ! 483: } ! 484: */ ! 485: void ChickSlash (edict_t *self) ! 486: { ! 487: vec3_t aim; ! 488: ! 489: VectorSet (aim, MELEE_DISTANCE, self->mins[0], 10); ! 490: gi.sound (self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0); ! 491: fire_hit (self, aim, (10 + (rand() %6)), 100); ! 492: } ! 493: ! 494: ! 495: void ChickRocket (edict_t *self) ! 496: { ! 497: vec3_t forward, right; ! 498: vec3_t start; ! 499: vec3_t dir; ! 500: vec3_t vec; ! 501: trace_t trace; // PMM - check target ! 502: int rocketSpeed; ! 503: float dist; ! 504: // pmm - blindfire ! 505: vec3_t target; ! 506: qboolean blindfire = false; ! 507: ! 508: if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) ! 509: blindfire = true; ! 510: else ! 511: blindfire = false; ! 512: ! 513: if(!self->enemy || !self->enemy->inuse) //PGM ! 514: return; //PGM ! 515: ! 516: AngleVectors (self->s.angles, forward, right, NULL); ! 517: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start); ! 518: ! 519: rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :) ! 520: ! 521: // put a debug trail from start to endpoint, confirm that the start point is ! 522: // correct for the trace ! 523: ! 524: // PMM ! 525: if (blindfire) ! 526: VectorCopy (self->monsterinfo.blind_fire_target, target); ! 527: else ! 528: VectorCopy (self->enemy->s.origin, target); ! 529: // pmm ! 530: //PGM ! 531: // PMM - blindfire shooting ! 532: if (blindfire) ! 533: { ! 534: VectorCopy (target, vec); ! 535: VectorSubtract (vec, start, dir); ! 536: } ! 537: // pmm ! 538: // don't shoot at feet if they're above where i'm shooting from. ! 539: else if(random() < 0.33 || (start[2] < self->enemy->absmin[2])) ! 540: { ! 541: // gi.dprintf("normal shot\n"); ! 542: VectorCopy (target, vec); ! 543: vec[2] += self->enemy->viewheight; ! 544: VectorSubtract (vec, start, dir); ! 545: } ! 546: else ! 547: { ! 548: // gi.dprintf("shooting at feet!\n"); ! 549: VectorCopy (target, vec); ! 550: vec[2] = self->enemy->absmin[2]; ! 551: VectorSubtract (vec, start, dir); ! 552: } ! 553: //PGM ! 554: ! 555: //====== ! 556: //PMM - lead target (not when blindfiring) ! 557: // 20, 35, 50, 65 chance of leading ! 558: if((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15))))) ! 559: { ! 560: float time; ! 561: ! 562: // gi.dprintf ("leading target\n"); ! 563: dist = VectorLength (dir); ! 564: time = dist/rocketSpeed; ! 565: VectorMA(vec, time, self->enemy->velocity, vec); ! 566: VectorSubtract(vec, start, dir); ! 567: } ! 568: //PMM - lead target ! 569: //====== ! 570: ! 571: VectorNormalize (dir); ! 572: ! 573: // pmm blindfire doesn't check target (done in checkattack) ! 574: // paranoia, make sure we're not shooting a target right next to us ! 575: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); ! 576: if (blindfire) ! 577: { ! 578: // blindfire has different fail criteria for the trace ! 579: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5))) ! 580: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1); ! 581: else ! 582: { ! 583: // geez, this is bad. she's avoiding about 80% of her blindfires due to hitting things. ! 584: // hunt around for a good shot ! 585: // try shifting the target to the left a little (to help counter her large offset) ! 586: VectorCopy (target, vec); ! 587: VectorMA (vec, -10, right, vec); ! 588: VectorSubtract(vec, start, dir); ! 589: VectorNormalize (dir); ! 590: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); ! 591: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5))) ! 592: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1); ! 593: else ! 594: { ! 595: // ok, that failed. try to the right ! 596: VectorCopy (target, vec); ! 597: VectorMA (vec, 10, right, vec); ! 598: VectorSubtract(vec, start, dir); ! 599: VectorNormalize (dir); ! 600: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); ! 601: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5))) ! 602: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1); ! 603: else if ((g_showlogic) && (g_showlogic->value)) ! 604: // ok, I give up ! 605: gi.dprintf ("chick avoiding blindfire shot\n"); ! 606: } ! 607: } ! 608: } ! 609: else ! 610: { ! 611: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT); ! 612: if(trace.ent == self->enemy || trace.ent == world) ! 613: { ! 614: if(trace.fraction > 0.5 || (trace.ent && trace.ent->client)) ! 615: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1); ! 616: // else ! 617: // gi.dprintf("didn't make it halfway to target...aborting\n"); ! 618: } ! 619: } ! 620: } ! 621: ! 622: void Chick_PreAttack1 (edict_t *self) ! 623: { ! 624: gi.sound (self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0); ! 625: } ! 626: ! 627: void ChickReload (edict_t *self) ! 628: { ! 629: gi.sound (self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0); ! 630: } ! 631: ! 632: ! 633: mframe_t chick_frames_start_attack1 [] = ! 634: { ! 635: ai_charge, 0, Chick_PreAttack1, ! 636: ai_charge, 0, NULL, ! 637: ai_charge, 0, NULL, ! 638: ai_charge, 4, NULL, ! 639: ai_charge, 0, NULL, ! 640: ai_charge, -3, NULL, ! 641: ai_charge, 3, NULL, ! 642: ai_charge, 5, NULL, ! 643: ai_charge, 7, NULL, ! 644: ai_charge, 0, NULL, ! 645: ai_charge, 0, NULL, ! 646: ai_charge, 0, NULL, ! 647: ai_charge, 0, chick_attack1 ! 648: }; ! 649: mmove_t chick_move_start_attack1 = {FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL}; ! 650: ! 651: ! 652: mframe_t chick_frames_attack1 [] = ! 653: { ! 654: ai_charge, 19, ChickRocket, ! 655: ai_charge, -6, NULL, ! 656: ai_charge, -5, NULL, ! 657: ai_charge, -2, NULL, ! 658: ai_charge, -7, NULL, ! 659: ai_charge, 0, NULL, ! 660: ai_charge, 1, NULL, ! 661: ai_charge, 10, ChickReload, ! 662: ai_charge, 4, NULL, ! 663: ai_charge, 5, NULL, ! 664: ai_charge, 6, NULL, ! 665: ai_charge, 6, NULL, ! 666: ai_charge, 4, NULL, ! 667: ai_charge, 3, chick_rerocket ! 668: ! 669: }; ! 670: mmove_t chick_move_attack1 = {FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL}; ! 671: ! 672: mframe_t chick_frames_end_attack1 [] = ! 673: { ! 674: ai_charge, -3, NULL, ! 675: ai_charge, 0, NULL, ! 676: ai_charge, -6, NULL, ! 677: ai_charge, -4, NULL, ! 678: ai_charge, -2, NULL ! 679: }; ! 680: mmove_t chick_move_end_attack1 = {FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run}; ! 681: ! 682: void chick_rerocket(edict_t *self) ! 683: { ! 684: if (self->monsterinfo.aiflags & AI_MANUAL_STEERING) ! 685: { ! 686: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING; ! 687: self->monsterinfo.currentmove = &chick_move_end_attack1; ! 688: return; ! 689: } ! 690: if (self->enemy->health > 0) ! 691: { ! 692: if (range (self, self->enemy) > RANGE_MELEE) ! 693: if ( visible (self, self->enemy) ) ! 694: if (random() <= (0.6 + (0.05*((float)skill->value)))) ! 695: { ! 696: self->monsterinfo.currentmove = &chick_move_attack1; ! 697: return; ! 698: } ! 699: } ! 700: self->monsterinfo.currentmove = &chick_move_end_attack1; ! 701: } ! 702: ! 703: void chick_attack1(edict_t *self) ! 704: { ! 705: self->monsterinfo.currentmove = &chick_move_attack1; ! 706: } ! 707: ! 708: mframe_t chick_frames_slash [] = ! 709: { ! 710: ai_charge, 1, NULL, ! 711: ai_charge, 7, ChickSlash, ! 712: ai_charge, -7, NULL, ! 713: ai_charge, 1, NULL, ! 714: ai_charge, -1, NULL, ! 715: ai_charge, 1, NULL, ! 716: ai_charge, 0, NULL, ! 717: ai_charge, 1, NULL, ! 718: ai_charge, -2, chick_reslash ! 719: }; ! 720: mmove_t chick_move_slash = {FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL}; ! 721: ! 722: mframe_t chick_frames_end_slash [] = ! 723: { ! 724: ai_charge, -6, NULL, ! 725: ai_charge, -1, NULL, ! 726: ai_charge, -6, NULL, ! 727: ai_charge, 0, NULL ! 728: }; ! 729: mmove_t chick_move_end_slash = {FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run}; ! 730: ! 731: ! 732: void chick_reslash(edict_t *self) ! 733: { ! 734: if (self->enemy->health > 0) ! 735: { ! 736: if (range (self, self->enemy) == RANGE_MELEE) ! 737: if (random() <= 0.9) ! 738: { ! 739: self->monsterinfo.currentmove = &chick_move_slash; ! 740: return; ! 741: } ! 742: else ! 743: { ! 744: self->monsterinfo.currentmove = &chick_move_end_slash; ! 745: return; ! 746: } ! 747: } ! 748: self->monsterinfo.currentmove = &chick_move_end_slash; ! 749: } ! 750: ! 751: void chick_slash(edict_t *self) ! 752: { ! 753: self->monsterinfo.currentmove = &chick_move_slash; ! 754: } ! 755: ! 756: ! 757: mframe_t chick_frames_start_slash [] = ! 758: { ! 759: ai_charge, 1, NULL, ! 760: ai_charge, 8, NULL, ! 761: ai_charge, 3, NULL ! 762: }; ! 763: mmove_t chick_move_start_slash = {FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash}; ! 764: ! 765: ! 766: ! 767: void chick_melee(edict_t *self) ! 768: { ! 769: self->monsterinfo.currentmove = &chick_move_start_slash; ! 770: } ! 771: ! 772: ! 773: void chick_attack(edict_t *self) ! 774: { ! 775: float r, chance; ! 776: ! 777: monster_done_dodge (self); ! 778: ! 779: // PMM ! 780: if (self->monsterinfo.attack_state == AS_BLIND) ! 781: { ! 782: // setup shot probabilities ! 783: if (self->monsterinfo.blind_fire_delay < 1.0) ! 784: chance = 1.0; ! 785: else if (self->monsterinfo.blind_fire_delay < 7.5) ! 786: chance = 0.4; ! 787: else ! 788: chance = 0.1; ! 789: ! 790: r = random(); ! 791: ! 792: gi.dprintf ("chance = %2.2f, roll = %2.2f\n", chance, r); ! 793: ! 794: // minimum of 2 seconds, plus 0-3, after the shots are done ! 795: self->monsterinfo.blind_fire_delay += 4.0 + 1.5 + random(); ! 796: ! 797: // don't shoot at the origin ! 798: if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin)) ! 799: return; ! 800: ! 801: // don't shoot if the dice say not to ! 802: if (r > chance) ! 803: { ! 804: if ((g_showlogic) && (g_showlogic->value)) ! 805: gi.dprintf ("blindfire - NO SHOT\n"); ! 806: return; ! 807: } ! 808: ! 809: // turn on manual steering to signal both manual steering and blindfire ! 810: self->monsterinfo.aiflags |= AI_MANUAL_STEERING; ! 811: self->monsterinfo.currentmove = &chick_move_start_attack1; ! 812: self->monsterinfo.attack_finished = level.time + 2*random(); ! 813: return; ! 814: } ! 815: // pmm ! 816: ! 817: self->monsterinfo.currentmove = &chick_move_start_attack1; ! 818: } ! 819: ! 820: void chick_sight(edict_t *self, edict_t *other) ! 821: { ! 822: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); ! 823: } ! 824: ! 825: //=========== ! 826: //PGM ! 827: qboolean chick_blocked (edict_t *self, float dist) ! 828: { ! 829: if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) )) ! 830: return true; ! 831: ! 832: if(blocked_checkplat (self, dist)) ! 833: return true; ! 834: ! 835: return false; ! 836: } ! 837: //PGM ! 838: //=========== ! 839: ! 840: void chick_duck (edict_t *self, float eta) ! 841: { ! 842: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) || ! 843: (self->monsterinfo.currentmove == &chick_move_attack1)) ! 844: { ! 845: // if we're shooting, and not on easy, don't dodge ! 846: if (skill->value) ! 847: { ! 848: self->monsterinfo.aiflags &= ~AI_DUCKED; ! 849: return; ! 850: } ! 851: } ! 852: ! 853: if (skill->value == 0) ! 854: // PMM - stupid dodge ! 855: self->monsterinfo.duck_wait_time = level.time + eta + 1; ! 856: else ! 857: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value)); ! 858: ! 859: // has to be done immediately otherwise she can get stuck ! 860: monster_duck_down(self); ! 861: ! 862: self->monsterinfo.nextframe = FRAME_duck01; ! 863: self->monsterinfo.currentmove = &chick_move_duck; ! 864: return; ! 865: } ! 866: ! 867: void chick_sidestep (edict_t *self) ! 868: { ! 869: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) || ! 870: (self->monsterinfo.currentmove == &chick_move_attack1)) ! 871: { ! 872: // if we're shooting, and not on easy, don't dodge ! 873: if (skill->value) ! 874: { ! 875: self->monsterinfo.aiflags &= ~AI_DODGING; ! 876: return; ! 877: } ! 878: } ! 879: ! 880: if (self->monsterinfo.currentmove != &chick_move_run) ! 881: self->monsterinfo.currentmove = &chick_move_run; ! 882: } ! 883: ! 884: /*QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight ! 885: */ ! 886: void SP_monster_chick (edict_t *self) ! 887: { ! 888: if (deathmatch->value) ! 889: { ! 890: G_FreeEdict (self); ! 891: return; ! 892: } ! 893: ! 894: sound_missile_prelaunch = gi.soundindex ("chick/chkatck1.wav"); ! 895: sound_missile_launch = gi.soundindex ("chick/chkatck2.wav"); ! 896: sound_melee_swing = gi.soundindex ("chick/chkatck3.wav"); ! 897: sound_melee_hit = gi.soundindex ("chick/chkatck4.wav"); ! 898: sound_missile_reload = gi.soundindex ("chick/chkatck5.wav"); ! 899: sound_death1 = gi.soundindex ("chick/chkdeth1.wav"); ! 900: sound_death2 = gi.soundindex ("chick/chkdeth2.wav"); ! 901: sound_fall_down = gi.soundindex ("chick/chkfall1.wav"); ! 902: sound_idle1 = gi.soundindex ("chick/chkidle1.wav"); ! 903: sound_idle2 = gi.soundindex ("chick/chkidle2.wav"); ! 904: sound_pain1 = gi.soundindex ("chick/chkpain1.wav"); ! 905: sound_pain2 = gi.soundindex ("chick/chkpain2.wav"); ! 906: sound_pain3 = gi.soundindex ("chick/chkpain3.wav"); ! 907: sound_sight = gi.soundindex ("chick/chksght1.wav"); ! 908: sound_search = gi.soundindex ("chick/chksrch1.wav"); ! 909: ! 910: self->movetype = MOVETYPE_STEP; ! 911: self->solid = SOLID_BBOX; ! 912: self->s.modelindex = gi.modelindex ("models/monsters/bitch2/tris.md2"); ! 913: VectorSet (self->mins, -16, -16, 0); ! 914: VectorSet (self->maxs, 16, 16, 56); ! 915: ! 916: self->health = 175; ! 917: self->gib_health = -70; ! 918: self->mass = 200; ! 919: ! 920: self->pain = chick_pain; ! 921: self->die = chick_die; ! 922: ! 923: self->monsterinfo.stand = chick_stand; ! 924: self->monsterinfo.walk = chick_walk; ! 925: self->monsterinfo.run = chick_run; ! 926: // pmm ! 927: self->monsterinfo.dodge = M_MonsterDodge; ! 928: self->monsterinfo.duck = chick_duck; ! 929: self->monsterinfo.unduck = monster_duck_up; ! 930: self->monsterinfo.sidestep = chick_sidestep; ! 931: // self->monsterinfo.dodge = chick_dodge; ! 932: // pmm ! 933: self->monsterinfo.attack = chick_attack; ! 934: self->monsterinfo.melee = chick_melee; ! 935: self->monsterinfo.sight = chick_sight; ! 936: self->monsterinfo.blocked = chick_blocked; // PGM ! 937: ! 938: gi.linkentity (self); ! 939: ! 940: self->monsterinfo.currentmove = &chick_move_stand; ! 941: self->monsterinfo.scale = MODEL_SCALE; ! 942: ! 943: // PMM ! 944: self->monsterinfo.blindfire = true; ! 945: // pmm ! 946: walkmonster_start (self); ! 947: } ! 948:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.