|
|
1.1 ! root 1: /* ! 2: xatrix ! 3: gekk.c ! 4: */ ! 5: ! 6: #include "g_local.h" ! 7: #include "m_gekk.h" ! 8: ! 9: static int sound_swing; ! 10: static int sound_hit; ! 11: static int sound_hit2; ! 12: static int sound_death; ! 13: static int sound_pain1; ! 14: static int sound_sight; ! 15: static int sound_search; ! 16: static int sound_step1; ! 17: static int sound_step2; ! 18: static int sound_step3; ! 19: static int sound_thud; ! 20: static int sound_chantlow; ! 21: static int sound_chantmid; ! 22: static int sound_chanthigh; ! 23: ! 24: void gekk_swim (edict_t *self); ! 25: ! 26: extern void gekk_jump_takeoff (edict_t *self); ! 27: extern void gekk_jump_takeoff2 (edict_t *self); ! 28: extern void gekk_check_landing (edict_t *self); ! 29: extern void gekk_check_landing2 (edict_t *self); ! 30: extern void gekk_stop_skid (edict_t *self); ! 31: ! 32: extern void water_to_land (edict_t *self); ! 33: extern void land_to_water (edict_t *self); ! 34: ! 35: extern void gekk_check_underwater (edict_t *self); ! 36: extern void gekk_bite (edict_t *self); ! 37: ! 38: extern void gekk_hit_left (edict_t *self); ! 39: extern void gekk_hit_right (edict_t *self); ! 40: extern void gekk_run_start (edict_t *self); ! 41: ! 42: extern mmove_t gekk_move_attack1; ! 43: extern mmove_t gekk_move_attack2; ! 44: extern mmove_t gekk_move_chant; ! 45: extern mmove_t gekk_move_swim_start; ! 46: extern mmove_t gekk_move_swim_loop; ! 47: extern mmove_t gekk_move_spit; ! 48: extern mmove_t gekk_move_run_start; ! 49: ! 50: extern qboolean gekk_check_jump (edict_t *self); ! 51: ! 52: // ! 53: // CHECKATTACK ! 54: // ! 55: ! 56: qboolean gekk_check_melee (edict_t *self) ! 57: { ! 58: if (!self->enemy && self->enemy->health <= 0) ! 59: return false; ! 60: ! 61: if (range (self, self->enemy) == RANGE_MELEE) ! 62: return true; ! 63: return false; ! 64: } ! 65: ! 66: qboolean gekk_check_jump (edict_t *self) ! 67: { ! 68: vec3_t v; ! 69: float distance; ! 70: ! 71: if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2])) ! 72: return false; ! 73: ! 74: if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2])) ! 75: return false; ! 76: ! 77: v[0] = self->s.origin[0] - self->enemy->s.origin[0]; ! 78: v[1] = self->s.origin[1] - self->enemy->s.origin[1]; ! 79: v[2] = 0; ! 80: distance = VectorLength(v); ! 81: ! 82: if (distance < 100) ! 83: { ! 84: return false; ! 85: } ! 86: if (distance > 100) ! 87: { ! 88: if (random() < 0.9) ! 89: return false; ! 90: } ! 91: ! 92: return true; ! 93: } ! 94: ! 95: qboolean gekk_check_jump_close (edict_t *self) ! 96: { ! 97: vec3_t v; ! 98: float distance; ! 99: ! 100: v[0] = self->s.origin[0] - self->enemy->s.origin[0]; ! 101: v[1] = self->s.origin[1] - self->enemy->s.origin[1]; ! 102: v[2] = 0; ! 103: ! 104: distance = VectorLength(v); ! 105: ! 106: if (distance < 100) ! 107: { ! 108: if (self->s.origin[2] < self->enemy->s.origin[2]) ! 109: return true; ! 110: else ! 111: return false; ! 112: } ! 113: ! 114: return true; ! 115: } ! 116: ! 117: ! 118: qboolean gekk_checkattack (edict_t *self) ! 119: { ! 120: if (!self->enemy || self->enemy->health <= 0) ! 121: return false; ! 122: ! 123: if (gekk_check_melee(self)) ! 124: { ! 125: self->monsterinfo.attack_state = AS_MELEE; ! 126: return true; ! 127: } ! 128: ! 129: if (gekk_check_jump(self)) ! 130: { ! 131: self->monsterinfo.attack_state = AS_MISSILE; ! 132: return true; ! 133: } ! 134: ! 135: if (gekk_check_jump_close (self) && !self->waterlevel) ! 136: { ! 137: self->monsterinfo.attack_state = AS_MISSILE; ! 138: return true; ! 139: } ! 140: ! 141: return false; ! 142: } ! 143: ! 144: ! 145: // ! 146: // SOUNDS ! 147: // ! 148: ! 149: void gekk_step (edict_t *self) ! 150: { ! 151: int n; ! 152: n = (rand() + 1) % 3; ! 153: if (n == 0) ! 154: gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0); ! 155: else if (n == 1) ! 156: gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0); ! 157: else ! 158: gi.sound (self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0); ! 159: } ! 160: ! 161: void gekk_sight (edict_t *self, edict_t *other) ! 162: { ! 163: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); ! 164: } ! 165: ! 166: void gekk_search (edict_t *self) ! 167: { ! 168: float r; ! 169: ! 170: if (self->spawnflags & 8) ! 171: { ! 172: r = random(); ! 173: if (r < 0.33) ! 174: gi.sound (self, CHAN_VOICE, sound_chantlow, 1, ATTN_NORM, 0); ! 175: else if (r < 0.66) ! 176: gi.sound (self, CHAN_VOICE, sound_chantmid, 1, ATTN_NORM, 0); ! 177: else ! 178: gi.sound (self, CHAN_VOICE, sound_chanthigh, 1, ATTN_NORM, 0); ! 179: } ! 180: else ! 181: gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); ! 182: ! 183: ! 184: self->health += 10 + (10 * random()); ! 185: if (self->health > self->max_health) ! 186: self->health = self->max_health; ! 187: ! 188: if (self->health < (self->max_health /4)) ! 189: self->s.skinnum = 2; ! 190: else if (self->health < (self->max_health / 2)) ! 191: self->s.skinnum = 1; ! 192: else ! 193: self->s.skinnum = 0; ! 194: } ! 195: ! 196: void gekk_swing (edict_t *self) ! 197: { ! 198: gi.sound (self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0); ! 199: } ! 200: ! 201: extern mmove_t gekk_move_run; ! 202: void gekk_face (edict_t *self) ! 203: { ! 204: self->monsterinfo.currentmove = &gekk_move_run; ! 205: } ! 206: ! 207: // ! 208: // STAND ! 209: // ! 210: ! 211: void ai_stand2 (edict_t *self, float dist) ! 212: { ! 213: if (self->spawnflags & 8) ! 214: { ! 215: ai_move (self, dist); ! 216: if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time)) ! 217: { ! 218: if (self->monsterinfo.idle_time) ! 219: { ! 220: self->monsterinfo.idle (self); ! 221: self->monsterinfo.idle_time = level.time + 15 + random() * 15; ! 222: } ! 223: else ! 224: { ! 225: self->monsterinfo.idle_time = level.time + random() * 15; ! 226: } ! 227: } ! 228: } ! 229: else ! 230: ai_stand (self, dist); ! 231: } ! 232: ! 233: mframe_t gekk_frames_stand [] = ! 234: { ! 235: ai_stand2, 0, NULL, ! 236: ai_stand2, 0, NULL, ! 237: ai_stand2, 0, NULL, ! 238: ai_stand2, 0, NULL, ! 239: ai_stand2, 0, NULL, ! 240: ai_stand2, 0, NULL, ! 241: ai_stand2, 0, NULL, ! 242: ai_stand2, 0, NULL, ! 243: ai_stand2, 0, NULL, ! 244: ai_stand2, 0, NULL, // 10 ! 245: ! 246: ai_stand2, 0, NULL, ! 247: ai_stand2, 0, NULL, ! 248: ai_stand2, 0, NULL, ! 249: ai_stand2, 0, NULL, ! 250: ai_stand2, 0, NULL, ! 251: ai_stand2, 0, NULL, ! 252: ai_stand2, 0, NULL, ! 253: ai_stand2, 0, NULL, ! 254: ai_stand2, 0, NULL, ! 255: ai_stand2, 0, NULL, // 20 ! 256: ! 257: ai_stand2, 0, NULL, ! 258: ai_stand2, 0, NULL, ! 259: ai_stand2, 0, NULL, ! 260: ai_stand2, 0, NULL, ! 261: ai_stand2, 0, NULL, ! 262: ai_stand2, 0, NULL, ! 263: ai_stand2, 0, NULL, ! 264: ai_stand2, 0, NULL, ! 265: ai_stand2, 0, NULL, ! 266: ai_stand2, 0, NULL, // 30 ! 267: ! 268: ai_stand2, 0, NULL, ! 269: ai_stand2, 0, NULL, ! 270: ai_stand2, 0, NULL, ! 271: ai_stand2, 0, NULL, ! 272: ai_stand2, 0, NULL, ! 273: ai_stand2, 0, NULL, ! 274: ai_stand2, 0, NULL, ! 275: ai_stand2, 0, NULL, ! 276: ! 277: ai_stand2, 0, gekk_check_underwater, ! 278: }; ! 279: mmove_t gekk_move_stand = {FRAME_stand_01, FRAME_stand_39, gekk_frames_stand, NULL}; ! 280: ! 281: mframe_t gekk_frames_standunderwater[] = ! 282: { ! 283: ai_stand2, 0, NULL, ! 284: ai_stand2, 0, NULL, ! 285: ai_stand2, 0, NULL, ! 286: ! 287: ai_stand2, 0, gekk_check_underwater ! 288: }; ! 289: ! 290: mmove_t gekk_move_standunderwater = {FRAME_amb_01, FRAME_amb_04, gekk_frames_standunderwater, NULL}; ! 291: ! 292: ! 293: void gekk_swim_loop (edict_t *self) ! 294: { ! 295: self->flags |= FL_SWIM; ! 296: self->monsterinfo.currentmove = &gekk_move_swim_loop; ! 297: } ! 298: ! 299: mframe_t gekk_frames_swim [] = ! 300: { ! 301: ai_run, 16, NULL, ! 302: ai_run, 16, NULL, ! 303: ai_run, 16, NULL, ! 304: ! 305: ai_run, 16, gekk_swim ! 306: }; ! 307: mmove_t gekk_move_swim_loop = {FRAME_amb_01, FRAME_amb_04, gekk_frames_swim, gekk_swim_loop}; ! 308: ! 309: mframe_t gekk_frames_swim_start [] = ! 310: { ! 311: ai_run, 14, NULL, ! 312: ai_run, 14, NULL, ! 313: ai_run, 14, NULL, ! 314: ai_run, 14, NULL, ! 315: ai_run, 16, NULL, ! 316: ai_run, 16, NULL, ! 317: ai_run, 16, NULL, ! 318: ai_run, 18, NULL, ! 319: ai_run, 18, gekk_hit_left, ! 320: ai_run, 18, NULL, ! 321: ! 322: ai_run, 20, NULL, ! 323: ai_run, 20, NULL, ! 324: ai_run, 22, NULL, ! 325: ai_run, 22, NULL, ! 326: ai_run, 24, gekk_hit_right, ! 327: ai_run, 24, NULL, ! 328: ai_run, 26, NULL, ! 329: ai_run, 26, NULL, ! 330: ai_run, 24, NULL, ! 331: ai_run, 24, NULL, ! 332: ! 333: ai_run, 22, gekk_bite, ! 334: ai_run, 22, NULL, ! 335: ai_run, 22, NULL, ! 336: ai_run, 22, NULL, ! 337: ai_run, 22, NULL, ! 338: ai_run, 22, NULL, ! 339: ai_run, 22, NULL, ! 340: ai_run, 22, NULL, ! 341: ai_run, 18, NULL, ! 342: ai_run, 18, NULL, ! 343: ! 344: ai_run, 18, NULL, ! 345: ai_run, 18, NULL ! 346: }; ! 347: mmove_t gekk_move_swim_start = {FRAME_swim_01, FRAME_swim_32, gekk_frames_swim_start, gekk_swim_loop}; ! 348: ! 349: void gekk_swim (edict_t *self) ! 350: { ! 351: ! 352: if (gekk_checkattack) ! 353: if (!self->enemy->waterlevel && random() > 0.7) ! 354: water_to_land (self); ! 355: else ! 356: self->monsterinfo.currentmove = &gekk_move_swim_start; ! 357: } ! 358: ! 359: ! 360: void gekk_stand (edict_t *self) ! 361: { ! 362: if (self->waterlevel) ! 363: self->monsterinfo.currentmove = &gekk_move_standunderwater; ! 364: else ! 365: self->monsterinfo.currentmove = &gekk_move_stand; ! 366: } ! 367: ! 368: void gekk_chant (edict_t *self) ! 369: { ! 370: self->monsterinfo.currentmove = &gekk_move_chant; ! 371: } ! 372: ! 373: // ! 374: // IDLE ! 375: // ! 376: ! 377: void gekk_idle_loop (edict_t *self) ! 378: { ! 379: if (random() > 0.75 && self->health < self->max_health) ! 380: self->monsterinfo.nextframe = FRAME_idle_01; ! 381: } ! 382: ! 383: mframe_t gekk_frames_idle [] = ! 384: { ! 385: ai_stand2, 0, gekk_search, ! 386: ai_stand2, 0, NULL, ! 387: ai_stand2, 0, NULL, ! 388: ai_stand2, 0, NULL, ! 389: ai_stand2, 0, NULL, ! 390: ai_stand2, 0, NULL, ! 391: ai_stand2, 0, NULL, ! 392: ai_stand2, 0, NULL, ! 393: ai_stand2, 0, NULL, ! 394: ai_stand2, 0, NULL, ! 395: ! 396: ai_stand2, 0, NULL, ! 397: ai_stand2, 0, NULL, ! 398: ai_stand2, 0, NULL, ! 399: ai_stand2, 0, NULL, ! 400: ai_stand2, 0, NULL, ! 401: ai_stand2, 0, NULL, ! 402: ai_stand2, 0, NULL, ! 403: ai_stand2, 0, NULL, ! 404: ai_stand2, 0, NULL, ! 405: ai_stand2, 0, NULL, ! 406: ! 407: ai_stand2, 0, NULL, ! 408: ai_stand2, 0, NULL, ! 409: ai_stand2, 0, NULL, ! 410: ai_stand2, 0, NULL, ! 411: ai_stand2, 0, NULL, ! 412: ai_stand2, 0, NULL, ! 413: ai_stand2, 0, NULL, ! 414: ai_stand2, 0, NULL, ! 415: ai_stand2, 0, NULL, ! 416: ai_stand2, 0, NULL, ! 417: ! 418: ai_stand2, 0, NULL, ! 419: ai_stand2, 0, gekk_idle_loop ! 420: }; ! 421: mmove_t gekk_move_idle = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_stand}; ! 422: mmove_t gekk_move_idle2 = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_face}; ! 423: ! 424: mframe_t gekk_frames_idle2 [] = ! 425: { ! 426: ai_move, 0, gekk_search, ! 427: ai_move, 0, NULL, ! 428: ai_move, 0, NULL, ! 429: ai_move, 0, NULL, ! 430: ai_move, 0, NULL, ! 431: ai_move, 0, NULL, ! 432: ai_move, 0, NULL, ! 433: ai_move, 0, NULL, ! 434: ai_move, 0, NULL, ! 435: ai_move, 0, NULL, ! 436: ! 437: ai_move, 0, NULL, ! 438: ai_move, 0, NULL, ! 439: ai_move, 0, NULL, ! 440: ai_move, 0, NULL, ! 441: ai_move, 0, NULL, ! 442: ai_move, 0, NULL, ! 443: ai_move, 0, NULL, ! 444: ai_move, 0, NULL, ! 445: ai_move, 0, NULL, ! 446: ai_move, 0, NULL, ! 447: ! 448: ai_move, 0, NULL, ! 449: ai_move, 0, NULL, ! 450: ai_move, 0, NULL, ! 451: ai_move, 0, NULL, ! 452: ai_move, 0, NULL, ! 453: ai_move, 0, NULL, ! 454: ai_move, 0, NULL, ! 455: ai_move, 0, NULL, ! 456: ai_move, 0, NULL, ! 457: ai_move, 0, NULL, ! 458: ! 459: ai_move, 0, NULL, ! 460: ai_move, 0, gekk_idle_loop ! 461: }; ! 462: mmove_t gekk_move_chant = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle2, gekk_chant}; ! 463: ! 464: ! 465: void gekk_idle (edict_t *self) ! 466: { ! 467: if (!self->waterlevel) ! 468: self->monsterinfo.currentmove = &gekk_move_idle; ! 469: else ! 470: self->monsterinfo.currentmove = &gekk_move_swim_start; ! 471: // gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); ! 472: } ! 473: ! 474: ! 475: // ! 476: // WALK ! 477: // ! 478: ! 479: void gekk_walk (edict_t *self); ! 480: mframe_t gekk_frames_walk[] = ! 481: { ! 482: ai_walk, 3.849, gekk_check_underwater, // frame 0 ! 483: ai_walk, 19.606, NULL, // frame 1 ! 484: ai_walk, 25.583, NULL, // frame 2 ! 485: ai_walk, 34.625, gekk_step, // frame 3 ! 486: ai_walk, 27.365, NULL, // frame 4 ! 487: ai_walk, 28.480, NULL, // frame 5 ! 488: }; ! 489: ! 490: mmove_t gekk_move_walk = {FRAME_run_01, FRAME_run_06, gekk_frames_walk, NULL}; ! 491: ! 492: void gekk_walk (edict_t *self) ! 493: { ! 494: self->monsterinfo.currentmove = &gekk_move_walk; ! 495: } ! 496: ! 497: ! 498: // ! 499: // RUN ! 500: // ! 501: ! 502: void gekk_run_start (edict_t *self) ! 503: { ! 504: if (self->waterlevel) ! 505: { ! 506: self->monsterinfo.currentmove = &gekk_move_swim_start; ! 507: } ! 508: else ! 509: { ! 510: self->monsterinfo.currentmove = &gekk_move_run_start; ! 511: } ! 512: } ! 513: ! 514: void gekk_run (edict_t *self) ! 515: { ! 516: ! 517: if (self->waterlevel) ! 518: { ! 519: self->monsterinfo.currentmove = &gekk_move_swim_start; ! 520: return; ! 521: } ! 522: else ! 523: { ! 524: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 525: self->monsterinfo.currentmove = &gekk_move_stand; ! 526: else ! 527: self->monsterinfo.currentmove = &gekk_move_run; ! 528: } ! 529: ! 530: } ! 531: mframe_t gekk_frames_run[] = ! 532: { ! 533: ai_run, 3.849, gekk_check_underwater, // frame 0 ! 534: ai_run, 19.606, NULL, // frame 1 ! 535: ai_run, 25.583, NULL, // frame 2 ! 536: ai_run, 34.625, gekk_step, // frame 3 ! 537: ai_run, 27.365, NULL, // frame 4 ! 538: ai_run, 28.480, NULL, // frame 5 ! 539: }; ! 540: mmove_t gekk_move_run = {FRAME_run_01, FRAME_run_06, gekk_frames_run, NULL}; ! 541: ! 542: mframe_t gekk_frames_run_st[] = ! 543: { ! 544: ai_run, 0.212, NULL, // frame 0 ! 545: ai_run, 19.753, NULL, // frame 1 ! 546: }; ! 547: mmove_t gekk_move_run_start = {FRAME_stand_01, FRAME_stand_02, gekk_frames_run_st, gekk_run}; ! 548: ! 549: // ! 550: // MELEE ! 551: // ! 552: ! 553: void gekk_hit_left (edict_t *self) ! 554: { ! 555: vec3_t aim; ! 556: ! 557: VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8); ! 558: if (fire_hit (self, aim, (15 + (rand() %5)), 100)) ! 559: gi.sound (self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0); ! 560: else ! 561: gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); ! 562: } ! 563: ! 564: void gekk_hit_right (edict_t *self) ! 565: { ! 566: vec3_t aim; ! 567: ! 568: VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8); ! 569: if (fire_hit (self, aim, (15 + (rand() %5)), 100)) ! 570: gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0); ! 571: else ! 572: gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); ! 573: } ! 574: ! 575: void gekk_check_refire (edict_t *self) ! 576: { ! 577: if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0) ! 578: return; ! 579: ! 580: if (random() < (skill->value * 0.1)) ! 581: { ! 582: if (range (self, self->enemy) == RANGE_MELEE) ! 583: { ! 584: if (self->s.frame == FRAME_clawatk3_09) ! 585: self->monsterinfo.currentmove = &gekk_move_attack2; ! 586: else if (self->s.frame == FRAME_clawatk5_09) ! 587: self->monsterinfo.currentmove = &gekk_move_attack1; ! 588: } ! 589: } ! 590: ! 591: } ! 592: ! 593: ! 594: void loogie_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) ! 595: { ! 596: ! 597: if (other == self->owner) ! 598: return; ! 599: ! 600: if (surf && (surf->flags & SURF_SKY)) ! 601: { ! 602: G_FreeEdict (self); ! 603: return; ! 604: } ! 605: ! 606: if (self->owner->client) ! 607: PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); ! 608: ! 609: if (other->takedamage) ! 610: T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_GEKK); ! 611: ! 612: G_FreeEdict (self); ! 613: }; ! 614: ! 615: ! 616: ! 617: void fire_loogie (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed) ! 618: { ! 619: edict_t *loogie; ! 620: trace_t tr; ! 621: ! 622: VectorNormalize (dir); ! 623: ! 624: loogie = G_Spawn(); ! 625: VectorCopy (start, loogie->s.origin); ! 626: VectorCopy (start, loogie->s.old_origin); ! 627: vectoangles (dir, loogie->s.angles); ! 628: VectorScale (dir, speed, loogie->velocity); ! 629: loogie->movetype = MOVETYPE_FLYMISSILE; ! 630: loogie->clipmask = MASK_SHOT; ! 631: loogie->solid = SOLID_BBOX; ! 632: loogie->s.effects |= RF_FULLBRIGHT; ! 633: VectorClear (loogie->mins); ! 634: VectorClear (loogie->maxs); ! 635: ! 636: loogie->s.modelindex = gi.modelindex ("models/objects/loogy/tris.md2"); ! 637: loogie->owner = self; ! 638: loogie->touch = loogie_touch; ! 639: loogie->nextthink = level.time + 2; ! 640: loogie->think = G_FreeEdict; ! 641: loogie->dmg = damage; ! 642: gi.linkentity (loogie); ! 643: ! 644: tr = gi.trace (self->s.origin, NULL, NULL, loogie->s.origin, loogie, MASK_SHOT); ! 645: if (tr.fraction < 1.0) ! 646: { ! 647: VectorMA (loogie->s.origin, -10, dir, loogie->s.origin); ! 648: loogie->touch (loogie, tr.ent, NULL, NULL); ! 649: } ! 650: ! 651: } ! 652: ! 653: void loogie (edict_t *self) ! 654: { ! 655: vec3_t start; ! 656: vec3_t forward, right, up; ! 657: vec3_t end; ! 658: vec3_t dir; ! 659: vec3_t gekkoffset; ! 660: ! 661: VectorSet (gekkoffset, -18, -0.8, 24); ! 662: ! 663: if (!self->enemy || self->enemy->health <= 0) ! 664: return; ! 665: ! 666: AngleVectors (self->s.angles, forward, right, up); ! 667: G_ProjectSource (self->s.origin, gekkoffset, forward, right, start); ! 668: ! 669: VectorMA (start, 2, up, start); ! 670: ! 671: VectorCopy (self->enemy->s.origin, end); ! 672: end[2] += self->enemy->viewheight; ! 673: VectorSubtract (end, start, dir); ! 674: ! 675: fire_loogie (self, start, dir, 5, 550); ! 676: ! 677: } ! 678: ! 679: void reloogie (edict_t *self) ! 680: { ! 681: if (random() > 0.8 && self->health < self->max_health) ! 682: { ! 683: self->monsterinfo.currentmove = &gekk_move_idle2; ! 684: return; ! 685: } ! 686: ! 687: if (self->enemy->health >= 0) ! 688: if (random() > 0.7 && (range(self, self->enemy) == RANGE_NEAR)) ! 689: self->monsterinfo.currentmove = &gekk_move_spit; ! 690: } ! 691: ! 692: ! 693: mframe_t gekk_frames_spit [] = ! 694: { ! 695: ai_charge, 0.000, NULL, ! 696: ai_charge, 0.000, NULL, ! 697: ai_charge, 0.000, NULL, ! 698: ai_charge, 0.000, NULL, ! 699: ai_charge, 0.000, NULL, ! 700: ! 701: ai_charge, 0.000, loogie, ! 702: ai_charge, 0.000, reloogie ! 703: }; ! 704: mmove_t gekk_move_spit = {FRAME_spit_01, FRAME_spit_07, gekk_frames_spit, gekk_run_start}; ! 705: ! 706: ! 707: mframe_t gekk_frames_attack1 [] = ! 708: { ! 709: ai_charge, 0, NULL, ! 710: ai_charge, 0, NULL, ! 711: ai_charge, 0, NULL, ! 712: ! 713: ai_charge, 0, gekk_hit_left, ! 714: ai_charge, 0, NULL, ! 715: ai_charge, 0, NULL, ! 716: ! 717: ai_charge, 0, NULL, ! 718: ai_charge, 0, NULL, ! 719: ai_charge, 0, gekk_check_refire ! 720: ! 721: }; ! 722: mmove_t gekk_move_attack1 = {FRAME_clawatk3_01, FRAME_clawatk3_09, gekk_frames_attack1, gekk_run_start}; ! 723: ! 724: mframe_t gekk_frames_attack2[] = ! 725: { ! 726: ai_charge, 0.000, NULL, ! 727: ai_charge, 0.000, NULL, ! 728: ai_charge, 0.000, gekk_hit_left, ! 729: ! 730: ai_charge, 0.000, NULL, ! 731: ai_charge, 0.000, NULL, ! 732: ai_charge, 0.000, gekk_hit_right, ! 733: ! 734: ai_charge, 0.000, NULL, ! 735: ai_charge, 0.000, NULL, ! 736: ai_charge, 0.000, gekk_check_refire ! 737: ! 738: }; ! 739: mmove_t gekk_move_attack2 = {FRAME_clawatk5_01, FRAME_clawatk5_09, gekk_frames_attack2, gekk_run_start}; ! 740: ! 741: void gekk_check_underwater (edict_t *self) ! 742: { ! 743: if (self->waterlevel) ! 744: { ! 745: land_to_water (self); ! 746: } ! 747: } ! 748: ! 749: mframe_t gekk_frames_leapatk[] = ! 750: { ! 751: ai_charge, 0.000, NULL, // frame 0 ! 752: ai_charge, -0.387, NULL, // frame 1 ! 753: ai_charge, -1.113, NULL, // frame 2 ! 754: ai_charge, -0.237, NULL, // frame 3 ! 755: ai_charge, 6.720, gekk_jump_takeoff, // frame 4 last frame on ground ! 756: ai_charge, 6.414, NULL, // frame 5 leaves ground ! 757: ai_charge, 0.163, NULL, // frame 6 ! 758: ai_charge, 28.316, NULL, // frame 7 ! 759: ai_charge, 24.198, NULL, // frame 8 ! 760: ai_charge, 31.742, NULL, // frame 9 ! 761: ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air ! 762: ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground ! 763: ai_charge, 20.122, gekk_stop_skid, // frame 12 ! 764: ai_charge, -1.042, gekk_stop_skid, // frame 13 ! 765: ai_charge, 2.556, gekk_stop_skid, // frame 14 ! 766: ai_charge, 0.544, gekk_stop_skid, // frame 15 ! 767: ai_charge, 1.862, gekk_stop_skid, // frame 16 ! 768: ai_charge, 1.224, gekk_stop_skid, // frame 17 ! 769: ! 770: ai_charge, -0.457, gekk_check_underwater, // frame 18 ! 771: }; ! 772: mmove_t gekk_move_leapatk = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk, gekk_run_start}; ! 773: ! 774: ! 775: mframe_t gekk_frames_leapatk2[] = ! 776: { ! 777: ai_charge, 0.000, NULL, // frame 0 ! 778: ai_charge, -0.387, NULL, // frame 1 ! 779: ai_charge, -1.113, NULL, // frame 2 ! 780: ai_charge, -0.237, NULL, // frame 3 ! 781: ai_charge, 6.720, gekk_jump_takeoff2, // frame 4 last frame on ground ! 782: ai_charge, 6.414, NULL, // frame 5 leaves ground ! 783: ai_charge, 0.163, NULL, // frame 6 ! 784: ai_charge, 28.316, NULL, // frame 7 ! 785: ai_charge, 24.198, NULL, // frame 8 ! 786: ai_charge, 31.742, NULL, // frame 9 ! 787: ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air ! 788: ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground ! 789: ai_charge, 20.122, gekk_stop_skid, // frame 12 ! 790: ai_charge, -1.042, gekk_stop_skid, // frame 13 ! 791: ai_charge, 2.556, gekk_stop_skid, // frame 14 ! 792: ai_charge, 0.544, gekk_stop_skid, // frame 15 ! 793: ai_charge, 1.862, gekk_stop_skid, // frame 16 ! 794: ai_charge, 1.224, gekk_stop_skid, // frame 17 ! 795: ! 796: ai_charge, -0.457, gekk_check_underwater, // frame 18 ! 797: }; ! 798: mmove_t gekk_move_leapatk2 = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk2, gekk_run_start}; ! 799: ! 800: ! 801: void gekk_bite (edict_t *self) ! 802: { ! 803: vec3_t aim; ! 804: ! 805: VectorSet (aim, MELEE_DISTANCE, 0, 0); ! 806: fire_hit (self, aim, 5, 0); ! 807: } ! 808: ! 809: void gekk_preattack (edict_t *self) ! 810: { ! 811: // underwater attack sound ! 812: // gi.sound (self, CHAN_WEAPON, something something underwater sound, 1, ATTN_NORM, 0); ! 813: return; ! 814: } ! 815: ! 816: ! 817: mframe_t gekk_frames_attack [] = ! 818: { ! 819: ai_charge, 16, gekk_preattack, ! 820: ai_charge, 16, NULL, ! 821: ai_charge, 16, NULL, ! 822: ai_charge, 16, NULL, ! 823: ai_charge, 16, gekk_bite, ! 824: ai_charge, 16, NULL, ! 825: ai_charge, 16, NULL, ! 826: ai_charge, 16, NULL, ! 827: ai_charge, 16, NULL, ! 828: ai_charge, 16, gekk_bite, ! 829: ! 830: ai_charge, 16, NULL, ! 831: ai_charge, 16, NULL, ! 832: ai_charge, 16, NULL, ! 833: ai_charge, 16, gekk_hit_left, ! 834: ai_charge, 16, NULL, ! 835: ai_charge, 16, NULL, ! 836: ai_charge, 16, NULL, ! 837: ai_charge, 16, NULL, ! 838: ai_charge, 16, gekk_hit_right, ! 839: ai_charge, 16, NULL, ! 840: ! 841: ai_charge, 16, NULL ! 842: ! 843: }; ! 844: mmove_t gekk_move_attack = {FRAME_attack_01, FRAME_attack_21, gekk_frames_attack, gekk_run_start}; ! 845: ! 846: void gekk_melee (edict_t *self) ! 847: { ! 848: ! 849: float r; ! 850: ! 851: if (self->waterlevel) ! 852: { ! 853: self->monsterinfo.currentmove = &gekk_move_attack; ! 854: } ! 855: else ! 856: { ! 857: r = random(); ! 858: ! 859: if (r > 0.66) ! 860: self->monsterinfo.currentmove = &gekk_move_attack1; ! 861: else ! 862: self->monsterinfo.currentmove = &gekk_move_attack2; ! 863: ! 864: } ! 865: ! 866: } ! 867: ! 868: ! 869: // ! 870: // ATTACK ! 871: // ! 872: ! 873: void gekk_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) ! 874: { ! 875: if (self->health <= 0) ! 876: { ! 877: self->touch = NULL; ! 878: return; ! 879: } ! 880: ! 881: if (other->takedamage) ! 882: { ! 883: if (VectorLength(self->velocity) > 200) ! 884: { ! 885: vec3_t point; ! 886: vec3_t normal; ! 887: int damage; ! 888: ! 889: VectorCopy (self->velocity, normal); ! 890: VectorNormalize(normal); ! 891: VectorMA (self->s.origin, self->maxs[0], normal, point); ! 892: damage = 10 + 10 * random(); ! 893: T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_GEKK); ! 894: } ! 895: } ! 896: ! 897: if (!M_CheckBottom (self)) ! 898: { ! 899: if (self->groundentity) ! 900: { ! 901: self->monsterinfo.nextframe = FRAME_leapatk_11; ! 902: self->touch = NULL; ! 903: } ! 904: return; ! 905: } ! 906: ! 907: self->touch = NULL; ! 908: } ! 909: ! 910: void gekk_jump_takeoff (edict_t *self) ! 911: { ! 912: vec3_t forward; ! 913: ! 914: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); ! 915: AngleVectors (self->s.angles, forward, NULL, NULL); ! 916: self->s.origin[2] += 1; ! 917: ! 918: // high jump ! 919: if (gekk_check_jump (self)) ! 920: { ! 921: VectorScale (forward, 700, self->velocity); ! 922: self->velocity[2] = 250; ! 923: } ! 924: else ! 925: { ! 926: VectorScale (forward, 250, self->velocity); ! 927: self->velocity[2] = 400; ! 928: } ! 929: ! 930: ! 931: self->groundentity = NULL; ! 932: self->monsterinfo.aiflags |= AI_DUCKED; ! 933: self->monsterinfo.attack_finished = level.time + 3; ! 934: self->touch = gekk_jump_touch; ! 935: } ! 936: ! 937: void gekk_jump_takeoff2 (edict_t *self) ! 938: { ! 939: vec3_t forward; ! 940: ! 941: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); ! 942: AngleVectors (self->s.angles, forward, NULL, NULL); ! 943: self->s.origin[2] = self->enemy->s.origin[2]; ! 944: ! 945: if (gekk_check_jump (self)) ! 946: { ! 947: VectorScale (forward, 300, self->velocity); ! 948: self->velocity[2] = 250; ! 949: } ! 950: else ! 951: { ! 952: VectorScale (forward, 150, self->velocity); ! 953: self->velocity[2] = 300; ! 954: } ! 955: ! 956: self->groundentity = NULL; ! 957: self->monsterinfo.aiflags |= AI_DUCKED; ! 958: self->monsterinfo.attack_finished = level.time + 3; ! 959: self->touch = gekk_jump_touch; ! 960: ! 961: } ! 962: ! 963: void gekk_stop_skid (edict_t *self) ! 964: { ! 965: if (self->groundentity) ! 966: { ! 967: VectorClear (self->velocity); ! 968: } ! 969: } ! 970: ! 971: void gekk_check_landing (edict_t *self) ! 972: { ! 973: if (self->groundentity) ! 974: { ! 975: gi.sound (self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0); ! 976: self->monsterinfo.attack_finished = 0; ! 977: self->monsterinfo.aiflags &= ~AI_DUCKED; ! 978: ! 979: VectorClear (self->velocity); ! 980: ! 981: return; ! 982: } ! 983: ! 984: // note to self ! 985: // causing skid ! 986: if (level.time > self->monsterinfo.attack_finished) ! 987: self->monsterinfo.nextframe = FRAME_leapatk_11; ! 988: else ! 989: { ! 990: self->monsterinfo.nextframe = FRAME_leapatk_12; ! 991: } ! 992: } ! 993: ! 994: void gekk_jump (edict_t *self) ! 995: { ! 996: ! 997: if (self->flags & FL_SWIM || self->waterlevel) ! 998: { ! 999: return; ! 1000: } ! 1001: else ! 1002: { ! 1003: //if (random() > 0.8 && self->health < self->max_health) ! 1004: // self->monsterinfo.currentmove = &gekk_move_idle2; ! 1005: //else ! 1006: { ! 1007: if (random() > 0.5 && (range (self, self->enemy) >= RANGE_NEAR)) ! 1008: self->monsterinfo.currentmove = &gekk_move_spit; ! 1009: else if (random() > 0.8) ! 1010: self->monsterinfo.currentmove = &gekk_move_spit; ! 1011: else ! 1012: self->monsterinfo.currentmove = &gekk_move_leapatk; ! 1013: ! 1014: } ! 1015: } ! 1016: } ! 1017: ! 1018: // ! 1019: // PAIN ! 1020: // ! 1021: ! 1022: mframe_t gekk_frames_pain[] = ! 1023: { ! 1024: ai_move, 0.000, NULL, // frame 0 ! 1025: ai_move, 0.000, NULL, // frame 1 ! 1026: ai_move, 0.000, NULL, // frame 2 ! 1027: ai_move, 0.000, NULL, // frame 3 ! 1028: ai_move, 0.000, NULL, // frame 4 ! 1029: ai_move, 0.000, NULL, // frame 5 ! 1030: }; ! 1031: mmove_t gekk_move_pain = {FRAME_pain_01, FRAME_pain_06, gekk_frames_pain, gekk_run_start}; ! 1032: ! 1033: mframe_t gekk_frames_pain1[] = ! 1034: { ! 1035: ai_move, 0.000, NULL, // frame 0 ! 1036: ai_move, 0.000, NULL, // frame 1 ! 1037: ai_move, 0.000, NULL, // frame 2 ! 1038: ai_move, 0.000, NULL, // frame 3 ! 1039: ai_move, 0.000, NULL, // frame 4 ! 1040: ai_move, 0.000, NULL, // frame 5 ! 1041: ai_move, 0.000, NULL, // frame 6 ! 1042: ai_move, 0.000, NULL, // frame 7 ! 1043: ai_move, 0.000, NULL, // frame 8 ! 1044: ai_move, 0.000, NULL, // frame 9 ! 1045: ! 1046: ai_move, 0.000, gekk_check_underwater ! 1047: }; ! 1048: mmove_t gekk_move_pain1 = {FRAME_pain3_01, FRAME_pain3_11, gekk_frames_pain1, gekk_run_start}; ! 1049: ! 1050: mframe_t gekk_frames_pain2[] = ! 1051: { ! 1052: ai_move, 0.000, NULL, // frame 0 ! 1053: ai_move, 0.000, NULL, // frame 1 ! 1054: ai_move, 0.000, NULL, // frame 2 ! 1055: ai_move, 0.000, NULL, // frame 3 ! 1056: ai_move, 0.000, NULL, // frame 4 ! 1057: ai_move, 0.000, NULL, // frame 5 ! 1058: ai_move, 0.000, NULL, // frame 6 ! 1059: ai_move, 0.000, NULL, // frame 7 ! 1060: ai_move, 0.000, NULL, // frame 8 ! 1061: ai_move, 0.000, NULL, // frame 9 ! 1062: ! 1063: ai_move, 0.000, NULL, // frame 10 ! 1064: ai_move, 0.000, NULL, // frame 11 ! 1065: ai_move, 0.000, gekk_check_underwater, ! 1066: }; ! 1067: mmove_t gekk_move_pain2 = {FRAME_pain4_01, FRAME_pain4_13, gekk_frames_pain2, gekk_run_start}; ! 1068: ! 1069: void gekk_pain (edict_t *self, edict_t *other, float kick, int damage) ! 1070: { ! 1071: float r; ! 1072: ! 1073: if (self->spawnflags & 8) ! 1074: { ! 1075: self->spawnflags &= ~8; ! 1076: return; ! 1077: } ! 1078: ! 1079: if (self->health < (self->max_health /4)) ! 1080: self->s.skinnum = 2; ! 1081: else if (self->health < (self->max_health / 2)) ! 1082: self->s.skinnum = 1; ! 1083: ! 1084: if (level.time < self->pain_debounce_time) ! 1085: return; ! 1086: ! 1087: self->pain_debounce_time = level.time + 3; ! 1088: ! 1089: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); ! 1090: ! 1091: if (self->waterlevel) ! 1092: { ! 1093: if (!self->flags & FL_SWIM) ! 1094: self->flags |= FL_SWIM; ! 1095: ! 1096: self->monsterinfo.currentmove = &gekk_move_pain; ! 1097: } ! 1098: else ! 1099: { ! 1100: r = random(); ! 1101: ! 1102: if (r > 0.5) ! 1103: self->monsterinfo.currentmove = &gekk_move_pain1; ! 1104: else ! 1105: self->monsterinfo.currentmove = &gekk_move_pain2; ! 1106: } ! 1107: } ! 1108: ! 1109: ! 1110: // ! 1111: // DEATH ! 1112: // ! 1113: ! 1114: void gekk_dead (edict_t *self) ! 1115: { ! 1116: // fix this because of no blocking problem ! 1117: if (self->waterlevel) ! 1118: { ! 1119: return; ! 1120: } ! 1121: else ! 1122: { ! 1123: VectorSet (self->mins, -16, -16, -24); ! 1124: VectorSet (self->maxs, 16, 16, -8); ! 1125: self->movetype = MOVETYPE_TOSS; ! 1126: self->svflags |= SVF_DEADMONSTER; ! 1127: self->nextthink = 0; ! 1128: gi.linkentity (self); ! 1129: } ! 1130: ! 1131: ! 1132: } ! 1133: ! 1134: void gekk_gibfest (edict_t *self) ! 1135: { ! 1136: ! 1137: int damage = 20; ! 1138: ! 1139: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 1140: ! 1141: ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC); ! 1142: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC); ! 1143: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC); ! 1144: ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC); ! 1145: ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC); ! 1146: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC); ! 1147: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC); ! 1148: ! 1149: ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC); ! 1150: ! 1151: ! 1152: self->deadflag = DEAD_DEAD; ! 1153: ! 1154: } ! 1155: ! 1156: void isgibfest (edict_t *self) ! 1157: { ! 1158: if (random() > 0.9) ! 1159: gekk_gibfest (self); ! 1160: } ! 1161: ! 1162: mframe_t gekk_frames_death1[] = ! 1163: { ! 1164: ! 1165: ai_move, -5.151, NULL, // frame 0 ! 1166: ai_move, -12.223, NULL, // frame 1 ! 1167: ai_move, -11.484, NULL, // frame 2 ! 1168: ai_move, -17.952, NULL, // frame 3 ! 1169: ai_move, -6.953, NULL, // frame 4 ! 1170: ai_move, -7.393, NULL, // frame 5 ! 1171: ai_move, -10.713, NULL, // frame 6 ! 1172: ai_move, -17.464, NULL, // frame 7 ! 1173: ai_move, -11.678, NULL, // frame 8 ! 1174: ai_move, -11.678, NULL // frame 9 ! 1175: }; ! 1176: mmove_t gekk_move_death1 = {FRAME_death1_01, FRAME_death1_10, gekk_frames_death1, gekk_dead}; ! 1177: ! 1178: mframe_t gekk_frames_death3[] = ! 1179: { ! 1180: ai_move, 0.000, NULL, // frame 0 ! 1181: ai_move, 0.022, NULL, // frame 1 ! 1182: ai_move, 0.169, NULL, // frame 2 ! 1183: ai_move, -0.710, NULL, // frame 3 ! 1184: ai_move, -13.446, NULL, // frame 4 ! 1185: ai_move, -7.654, isgibfest, // frame 5 ! 1186: ai_move, -31.951, NULL, // frame 6 ! 1187: ! 1188: }; ! 1189: mmove_t gekk_move_death3 = {FRAME_death3_01, FRAME_death3_07, gekk_frames_death3, gekk_dead}; ! 1190: ! 1191: mframe_t gekk_frames_death4[] = ! 1192: { ! 1193: ai_move, 5.103, NULL, // frame 0 ! 1194: ai_move, -4.808, NULL, // frame 1 ! 1195: ai_move, -10.509, NULL, // frame 2 ! 1196: ai_move, -9.899, NULL, // frame 3 ! 1197: ai_move, 4.033, isgibfest, // frame 4 ! 1198: ai_move, -5.197, NULL, // frame 5 ! 1199: ai_move, -0.919, NULL, // frame 6 ! 1200: ai_move, -8.821, NULL, // frame 7 ! 1201: ai_move, -5.626, NULL, // frame 8 ! 1202: ai_move, -8.865, isgibfest, // frame 9 ! 1203: ai_move, -0.845, NULL, // frame 10 ! 1204: ai_move, 1.986, NULL, // frame 11 ! 1205: ai_move, 0.170, NULL, // frame 12 ! 1206: ai_move, 1.339, isgibfest, // frame 13 ! 1207: ai_move, -0.922, NULL, // frame 14 ! 1208: ai_move, 0.818, NULL, // frame 15 ! 1209: ai_move, -1.288, NULL, // frame 16 ! 1210: ai_move, -1.408, isgibfest, // frame 17 ! 1211: ai_move, -7.787, NULL, // frame 18 ! 1212: ai_move, -3.995, NULL, // frame 19 ! 1213: ai_move, -4.604, NULL, // frame 20 ! 1214: ai_move, -1.715, isgibfest, // frame 21 ! 1215: ai_move, -0.564, NULL, // frame 22 ! 1216: ai_move, -0.597, NULL, // frame 23 ! 1217: ai_move, 0.074, NULL, // frame 24 ! 1218: ai_move, -0.309, isgibfest, // frame 25 ! 1219: ai_move, -0.395, NULL, // frame 26 ! 1220: ai_move, -0.501, NULL, // frame 27 ! 1221: ai_move, -0.325, NULL, // frame 28 ! 1222: ai_move, -0.931, isgibfest, // frame 29 ! 1223: ai_move, -1.433, NULL, // frame 30 ! 1224: ai_move, -1.626, NULL, // frame 31 ! 1225: ai_move, 4.680, NULL, // frame 32 ! 1226: ai_move, 0.560, NULL, // frame 33 ! 1227: ai_move, -0.549, gekk_gibfest // frame 34 ! 1228: }; ! 1229: mmove_t gekk_move_death4 = {FRAME_death4_01, FRAME_death4_35, gekk_frames_death4, gekk_dead}; ! 1230: ! 1231: mframe_t gekk_frames_wdeath[] = ! 1232: { ! 1233: ai_move, 0.000, NULL, // frame 0 ! 1234: ai_move, 0.000, NULL, // frame 1 ! 1235: ai_move, 0.000, NULL, // frame 2 ! 1236: ai_move, 0.000, NULL, // frame 3 ! 1237: ai_move, 0.000, NULL, // frame 4 ! 1238: ai_move, 0.000, NULL, // frame 5 ! 1239: ai_move, 0.000, NULL, // frame 6 ! 1240: ai_move, 0.000, NULL, // frame 7 ! 1241: ai_move, 0.000, NULL, // frame 8 ! 1242: ai_move, 0.000, NULL, // frame 9 ! 1243: ai_move, 0.000, NULL, // frame 10 ! 1244: ai_move, 0.000, NULL, // frame 11 ! 1245: ai_move, 0.000, NULL, // frame 12 ! 1246: ai_move, 0.000, NULL, // frame 13 ! 1247: ai_move, 0.000, NULL, // frame 14 ! 1248: ai_move, 0.000, NULL, // frame 15 ! 1249: ai_move, 0.000, NULL, // frame 16 ! 1250: ai_move, 0.000, NULL, // frame 17 ! 1251: ai_move, 0.000, NULL, // frame 18 ! 1252: ai_move, 0.000, NULL, // frame 19 ! 1253: ai_move, 0.000, NULL, // frame 20 ! 1254: ai_move, 0.000, NULL, // frame 21 ! 1255: ai_move, 0.000, NULL, // frame 22 ! 1256: ai_move, 0.000, NULL, // frame 23 ! 1257: ai_move, 0.000, NULL, // frame 24 ! 1258: ai_move, 0.000, NULL, // frame 25 ! 1259: ai_move, 0.000, NULL, // frame 26 ! 1260: ai_move, 0.000, NULL, // frame 27 ! 1261: ai_move, 0.000, NULL, // frame 28 ! 1262: ai_move, 0.000, NULL, // frame 29 ! 1263: ai_move, 0.000, NULL, // frame 30 ! 1264: ai_move, 0.000, NULL, // frame 31 ! 1265: ai_move, 0.000, NULL, // frame 32 ! 1266: ai_move, 0.000, NULL, // frame 33 ! 1267: ai_move, 0.000, NULL, // frame 34 ! 1268: ai_move, 0.000, NULL, // frame 35 ! 1269: ai_move, 0.000, NULL, // frame 36 ! 1270: ai_move, 0.000, NULL, // frame 37 ! 1271: ai_move, 0.000, NULL, // frame 38 ! 1272: ai_move, 0.000, NULL, // frame 39 ! 1273: ai_move, 0.000, NULL, // frame 40 ! 1274: ai_move, 0.000, NULL, // frame 41 ! 1275: ai_move, 0.000, NULL, // frame 42 ! 1276: ai_move, 0.000, NULL, // frame 43 ! 1277: ai_move, 0.000, NULL // frame 44 ! 1278: }; ! 1279: mmove_t gekk_move_wdeath = {FRAME_wdeath_01, FRAME_wdeath_45, gekk_frames_wdeath, gekk_dead}; ! 1280: ! 1281: void gekk_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) ! 1282: { ! 1283: ! 1284: float r; ! 1285: ! 1286: if (self->health <= self->gib_health) ! 1287: { ! 1288: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 1289: ! 1290: ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC); ! 1291: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC); ! 1292: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC); ! 1293: ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC); ! 1294: ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC); ! 1295: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC); ! 1296: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC); ! 1297: ! 1298: ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC); ! 1299: ! 1300: self->deadflag = DEAD_DEAD; ! 1301: return; ! 1302: } ! 1303: ! 1304: if (self->deadflag == DEAD_DEAD) ! 1305: return; ! 1306: ! 1307: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); ! 1308: self->deadflag = DEAD_DEAD; ! 1309: self->takedamage = DAMAGE_YES; ! 1310: self->s.skinnum = 2; ! 1311: ! 1312: if (self->waterlevel) ! 1313: self->monsterinfo.currentmove = &gekk_move_wdeath; ! 1314: else ! 1315: { ! 1316: r = random(); ! 1317: if (r > 0.66) ! 1318: self->monsterinfo.currentmove = &gekk_move_death1; ! 1319: else if (r > 0.33) ! 1320: self->monsterinfo.currentmove = &gekk_move_death3; ! 1321: else ! 1322: self->monsterinfo.currentmove = &gekk_move_death4; ! 1323: ! 1324: } ! 1325: ! 1326: } ! 1327: ! 1328: ! 1329: /* ! 1330: duck ! 1331: */ ! 1332: void gekk_duck_down (edict_t *self) ! 1333: { ! 1334: if (self->monsterinfo.aiflags & AI_DUCKED) ! 1335: return; ! 1336: self->monsterinfo.aiflags |= AI_DUCKED; ! 1337: self->maxs[2] -= 32; ! 1338: self->takedamage = DAMAGE_YES; ! 1339: self->monsterinfo.pausetime = level.time + 1; ! 1340: gi.linkentity (self); ! 1341: } ! 1342: ! 1343: void gekk_duck_up (edict_t *self) ! 1344: { ! 1345: self->monsterinfo.aiflags &= ~AI_DUCKED; ! 1346: self->maxs[2] += 32; ! 1347: self->takedamage = DAMAGE_AIM; ! 1348: gi.linkentity (self); ! 1349: } ! 1350: ! 1351: ! 1352: void gekk_duck_hold (edict_t *self) ! 1353: { ! 1354: if (level.time >= self->monsterinfo.pausetime) ! 1355: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; ! 1356: else ! 1357: self->monsterinfo.aiflags |= AI_HOLD_FRAME; ! 1358: } ! 1359: ! 1360: mframe_t gekk_frames_lduck[] = ! 1361: { ! 1362: ai_move, 0.000, NULL, // frame 0 ! 1363: ai_move, 0.000, NULL, // frame 1 ! 1364: ai_move, 0.000, NULL, // frame 2 ! 1365: ai_move, 0.000, NULL, // frame 3 ! 1366: ai_move, 0.000, NULL, // frame 4 ! 1367: ai_move, 0.000, NULL, // frame 5 ! 1368: ai_move, 0.000, NULL, // frame 6 ! 1369: ai_move, 0.000, NULL, // frame 7 ! 1370: ai_move, 0.000, NULL, // frame 8 ! 1371: ai_move, 0.000, NULL, // frame 9 ! 1372: ! 1373: ai_move, 0.000, NULL, // frame 10 ! 1374: ai_move, 0.000, NULL, // frame 11 ! 1375: ai_move, 0.000, NULL // frame 12 ! 1376: ! 1377: }; ! 1378: mmove_t gekk_move_lduck = {FRAME_lduck_01, FRAME_lduck_13, gekk_frames_lduck, gekk_run_start}; ! 1379: ! 1380: mframe_t gekk_frames_rduck[] = ! 1381: { ! 1382: ai_move, 0.000, NULL, // frame 0 ! 1383: ai_move, 0.000, NULL, // frame 1 ! 1384: ai_move, 0.000, NULL, // frame 2 ! 1385: ai_move, 0.000, NULL, // frame 3 ! 1386: ai_move, 0.000, NULL, // frame 4 ! 1387: ai_move, 0.000, NULL, // frame 5 ! 1388: ai_move, 0.000, NULL, // frame 6 ! 1389: ai_move, 0.000, NULL, // frame 7 ! 1390: ai_move, 0.000, NULL, // frame 8 ! 1391: ai_move, 0.000, NULL, // frame 9 ! 1392: ai_move, 0.000, NULL, // frame 10 ! 1393: ai_move, 0.000, NULL, // frame 11 ! 1394: ai_move, 0.000, NULL // frame 12 ! 1395: ! 1396: }; ! 1397: mmove_t gekk_move_rduck = {FRAME_rduck_01, FRAME_rduck_13, gekk_frames_rduck, gekk_run_start}; ! 1398: ! 1399: ! 1400: void gekk_dodge (edict_t *self, edict_t *attacker, float eta) ! 1401: { ! 1402: float r; ! 1403: ! 1404: r = random(); ! 1405: if (r > 0.25) ! 1406: return; ! 1407: ! 1408: if (!self->enemy) ! 1409: self->enemy = attacker; ! 1410: ! 1411: if (self->waterlevel) ! 1412: { ! 1413: self->monsterinfo.currentmove = &gekk_move_attack; ! 1414: return; ! 1415: } ! 1416: ! 1417: if (skill->value == 0) ! 1418: { ! 1419: r = random(); ! 1420: if (r > 0.5) ! 1421: self->monsterinfo.currentmove = &gekk_move_lduck; ! 1422: else ! 1423: self->monsterinfo.currentmove = &gekk_move_rduck; ! 1424: return; ! 1425: } ! 1426: ! 1427: self->monsterinfo.pausetime = level.time + eta + 0.3; ! 1428: r = random(); ! 1429: ! 1430: if (skill->value == 1) ! 1431: { ! 1432: if (r > 0.33) ! 1433: { ! 1434: r = random(); ! 1435: if (r > 0.5) ! 1436: self->monsterinfo.currentmove = &gekk_move_lduck; ! 1437: else ! 1438: self->monsterinfo.currentmove = &gekk_move_rduck; ! 1439: } ! 1440: else ! 1441: { ! 1442: r = random(); ! 1443: if (r > 0.66) ! 1444: self->monsterinfo.currentmove = &gekk_move_attack1; ! 1445: else ! 1446: self->monsterinfo.currentmove = &gekk_move_attack2; ! 1447: ! 1448: } ! 1449: return; ! 1450: } ! 1451: ! 1452: if (skill->value == 2) ! 1453: { ! 1454: if (r > 0.66) ! 1455: { ! 1456: r = random(); ! 1457: if (r > 0.5) ! 1458: self->monsterinfo.currentmove = &gekk_move_lduck; ! 1459: else ! 1460: self->monsterinfo.currentmove = &gekk_move_rduck; ! 1461: } ! 1462: else ! 1463: { ! 1464: r = random(); ! 1465: if (r > 0.66) ! 1466: self->monsterinfo.currentmove = &gekk_move_attack1; ! 1467: else ! 1468: self->monsterinfo.currentmove = &gekk_move_attack2; ! 1469: } ! 1470: return; ! 1471: } ! 1472: ! 1473: r = random(); ! 1474: if (r > 0.66) ! 1475: self->monsterinfo.currentmove = &gekk_move_attack1; ! 1476: else ! 1477: self->monsterinfo.currentmove = &gekk_move_attack2; ! 1478: ! 1479: ! 1480: } ! 1481: ! 1482: // ! 1483: // SPAWN ! 1484: // ! 1485: ! 1486: /*QUAKED monster_gekk (1 .5 0) (-24 -24 -24) (24 24 24) Ambush Trigger_Spawn Sight Chant ! 1487: */ ! 1488: void SP_monster_gekk (edict_t *self) ! 1489: { ! 1490: if (deathmatch->value) ! 1491: { ! 1492: G_FreeEdict (self); ! 1493: return; ! 1494: } ! 1495: ! 1496: sound_swing = gi.soundindex ("gek/gk_atck1.wav"); ! 1497: sound_hit = gi.soundindex ("gek/gk_atck2.wav"); ! 1498: sound_hit2 = gi.soundindex ("gek/gk_atck3.wav"); ! 1499: sound_death = gi.soundindex ("gek/gk_deth1.wav"); ! 1500: sound_pain1 = gi.soundindex ("gek/gk_pain1.wav"); ! 1501: sound_sight = gi.soundindex ("gek/gk_sght1.wav"); ! 1502: sound_search = gi.soundindex ("gek/gk_idle1.wav"); ! 1503: sound_step1 = gi.soundindex ("gek/gk_step1.wav"); ! 1504: sound_step2 = gi.soundindex ("gek/gk_step2.wav"); ! 1505: sound_step3 = gi.soundindex ("gek/gk_step3.wav"); ! 1506: sound_thud = gi.soundindex ("mutant/thud1.wav"); ! 1507: ! 1508: sound_chantlow = gi.soundindex ("gek/gek_low.wav"); ! 1509: sound_chantmid = gi.soundindex ("gek/gek_mid.wav"); ! 1510: sound_chanthigh = gi.soundindex ("gek/gek_high.wav"); ! 1511: ! 1512: self->movetype = MOVETYPE_STEP; ! 1513: self->solid = SOLID_BBOX; ! 1514: self->s.modelindex = gi.modelindex ("models/monsters/gekk/tris.md2"); ! 1515: VectorSet (self->mins, -24, -24, -24); ! 1516: VectorSet (self->maxs, 24, 24, 24); ! 1517: ! 1518: gi.modelindex ("models/objects/gekkgib/pelvis/tris.md2"); ! 1519: gi.modelindex ("models/objects/gekkgib/arm/tris.md2"); ! 1520: gi.modelindex ("models/objects/gekkgib/torso/tris.md2"); ! 1521: gi.modelindex ("models/objects/gekkgib/claw/tris.md2"); ! 1522: gi.modelindex ("models/objects/gekkgib/leg/tris.md2"); ! 1523: gi.modelindex ("models/objects/gekkgib/head/tris.md2"); ! 1524: ! 1525: self->health = 125; ! 1526: self->gib_health = -30; ! 1527: self->mass = 300; ! 1528: ! 1529: self->pain = gekk_pain; ! 1530: self->die = gekk_die; ! 1531: ! 1532: self->monsterinfo.stand = gekk_stand; ! 1533: ! 1534: self->monsterinfo.walk = gekk_walk; ! 1535: self->monsterinfo.run = gekk_run_start; ! 1536: self->monsterinfo.dodge = gekk_dodge; ! 1537: self->monsterinfo.attack = gekk_jump; ! 1538: self->monsterinfo.melee = gekk_melee; ! 1539: self->monsterinfo.sight = gekk_sight; ! 1540: ! 1541: self->monsterinfo.search = gekk_search; ! 1542: self->monsterinfo.idle = gekk_idle; ! 1543: self->monsterinfo.checkattack = gekk_checkattack; ! 1544: ! 1545: gi.linkentity (self); ! 1546: ! 1547: self->monsterinfo.currentmove = &gekk_move_stand; ! 1548: ! 1549: self->monsterinfo.scale = MODEL_SCALE; ! 1550: walkmonster_start (self); ! 1551: ! 1552: if (self->spawnflags & 8) ! 1553: self->monsterinfo.currentmove = &gekk_move_chant; ! 1554: ! 1555: } ! 1556: ! 1557: ! 1558: void water_to_land (edict_t *self) ! 1559: { ! 1560: self->flags &= ~FL_SWIM; ! 1561: self->yaw_speed = 20; ! 1562: self->viewheight = 25; ! 1563: ! 1564: self->monsterinfo.currentmove = &gekk_move_leapatk2; ! 1565: ! 1566: VectorSet (self->mins, -24, -24, -24); ! 1567: VectorSet (self->maxs, 24, 24, 24); ! 1568: } ! 1569: ! 1570: void land_to_water (edict_t *self) ! 1571: { ! 1572: self->flags |= FL_SWIM; ! 1573: self->yaw_speed = 10; ! 1574: self->viewheight = 10; ! 1575: ! 1576: self->monsterinfo.currentmove = &gekk_move_swim_start; ! 1577: ! 1578: VectorSet (self->mins, -24, -24, -24); ! 1579: VectorSet (self->maxs, 24, 24, 16); ! 1580: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.