ew-progs/ew/monsters/dweller.qc
2011-09-06 00:00:00 +00:00

506 lines
17 KiB
C++

/*
==============================================================================
Dweller
coded by Michael Rogers a.k.a Xsniper
http://xsniper.virtualave.net/
some code done by iD software
==============================================================================
*/
$cd /models/enemies
$origin 0 0 32
$base base
$skin base
$frame idle101 idle102 idle103 idle104 idle105 idle106 idle107 idle108 idle109 idle110
$frame idle111 idle112 idle113 idle114 idle115 idle116
$frame idle201 idle202 idle203 idle204 idle205 idle206 idle207 idle208 idle209 idle210
$frame idle211 idle212 idle213 idle214 idle215 idle216
$frame run01 run02 run03 run04 run05 run06 run07 run08
$frame walk01 walk02 walk03 walk04 walk05 walk06 walk07 walk08 walk09 walk10
$frame walk11 walk12 walk13
$frame attack101 attack102 attack103 attack104 attack105 attack106 attack107 attack108 attack109 attack110
$frame attack111
$frame attack201 attack202 attack203 attack204 attack205 attack206 attack207 attack208
$frame pain101 pain102 pain103 pain104 pain105
$frame pain201 pain202 pain203 pain204 pain205 pain206 pain207
$frame pain301 pain302 pain303 pain304 pain305 pain306 pain307 pain308 pain309 pain310
$frame pain311
$frame death101 death102 death103 death104 death105 death106 death107 death108 death109
$frame death201 death202 death203 death204 death205 death206 death207 death208 death209 death210
$frame death211 death212 death213 death214 death215 death216 death217 death218 death219 death220
$frame death221 death222 death223 death224 death225 death226
$frame death301 death302 death303 death304 death305 death306 death307 death308 death309 death310
$frame death311 death312 death313 death314 death315 death316 death317 death318 death319 death320
$frame death321
float SPAWN_CRUCIFIED = 1;
.float inpain;
void() dweller_charge1;
void() dweller_die;
void() dweller_idlesound;
//=============================================================================
void() DwellerCheckForCharge =
{
// check for mad charge
if (!enemy_vis)
return;
if (time < self.attack_finished)
return;
if ( fabs(self.origin_z - self.enemy.origin_z) > 20)
return; // too much height change
if ( vlen (self.origin - self.enemy.origin) < 80)
return; // use regular attack
// play rage sound and charge in
sound (self, CHAN_VOICE, "enemy/dweller/rage.wav", 1, ATTN_NORM);
SUB_AttackFinished (2);
dweller_charge1 ();
};
//=============================================================================
void() dweller_stand1 =[ $idle101, dweller_stand2 ] {ai_stand();};
void() dweller_stand2 =[ $idle102, dweller_stand3 ] {ai_stand();};
void() dweller_stand3 =[ $idle103, dweller_stand4 ] {ai_stand();};
void() dweller_stand4 =[ $idle104, dweller_stand5 ] {ai_stand();};
void() dweller_stand5 =[ $idle105, dweller_stand6 ] {ai_stand();};
void() dweller_stand6 =[ $idle106, dweller_stand7 ] {ai_stand();};
void() dweller_stand7 =[ $idle107, dweller_stand8 ] {ai_stand();};
void() dweller_stand8 =[ $idle108, dweller_stand9 ] {ai_stand();};
void() dweller_stand9 =[ $idle109, dweller_stand10 ] {ai_stand();};
void() dweller_stand10 =[ $idle110, dweller_stand11 ] {ai_stand();};
void() dweller_stand11 =[ $idle111, dweller_stand12 ] {ai_stand();};
void() dweller_stand12 =[ $idle112, dweller_stand13 ] {ai_stand();};
void() dweller_stand13 =[ $idle113, dweller_stand14 ] {ai_stand();};
void() dweller_stand14 =[ $idle114, dweller_stand15 ] {ai_stand();};
void() dweller_stand15 =[ $idle115, dweller_stand16 ] {ai_stand();};
void() dweller_stand16 =[ $idle116, dweller_stand1 ] {ai_stand();};
//=============================================================================
void() dweller_walk1 =[ $walk01, dweller_walk2 ] {ai_walk(3);};
void() dweller_walk2 =[ $walk02, dweller_walk3 ] {ai_walk(2);};
void() dweller_walk3 =[ $walk03, dweller_walk4 ] {ai_walk(3);};
void() dweller_walk4 =[ $walk04, dweller_walk5 ] {ai_walk(2);};
void() dweller_walk5 =[ $walk05, dweller_walk6 ] {ai_walk(2);};
void() dweller_walk6 =[ $walk06, dweller_walk7 ] {ai_walk(3);};
void() dweller_walk7 =[ $walk07, dweller_walk8 ] {ai_walk(3);};
void() dweller_walk8 =[ $walk08, dweller_walk9 ] {ai_walk(2);};
void() dweller_walk9 =[ $walk09, dweller_walk10 ] {ai_walk(2);};
void() dweller_walk10 =[ $walk10, dweller_walk11 ] {ai_walk(1);};
void() dweller_walk11 =[ $walk11, dweller_walk12 ] {ai_walk(2);};
void() dweller_walk12 =[ $walk12, dweller_walk13 ] {ai_walk(3);};
void() dweller_walk13 =[ $walk13, dweller_walk1 ] {ai_walk(2);dweller_idlesound();};
//=============================================================================
void() dweller_run1 =[ $run01, dweller_run2 ]
{
ai_run(15);
self.inpain = 0;
DwellerCheckForCharge();
};
void() dweller_run2 =[ $run02, dweller_run3 ] {ai_run(10);};
void() dweller_run3 =[ $run03, dweller_run4 ] {ai_run(12);};
void() dweller_run4 =[ $run04, dweller_run5 ] {ai_run(14);};
void() dweller_run5 =[ $run05, dweller_run6 ] {ai_run(15);};
void() dweller_run6 =[ $run06, dweller_run7 ] {ai_run(14);};
void() dweller_run7 =[ $run07, dweller_run8 ] {ai_run(11);};
void() dweller_run8 =[ $run08, dweller_run1 ] {ai_run(16);dweller_idlesound();};
//=============================================================================
void() dweller_charge1 =[ $run01, dweller_charge2 ] {ai_charge(20);};
void() dweller_charge2 =[ $run02, dweller_charge3 ] {ai_charge(18);};
void() dweller_charge3 =[ $run03, dweller_charge4 ] {ai_charge(15);};
void() dweller_charge4 =[ $run04, dweller_charge5 ] {ai_charge(22);};
void() dweller_charge5 =[ $run05, dweller_charge6 ] {ai_charge(13);};
void() dweller_charge6 =[ $run06, dweller_charge7 ] {ai_charge(20);};
void() dweller_charge7 =[ $run07, dweller_charge8 ] {ai_charge(19);};
void() dweller_charge8 =[ $run08, dweller_run1 ] {ai_charge(21);};
//=============================================================================
void() dweller_atta1 =[ $attack101, dweller_atta2 ] {ai_charge(20);};
void() dweller_atta2 =[ $attack102, dweller_atta3 ] {ai_charge(22);};
void() dweller_atta3 =[ $attack103, dweller_atta4 ] {ai_charge(26);};
void() dweller_atta4 =[ $attack104, dweller_atta5 ] {ai_charge(20);ai_melee();};
void() dweller_atta5 =[ $attack105, dweller_atta6 ] {ai_charge(21);ai_melee();};
void() dweller_atta6 =[ $attack106, dweller_atta7 ] {ai_charge(24);ai_melee();};
void() dweller_atta7 =[ $attack107, dweller_atta8 ] {ai_charge(23);ai_melee();};
void() dweller_atta8 =[ $attack108, dweller_atta9 ] {ai_charge(22);ai_melee();};
void() dweller_atta9 =[ $attack109, dweller_atta10 ] {ai_face();};
void() dweller_atta10 =[ $attack110, dweller_atta11 ] {ai_face();};
void() dweller_atta11 =[ $attack111, dweller_run1 ] {ai_face();};
//=============================================================================
void() dweller_attb1 =[ $attack201, dweller_attb2 ] {ai_charge(29);};
void() dweller_attb2 =[ $attack202, dweller_attb3 ] {ai_charge(22);};
void() dweller_attb3 =[ $attack203, dweller_attb4 ] {ai_charge(21);ai_melee();};
void() dweller_attb4 =[ $attack204, dweller_attb5 ] {ai_charge(26);ai_melee();};
void() dweller_attb5 =[ $attack205, dweller_attb6 ] {ai_charge(24);ai_melee();};
void() dweller_attb6 =[ $attack206, dweller_attb7 ] {ai_charge(25);ai_melee();};
void() dweller_attb7 =[ $attack207, dweller_attb8 ] {ai_face();};
void() dweller_attb8 =[ $attack208, dweller_run1 ] {ai_face();};
//=============================================================================
/*
=============================================================================
PAIN
=============================================================================
*/
void() dweller_paina1 =[ $pain101, dweller_paina2 ] {};
void() dweller_paina2 =[ $pain102, dweller_paina3 ] {ai_painforward(3);};
void() dweller_paina3 =[ $pain103, dweller_paina4 ] {ai_painforward(1);};
void() dweller_paina4 =[ $pain104, dweller_paina5 ] {ai_pain(1);};
void() dweller_paina5 =[ $pain105, dweller_run1 ] {ai_pain(3);};
//=============================================================================
void() dweller_painb1 =[ $pain201, dweller_painb2 ] {};
void() dweller_painb2 =[ $pain202, dweller_painb3 ] {ai_pain(2);};
void() dweller_painb3 =[ $pain203, dweller_painb4 ] {ai_pain(8);};
void() dweller_painb4 =[ $pain204, dweller_painb5 ] {ai_pain(6);};
void() dweller_painb5 =[ $pain205, dweller_painb6 ] {ai_pain(2);};
void() dweller_painb6 =[ $pain206, dweller_painb7 ] {ai_pain(2);};
void() dweller_painb7 =[ $pain207, dweller_run1 ] {};
//=============================================================================
void() dweller_painc1 =[ $pain301, dweller_painc2 ] {};
void() dweller_painc2 =[ $pain302, dweller_painc3 ] {};
void() dweller_painc3 =[ $pain303, dweller_painc4 ] {ai_pain(3);};
void() dweller_painc4 =[ $pain304, dweller_painc5 ] {ai_pain(1);};
void() dweller_painc5 =[ $pain305, dweller_painc6 ] {};
void() dweller_painc6 =[ $pain306, dweller_painc7 ] {};
void() dweller_painc7 =[ $pain307, dweller_painc8 ] {};
void() dweller_painc8 =[ $pain308, dweller_painc9 ] {};
void() dweller_painc9 =[ $pain309, dweller_painc10 ] {};
void() dweller_painc10 =[ $pain310, dweller_painc11 ] {};
void() dweller_painc11 =[ $pain311, dweller_run1 ] {};
//=============================================================================
void() dweller_paine1 =[ $death101, dweller_paine2 ] {self.health = 60;};
void() dweller_paine2 =[ $death102, dweller_paine3 ] {ai_pain(8);};
void() dweller_paine3 =[ $death103, dweller_paine4 ] {ai_pain(5);};
void() dweller_paine4 =[ $death104, dweller_paine5 ] {ai_pain(3);};
void() dweller_paine5 =[ $death105, dweller_paine6 ] {ai_pain(1);};
void() dweller_paine6 =[ $death106, dweller_paine7 ] {ai_pain(2);};
void() dweller_paine7 =[ $death107, dweller_paine8 ] {ai_pain(1);};
void() dweller_paine8 =[ $death108, dweller_paine9 ] {ai_pain(1);};
void() dweller_paine9 =[ $death109, dweller_paine10 ] {self.solid = SOLID_NOT;};
void() dweller_paine10 =[ $death109, dweller_paine11 ]
{
self.nextthink = self.nextthink + 5;
self.health = 60;
};
void() dweller_paine11 =[ $death109, dweller_paine12 ]
{
// see if ok to stand up
self.health = 60;
self.solid = SOLID_SLIDEBOX;
if (!walkmove (0, 0))
{
self.health = -60;
return;
}
else if (random() <= 0.5)
{
//random chance of dieing anyway
//self.think = dweller_die;
//self.solid = SOLID_NOT;
self.health = -60;
return;
}
};
void() dweller_paine12 =[ $death108, dweller_paine13 ] {};
void() dweller_paine13 =[ $death107, dweller_paine14 ] {};
void() dweller_paine14 =[ $death106, dweller_paine15 ] {};
void() dweller_paine15 =[ $death105, dweller_paine16 ] {};
void() dweller_paine16 =[ $death104, dweller_paine17 ] {};
void() dweller_paine17 =[ $death103, dweller_paine18 ] {};
void() dweller_paine18 =[ $death102, dweller_paine19 ] {};
void() dweller_paine19 =[ $death101, dweller_run1 ] {};
/*
=================
dweller_pain
Dwellers can only be killed (gibbed) by doing 60 hit points of damage
in a single frame (rockets, grenades, quad shotgun, quad nailgun).
A hit of 25 points or more (super shotgun, quad nailgun) will allways put it
down to the ground.
A hit of from 10 to 40 points in one frame will cause it to go down if it
has been twice in two seconds, otherwise it goes into one of the four
fast pain frames.
A hit of less than 10 points of damage (winged by a shotgun) will be ignored.
FIXME: don't use pain_finished because of nightmare hack
=================
*/
void(entity attacker, float take) dweller_pain =
{
local float r;
self.health = set_health(60); // allways reset health
if (take < 9)
return; // totally ignore
if (self.inpain == 2)
return; // down on ground, so don't reset any counters
//pick a pain sound at random
r = random();
if (r <= 0.3)
sound (self, CHAN_VOICE, "enemy/dweller/pain1.wav", 1, ATTN_NORM);
else if(r <= 0.6)
sound (self, CHAN_VOICE, "enemy/dweller/pain2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "enemy/dweller/pain3.wav", 1, ATTN_NORM);
// go down immediately if a big enough hit
if (take >= 25)
{
self.inpain = 2;
dweller_paine1 ();
return;
}
if (self.inpain)
{
// if hit again in next gre seconds while not in pain frames, definately drop
self.pain_finished = time + 3;
return; // currently going through an animation, don't change
}
if (self.pain_finished > time)
{
// hit again, so drop down
self.inpain = 2;
dweller_paine1 ();
return;
}
// go into one of the fast pain animations
self.inpain = 1;
r = random();
if (r < 0.35)
dweller_paina1 ();
else if (r < 0.65)
dweller_painb1 ();
else
dweller_painc1 ();
};
//=============================================================================
void() dweller_die =
{
//this seems important
self.solid = SOLID_NOT;
//lets do some damage here
T_RadiusDamage (self, self, 65, world);
self.origin = self.origin - 8*normalize(self.velocity);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_TAREXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};
//=============================================================================
void() dweller_idlesound =
{
if (random() <= 0.2)
{
if (random() <= 0.5)
sound (self, CHAN_VOICE, "enemy/dweller/alert1.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "enemy/dweller/attack1.wav", 1, ATTN_NORM);
}
};
void() dweller_melee =
{
local float r;
r = random();
//play attack sound
sound (self, CHAN_VOICE, "enemy/dweller/miss.wav", 1, ATTN_NORM);
if (r > 0.5)
dweller_atta1 ();
else if (r < 0.5)
dweller_attb1 ();
};
//============================================================================
/*QUAKED monster_dweller (1 0 0) (-16 -16 -24) (16 16 32) Crucified ambush
If crucified, stick the bounding box 12 pixels back into a wall to look right.
*/
void() monster_dweller =
{
local float r;
if (deathmatch)
{
remove(self);
return;
}
if (self.spawnflags & SPAWN_CRUCIFIED)
{
remove(self);
return;
}
precache_model ("models/enemies/dweller.md2");
precache_sound ("enemy/dweller/alert1.wav");
precache_sound ("enemy/dweller/attack1.wav");
precache_sound ("enemy/dweller/miss.wav");
precache_sound ("enemy/dweller/pain1.wav");
precache_sound ("enemy/dweller/pain2.wav");
precache_sound ("enemy/dweller/pain3.wav");
precache_sound ("enemy/dweller/rage.wav");
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
setmodel (self, "models/enemies/dweller.md2");
setsize (self, '-16 -16 -24', '16 16 32');
// setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
self.health = set_health(60);
self.speed = set_speed(600);
self.dtype = 4; //dodge type do nothing
self.th_stand = dweller_stand1;
self.th_walk = dweller_walk1;
self.th_run = dweller_run1;
self.th_pain = dweller_pain;
self.th_die = dweller_die;
self.th_melee = dweller_melee;
//pick a random skin
r = random();
if (r <= 0.25)
self.skin = 0;
else if (r <= 0.5)
self.skin = 1;
else if (r <= 0.75)
self.skin = 2;
else
self.skin = 3;
//my new classname is?
self.classname = "monster_dweller";
//set up our monflag
self.monflag = "TRUE";
walkmonster_start();
};
/*
=================
create_dwellerbot
Creates a Dweller at the specified 'spot'.
This is mostly used for the Necromancer's summoning ability.
=================
*/
void(vector spot) create_dwellerbot =
{
local entity bot;
local float r;
// start entity and place it in world
bot = spawn();
bot.angles = self.angles;
setorigin (bot, spot);
bot.fixangle = TRUE;
spawn_tfog (bot.origin);
spawn_tdeath (bot.origin, bot);
// set size and shape
bot.solid = SOLID_SLIDEBOX;
bot.movetype = MOVETYPE_STEP;
setmodel (bot, "models/enemies/dweller.md2");
setsize (bot, '-16 -16 -24', '16 16 32');
bot.flags = bot.flags | FL_MONSTER;
bot.takedamage = DAMAGE_AIM;
// define his animation
bot.th_stand = dweller_stand1;
bot.th_walk = dweller_walk1;
bot.th_run = dweller_run1;
bot.th_die = dweller_die;
bot.th_melee = dweller_melee;
bot.th_pain = dweller_pain;
bot.health = set_health(60);
bot.speed = set_speed(600);
bot.dtype = 4; //dodge type do nothing
// polish him up
bot.classname = "monster_dweller";
bot.ideal_yaw = bot.angles * '0 1 0';
bot.yaw_speed = 120;
bot.view_ofs = '0 0 22';
//set up our monflag
bot.monflag = "TRUE";
//pick a random skin
r = random();
if (r <= 0.25)
bot.skin = 0;
else if (r <= 0.5)
bot.skin = 1;
else if (r <= 0.75)
bot.skin = 2;
else
bot.skin = 3;
// begin his thinking
bot.nextthink = time + 0.1 + random();
bot.think = th_stuck;
};