|
|
1.1 ! root 1: /* ! 2: ============================================================================== ! 3: ! 4: parasite ! 5: ! 6: ============================================================================== ! 7: */ ! 8: ! 9: #include "g_local.h" ! 10: #include "m_parasite.h" ! 11: ! 12: ! 13: static int sound_pain1; ! 14: static int sound_pain2; ! 15: static int sound_die; ! 16: static int sound_launch; ! 17: static int sound_impact; ! 18: static int sound_suck; ! 19: static int sound_reelin; ! 20: static int sound_sight; ! 21: static int sound_tap; ! 22: static int sound_scratch; ! 23: static int sound_search; ! 24: ! 25: ! 26: void parasite_stand (edict_t *self); ! 27: void parasite_start_run (edict_t *self); ! 28: void parasite_run (edict_t *self); ! 29: void parasite_walk (edict_t *self); ! 30: void parasite_start_walk (edict_t *self); ! 31: void parasite_end_fidget (edict_t *self); ! 32: void parasite_do_fidget (edict_t *self); ! 33: void parasite_refidget (edict_t *self); ! 34: ! 35: ! 36: void parasite_launch (edict_t *self) ! 37: { ! 38: gi.sound (self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0); ! 39: } ! 40: ! 41: void parasite_reel_in (edict_t *self) ! 42: { ! 43: gi.sound (self, CHAN_WEAPON, sound_reelin, 1, ATTN_NORM, 0); ! 44: } ! 45: ! 46: void parasite_sight (edict_t *self, edict_t *other) ! 47: { ! 48: gi.sound (self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0); ! 49: } ! 50: ! 51: void parasite_tap (edict_t *self) ! 52: { ! 53: gi.sound (self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0); ! 54: } ! 55: ! 56: void parasite_scratch (edict_t *self) ! 57: { ! 58: gi.sound (self, CHAN_WEAPON, sound_scratch, 1, ATTN_IDLE, 0); ! 59: } ! 60: ! 61: void parasite_search (edict_t *self) ! 62: { ! 63: gi.sound (self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0); ! 64: } ! 65: ! 66: ! 67: mframe_t parasite_frames_start_fidget [] = ! 68: { ! 69: ai_stand, 0, NULL, ! 70: ai_stand, 0, NULL, ! 71: ai_stand, 0, NULL, ! 72: ai_stand, 0, NULL ! 73: }; ! 74: mmove_t parasite_move_start_fidget = {FRAME_stand18, FRAME_stand21, parasite_frames_start_fidget, parasite_do_fidget}; ! 75: ! 76: mframe_t parasite_frames_fidget [] = ! 77: { ! 78: ai_stand, 0, parasite_scratch, ! 79: ai_stand, 0, NULL, ! 80: ai_stand, 0, NULL, ! 81: ai_stand, 0, parasite_scratch, ! 82: ai_stand, 0, NULL, ! 83: ai_stand, 0, NULL ! 84: }; ! 85: mmove_t parasite_move_fidget = {FRAME_stand22, FRAME_stand27, parasite_frames_fidget, parasite_refidget}; ! 86: ! 87: mframe_t parasite_frames_end_fidget [] = ! 88: { ! 89: ai_stand, 0, parasite_scratch, ! 90: ai_stand, 0, NULL, ! 91: ai_stand, 0, NULL, ! 92: ai_stand, 0, NULL, ! 93: ai_stand, 0, NULL, ! 94: ai_stand, 0, NULL, ! 95: ai_stand, 0, NULL, ! 96: ai_stand, 0, NULL ! 97: }; ! 98: mmove_t parasite_move_end_fidget = {FRAME_stand28, FRAME_stand35, parasite_frames_end_fidget, parasite_stand}; ! 99: ! 100: void parasite_end_fidget (edict_t *self) ! 101: { ! 102: self->monsterinfo.currentmove = ¶site_move_end_fidget; ! 103: } ! 104: ! 105: void parasite_do_fidget (edict_t *self) ! 106: { ! 107: self->monsterinfo.currentmove = ¶site_move_fidget; ! 108: } ! 109: ! 110: void parasite_refidget (edict_t *self) ! 111: { ! 112: if (random() <= 0.8) ! 113: self->monsterinfo.currentmove = ¶site_move_fidget; ! 114: else ! 115: self->monsterinfo.currentmove = ¶site_move_end_fidget; ! 116: } ! 117: ! 118: void parasite_idle (edict_t *self) ! 119: { ! 120: self->monsterinfo.currentmove = ¶site_move_start_fidget; ! 121: } ! 122: ! 123: ! 124: mframe_t parasite_frames_stand [] = ! 125: { ! 126: ai_stand, 0, NULL, ! 127: ai_stand, 0, NULL, ! 128: ai_stand, 0, parasite_tap, ! 129: ai_stand, 0, NULL, ! 130: ai_stand, 0, parasite_tap, ! 131: ai_stand, 0, NULL, ! 132: ai_stand, 0, NULL, ! 133: ai_stand, 0, NULL, ! 134: ai_stand, 0, parasite_tap, ! 135: ai_stand, 0, NULL, ! 136: ai_stand, 0, parasite_tap, ! 137: ai_stand, 0, NULL, ! 138: ai_stand, 0, NULL, ! 139: ai_stand, 0, NULL, ! 140: ai_stand, 0, parasite_tap, ! 141: ai_stand, 0, NULL, ! 142: ai_stand, 0, parasite_tap ! 143: }; ! 144: mmove_t parasite_move_stand = {FRAME_stand01, FRAME_stand17, parasite_frames_stand, parasite_stand}; ! 145: ! 146: void parasite_stand (edict_t *self) ! 147: { ! 148: self->monsterinfo.currentmove = ¶site_move_stand; ! 149: } ! 150: ! 151: ! 152: mframe_t parasite_frames_run [] = ! 153: { ! 154: ai_run, 30, NULL, ! 155: ai_run, 30, NULL, ! 156: ai_run, 22, NULL, ! 157: ai_run, 19, NULL, ! 158: ai_run, 24, NULL, ! 159: ai_run, 28, NULL, ! 160: ai_run, 25, NULL ! 161: }; ! 162: mmove_t parasite_move_run = {FRAME_run03, FRAME_run09, parasite_frames_run, NULL}; ! 163: ! 164: mframe_t parasite_frames_start_run [] = ! 165: { ! 166: ai_run, 0, NULL, ! 167: ai_run, 30, NULL, ! 168: }; ! 169: mmove_t parasite_move_start_run = {FRAME_run01, FRAME_run02, parasite_frames_start_run, parasite_run}; ! 170: ! 171: mframe_t parasite_frames_stop_run [] = ! 172: { ! 173: ai_run, 20, NULL, ! 174: ai_run, 20, NULL, ! 175: ai_run, 12, NULL, ! 176: ai_run, 10, NULL, ! 177: ai_run, 0, NULL, ! 178: ai_run, 0, NULL ! 179: }; ! 180: mmove_t parasite_move_stop_run = {FRAME_run10, FRAME_run15, parasite_frames_stop_run, NULL}; ! 181: ! 182: void parasite_start_run (edict_t *self) ! 183: { ! 184: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 185: self->monsterinfo.currentmove = ¶site_move_stand; ! 186: else ! 187: self->monsterinfo.currentmove = ¶site_move_start_run; ! 188: } ! 189: ! 190: void parasite_run (edict_t *self) ! 191: { ! 192: if (self->monsterinfo.aiflags & AI_STAND_GROUND) ! 193: self->monsterinfo.currentmove = ¶site_move_stand; ! 194: else ! 195: self->monsterinfo.currentmove = ¶site_move_run; ! 196: } ! 197: ! 198: ! 199: mframe_t parasite_frames_walk [] = ! 200: { ! 201: ai_walk, 30, NULL, ! 202: ai_walk, 30, NULL, ! 203: ai_walk, 22, NULL, ! 204: ai_walk, 19, NULL, ! 205: ai_walk, 24, NULL, ! 206: ai_walk, 28, NULL, ! 207: ai_walk, 25, NULL ! 208: }; ! 209: mmove_t parasite_move_walk = {FRAME_run03, FRAME_run09, parasite_frames_walk, parasite_walk}; ! 210: ! 211: mframe_t parasite_frames_start_walk [] = ! 212: { ! 213: ai_walk, 0, NULL, ! 214: ai_walk, 30, parasite_walk ! 215: }; ! 216: mmove_t parasite_move_start_walk = {FRAME_run01, FRAME_run02, parasite_frames_start_walk, NULL}; ! 217: ! 218: mframe_t parasite_frames_stop_walk [] = ! 219: { ! 220: ai_walk, 20, NULL, ! 221: ai_walk, 20, NULL, ! 222: ai_walk, 12, NULL, ! 223: ai_walk, 10, NULL, ! 224: ai_walk, 0, NULL, ! 225: ai_walk, 0, NULL ! 226: }; ! 227: mmove_t parasite_move_stop_walk = {FRAME_run10, FRAME_run15, parasite_frames_stop_walk, NULL}; ! 228: ! 229: void parasite_start_walk (edict_t *self) ! 230: { ! 231: self->monsterinfo.currentmove = ¶site_move_start_walk; ! 232: } ! 233: ! 234: void parasite_walk (edict_t *self) ! 235: { ! 236: self->monsterinfo.currentmove = ¶site_move_walk; ! 237: } ! 238: ! 239: ! 240: mframe_t parasite_frames_pain1 [] = ! 241: { ! 242: ai_move, 0, NULL, ! 243: ai_move, 0, NULL, ! 244: ai_move, 0, NULL, ! 245: ai_move, 0, NULL, ! 246: ai_move, 0, NULL, ! 247: ai_move, 0, NULL, ! 248: ai_move, 6, NULL, ! 249: ai_move, 16, NULL, ! 250: ai_move, -6, NULL, ! 251: ai_move, -7, NULL, ! 252: ai_move, 0, NULL ! 253: }; ! 254: mmove_t parasite_move_pain1 = {FRAME_pain101, FRAME_pain111, parasite_frames_pain1, parasite_start_run}; ! 255: ! 256: void parasite_pain (edict_t *self, edict_t *other, float kick, int damage) ! 257: { ! 258: if (self->health < (self->max_health / 2)) ! 259: self->s.skinnum = 1; ! 260: ! 261: if (level.time < self->pain_debounce_time) ! 262: return; ! 263: ! 264: self->pain_debounce_time = level.time + 3; ! 265: ! 266: if (skill->value == 3) ! 267: return; // no pain anims in nightmare ! 268: ! 269: if (random() < 0.5) ! 270: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); ! 271: else ! 272: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); ! 273: ! 274: self->monsterinfo.currentmove = ¶site_move_pain1; ! 275: } ! 276: ! 277: ! 278: static qboolean parasite_drain_attack_ok (vec3_t start, vec3_t end) ! 279: { ! 280: vec3_t dir, angles; ! 281: ! 282: // check for max distance ! 283: VectorSubtract (start, end, dir); ! 284: if (VectorLength(dir) > 256) ! 285: return false; ! 286: ! 287: // check for min/max pitch ! 288: vectoangles (dir, angles); ! 289: if (angles[0] < -180) ! 290: angles[0] += 360; ! 291: if (fabs(angles[0]) > 30) ! 292: return false; ! 293: ! 294: return true; ! 295: } ! 296: ! 297: void parasite_drain_attack (edict_t *self) ! 298: { ! 299: vec3_t offset, start, f, r, end, dir; ! 300: trace_t tr; ! 301: int damage; ! 302: ! 303: AngleVectors (self->s.angles, f, r, NULL); ! 304: VectorSet (offset, 24, 0, 6); ! 305: G_ProjectSource (self->s.origin, offset, f, r, start); ! 306: ! 307: VectorCopy (self->enemy->s.origin, end); ! 308: if (!parasite_drain_attack_ok(start, end)) ! 309: { ! 310: end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; ! 311: if (!parasite_drain_attack_ok(start, end)) ! 312: { ! 313: end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; ! 314: if (!parasite_drain_attack_ok(start, end)) ! 315: return; ! 316: } ! 317: } ! 318: VectorCopy (self->enemy->s.origin, end); ! 319: ! 320: tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); ! 321: if (tr.ent != self->enemy) ! 322: return; ! 323: ! 324: if (self->s.frame == FRAME_drain03) ! 325: { ! 326: damage = 5; ! 327: gi.sound (self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0); ! 328: } ! 329: else ! 330: { ! 331: if (self->s.frame == FRAME_drain04) ! 332: gi.sound (self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0); ! 333: damage = 2; ! 334: } ! 335: ! 336: gi.WriteByte (svc_temp_entity); ! 337: gi.WriteByte (TE_PARASITE_ATTACK); ! 338: gi.WriteShort (self - g_edicts); ! 339: gi.WritePosition (start); ! 340: gi.WritePosition (end); ! 341: gi.multicast (self->s.origin, MULTICAST_PVS); ! 342: ! 343: VectorSubtract (start, end, dir); ! 344: T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); ! 345: } ! 346: ! 347: mframe_t parasite_frames_drain [] = ! 348: { ! 349: ai_charge, 0, parasite_launch, ! 350: ai_charge, 0, NULL, ! 351: ai_charge, 15, parasite_drain_attack, // Target hits ! 352: ai_charge, 0, parasite_drain_attack, // drain ! 353: ai_charge, 0, parasite_drain_attack, // drain ! 354: ai_charge, 0, parasite_drain_attack, // drain ! 355: ai_charge, 0, parasite_drain_attack, // drain ! 356: ai_charge, -2, parasite_drain_attack, // drain ! 357: ai_charge, -2, parasite_drain_attack, // drain ! 358: ai_charge, -3, parasite_drain_attack, // drain ! 359: ai_charge, -2, parasite_drain_attack, // drain ! 360: ai_charge, 0, parasite_drain_attack, // drain ! 361: ai_charge, -1, parasite_drain_attack, // drain ! 362: ai_charge, 0, parasite_reel_in, // let go ! 363: ai_charge, -2, NULL, ! 364: ai_charge, -2, NULL, ! 365: ai_charge, -3, NULL, ! 366: ai_charge, 0, NULL ! 367: }; ! 368: mmove_t parasite_move_drain = {FRAME_drain01, FRAME_drain18, parasite_frames_drain, parasite_start_run}; ! 369: ! 370: ! 371: mframe_t parasite_frames_break [] = ! 372: { ! 373: ai_charge, 0, NULL, ! 374: ai_charge, -3, NULL, ! 375: ai_charge, 1, NULL, ! 376: ai_charge, 2, NULL, ! 377: ai_charge, -3, NULL, ! 378: ai_charge, 1, NULL, ! 379: ai_charge, 1, NULL, ! 380: ai_charge, 3, NULL, ! 381: ai_charge, 0, NULL, ! 382: ai_charge, -18, NULL, ! 383: ai_charge, 3, NULL, ! 384: ai_charge, 9, NULL, ! 385: ai_charge, 6, NULL, ! 386: ai_charge, 0, NULL, ! 387: ai_charge, -18, NULL, ! 388: ai_charge, 0, NULL, ! 389: ai_charge, 8, NULL, ! 390: ai_charge, 9, NULL, ! 391: ai_charge, 0, NULL, ! 392: ai_charge, -18, NULL, ! 393: ai_charge, 0, NULL, ! 394: ai_charge, 0, NULL, // airborne ! 395: ai_charge, 0, NULL, // airborne ! 396: ai_charge, 0, NULL, // slides ! 397: ai_charge, 0, NULL, // slides ! 398: ai_charge, 0, NULL, // slides ! 399: ai_charge, 0, NULL, // slides ! 400: ai_charge, 4, NULL, ! 401: ai_charge, 11, NULL, ! 402: ai_charge, -2, NULL, ! 403: ai_charge, -5, NULL, ! 404: ai_charge, 1, NULL ! 405: }; ! 406: mmove_t parasite_move_break = {FRAME_break01, FRAME_break32, parasite_frames_break, parasite_start_run}; ! 407: ! 408: /* ! 409: === ! 410: Break Stuff Ends ! 411: === ! 412: */ ! 413: ! 414: void parasite_attack (edict_t *self) ! 415: { ! 416: // if (random() <= 0.2) ! 417: // self->monsterinfo.currentmove = ¶site_move_break; ! 418: // else ! 419: self->monsterinfo.currentmove = ¶site_move_drain; ! 420: } ! 421: ! 422: ! 423: ! 424: /* ! 425: === ! 426: Death Stuff Starts ! 427: === ! 428: */ ! 429: ! 430: void parasite_dead (edict_t *self) ! 431: { ! 432: VectorSet (self->mins, -16, -16, -24); ! 433: VectorSet (self->maxs, 16, 16, -8); ! 434: self->movetype = MOVETYPE_TOSS; ! 435: self->svflags |= SVF_DEADMONSTER; ! 436: self->nextthink = 0; ! 437: gi.linkentity (self); ! 438: } ! 439: ! 440: mframe_t parasite_frames_death [] = ! 441: { ! 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: ai_move, 0, NULL, ! 448: ai_move, 0, NULL ! 449: }; ! 450: mmove_t parasite_move_death = {FRAME_death101, FRAME_death107, parasite_frames_death, parasite_dead}; ! 451: ! 452: void parasite_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) ! 453: { ! 454: int n; ! 455: ! 456: // check for gib ! 457: if (self->health <= self->gib_health) ! 458: { ! 459: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); ! 460: for (n= 0; n < 2; n++) ! 461: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); ! 462: for (n= 0; n < 4; n++) ! 463: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ! 464: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); ! 465: self->deadflag = DEAD_DEAD; ! 466: return; ! 467: } ! 468: ! 469: if (self->deadflag == DEAD_DEAD) ! 470: return; ! 471: ! 472: // regular death ! 473: gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); ! 474: self->deadflag = DEAD_DEAD; ! 475: self->takedamage = DAMAGE_YES; ! 476: self->monsterinfo.currentmove = ¶site_move_death; ! 477: } ! 478: ! 479: /* ! 480: === ! 481: End Death Stuff ! 482: === ! 483: */ ! 484: ! 485: /*QUAKED monster_parasite (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight ! 486: */ ! 487: void SP_monster_parasite (edict_t *self) ! 488: { ! 489: if (deathmatch->value) ! 490: { ! 491: G_FreeEdict (self); ! 492: return; ! 493: } ! 494: ! 495: sound_pain1 = gi.soundindex ("parasite/parpain1.wav"); ! 496: sound_pain2 = gi.soundindex ("parasite/parpain2.wav"); ! 497: sound_die = gi.soundindex ("parasite/pardeth1.wav"); ! 498: sound_launch = gi.soundindex("parasite/paratck1.wav"); ! 499: sound_impact = gi.soundindex("parasite/paratck2.wav"); ! 500: sound_suck = gi.soundindex("parasite/paratck3.wav"); ! 501: sound_reelin = gi.soundindex("parasite/paratck4.wav"); ! 502: sound_sight = gi.soundindex("parasite/parsght1.wav"); ! 503: sound_tap = gi.soundindex("parasite/paridle1.wav"); ! 504: sound_scratch = gi.soundindex("parasite/paridle2.wav"); ! 505: sound_search = gi.soundindex("parasite/parsrch1.wav"); ! 506: ! 507: self->s.modelindex = gi.modelindex ("models/monsters/parasite/tris.md2"); ! 508: VectorSet (self->mins, -16, -16, -24); ! 509: VectorSet (self->maxs, 16, 16, 24); ! 510: self->movetype = MOVETYPE_STEP; ! 511: self->solid = SOLID_BBOX; ! 512: ! 513: self->health = 175; ! 514: self->gib_health = -50; ! 515: self->mass = 250; ! 516: ! 517: self->pain = parasite_pain; ! 518: self->die = parasite_die; ! 519: ! 520: self->monsterinfo.stand = parasite_stand; ! 521: self->monsterinfo.walk = parasite_start_walk; ! 522: self->monsterinfo.run = parasite_start_run; ! 523: self->monsterinfo.attack = parasite_attack; ! 524: self->monsterinfo.sight = parasite_sight; ! 525: self->monsterinfo.idle = parasite_idle; ! 526: ! 527: gi.linkentity (self); ! 528: ! 529: self->monsterinfo.currentmove = ¶site_move_stand; ! 530: self->monsterinfo.scale = MODEL_SCALE; ! 531: ! 532: walkmonster_start (self); ! 533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.