Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

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 = &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 }