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