m_parasite.c (13757B)
1 /* 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 /* 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 }