File: game\m_parasite.c

    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 = &parasite_move_end_fidget;
  122 }
  123 
  124 void parasite_do_fidget (edict_t *self)
  125 {
  126         self->monsterinfo.currentmove = &parasite_move_fidget;
  127 }
  128 
  129 void parasite_refidget (edict_t *self)
  130 { 
  131         if (random() <= 0.8)
  132                 self->monsterinfo.currentmove = &parasite_move_fidget;
  133         else
  134                 self->monsterinfo.currentmove = &parasite_move_end_fidget;
  135 }
  136 
  137 void parasite_idle (edict_t *self)
  138 { 
  139         self->monsterinfo.currentmove = &parasite_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 = &parasite_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 = &parasite_move_stand;
  205         else
  206                 self->monsterinfo.currentmove = &parasite_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 = &parasite_move_stand;
  213         else
  214                 self->monsterinfo.currentmove = &parasite_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 = &parasite_move_start_walk;
  251 }
  252 
  253 void parasite_walk (edict_t *self)
  254 {
  255         self->monsterinfo.currentmove = &parasite_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 = &parasite_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 = &parasite_move_break;
  437 //      else
  438                 self->monsterinfo.currentmove = &parasite_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 = &parasite_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 = &parasite_move_stand;   
  549         self->monsterinfo.scale = MODEL_SCALE;
  550 
  551         walkmonster_start (self);
  552 }
  553