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

459 lines
14 KiB
C++

/*
==============================================================================
Torment
coded by Michael Rogers a.k.a Xsniper
http://xsniper.virtualave.net/
some code done by iD software
==============================================================================
*/
$cd /models/enemies
$origin 0 0 24
$base base
$skin base
$frame idle101 idle102 idle103 idle104 idle105 idle106 idle107
$frame idle201 idle202 idle203 idle204 idle205 idle206 idle207 idle208 idle209 idle210
$frame idle211 idle212 idle213 idle214 idle215 idle216 idle217 idle218 idle219 idle220
$frame idle301 idle302 idle303 idle304 idle305 idle306
$frame run01 run02 run03 run04 run05 run06 run07 run08
$frame walk01 walk02 walk03 walk04 walk05 walk06 walk07 walk08 walk09 walk10
$frame walk11 walk12
$frame attack101 attack102 attack103 attack104 attack105 attack106 attack107 attack108 attack109
$frame attack201 attack202 attack203 attack204 attack205 attack206 attack207 attack208
$frame pain101 pain102 pain103 pain104
$frame pain201 pain202 pain203 pain204 pain205 pain206
$frame pain301 pain302 pain303 pain304 pain305
$frame death101 death102 death103 death104 death105 death106 death107
void() torment_char_a1;
void() torment_run1;
void() TormentCheckForCharge =
{
// 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
// charge
SUB_AttackFinished (2);
torment_char_a1 ();
};
void() TormentCheckContinueCharge =
{
if (time > self.attack_finished)
{
SUB_AttackFinished (3);
torment_run1 ();
return; // done charging
}
sound (self, CHAN_WEAPON, "enemy/torment/miss.wav", 1, ATTN_NORM);
};
void() HellStaffExplode =
{
T_RadiusDamage (self, self.owner, 30, world);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion();
};
void() HellStaffTouch =
{
if (other == self.owner)
return; // don't explode on owner
if (other.takedamage == DAMAGE_AIM)
{
//set everything but the world on fire
if (other != world && random() <= 0.2)
{
other.onfire = 1;
other.burningtime = time + 2 + random() * 2;
other.burninflictor = self.owner;
}
//lets explode now
HellStaffExplode();
return;
}
sound (self, CHAN_VOICE, "weapons/demon/firehit.wav", 1, ATTN_NORM); // bounce sound
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
/*
================
HellStaff
Hurls multiple fireballs down on enemy from the sky
================
*/
void() HellStaff =
{
local entity missile;
local float r;
//set random variable
r = random();
self.effects = self.effects | EF_MUZZLEFLASH;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
// set missile speed
makevectors (self.v_angle);
missile.velocity = normalize(self.enemy.origin - self.origin);
missile.velocity = missile.velocity * 500;
missile.velocity_z = missile.velocity_z + 200 + (r * 100); //give a little random boost
missile.avelocity = '300 300 300';
missile.angles = vectoangles(missile.velocity);
missile.touch = HellStaffTouch;
// set missile duration
missile.nextthink = time + 2.5;
missile.think = HellStaffExplode;
setmodel (missile, "progs/flame2.mdl");
missile.frame = 1;
missile.glow_size = 100;
missile.glow_red = 1;
missile.glow_green = 0.5;
missile.glow_blue = 0;
setsize (missile, '0 0 0', '0 0 0');
// random amount to the left or right
r = random();
if (random() <= 0.5)
{
//either r * 10 or r * 25
if (random() <= 0.5)
setorigin (missile, self.origin + (v_right * (r * 10)) + '0 0 10');
else
setorigin (missile, self.origin + (v_right * (r * 25)) + '0 0 10');
}
else
{
//either r * 10 or r * 25
if (random() <= 0.5)
setorigin (missile, self.origin - (v_right * (r * 10)) + '0 0 10');
else
setorigin (missile, self.origin - (v_right * (r * 25)) + '0 0 10');
}
//make hellstaff sound
sound (self, CHAN_WEAPON, "weapons/demon/hellstafffire.wav", 1, ATTN_NORM);
};
//===========================================================================
void() torment_stand1 =[ $idle101, torment_stand2 ] {ai_stand();};
void() torment_stand2 =[ $idle102, torment_stand3 ] {ai_stand();};
void() torment_stand3 =[ $idle103, torment_stand4 ] {ai_stand();};
void() torment_stand4 =[ $idle104, torment_stand5 ] {ai_stand();};
void() torment_stand5 =[ $idle105, torment_stand6 ] {ai_stand();};
void() torment_stand6 =[ $idle106, torment_stand7 ] {ai_stand();};
void() torment_stand7 =[ $idle107, torment_stand1 ] {ai_stand();};
//===========================================================================
void() torment_walk1 =[ $walk01, torment_walk2 ] {ai_walk(2);};
void() torment_walk2 =[ $walk02, torment_walk3 ] {ai_walk(5);};
void() torment_walk3 =[ $walk03, torment_walk4 ] {ai_walk(5);};
void() torment_walk4 =[ $walk04, torment_walk5 ] {ai_walk(4);};
void() torment_walk5 =[ $walk05, torment_walk6 ] {ai_walk(4);};
void() torment_walk6 =[ $walk06, torment_walk7 ] {ai_walk(2);};
void() torment_walk7 =[ $walk07, torment_walk8 ] {ai_walk(2);};
void() torment_walk8 =[ $walk08, torment_walk9 ] {ai_walk(3);};
void() torment_walk9 =[ $walk09, torment_walk10 ] {ai_walk(3);};
void() torment_walk10 =[ $walk10, torment_walk11 ] {ai_walk(4);};
void() torment_walk11 =[ $walk11, torment_walk12 ] {ai_walk(3);};
void() torment_walk12 =[ $walk12, torment_walk1 ] {ai_walk(2);};
//===========================================================================
void() torment_run1 =[ $run01, torment_run2 ]
{
ai_run(20);
TormentCheckForCharge();
};
void() torment_run2 =[ $run02, torment_run3 ] {ai_run(25);};
void() torment_run3 =[ $run03, torment_run4 ] {ai_run(18);};
void() torment_run4 =[ $run04, torment_run5 ] {ai_run(16);};
void() torment_run5 =[ $run05, torment_run6 ] {ai_run(14);};
void() torment_run6 =[ $run06, torment_run7 ] {ai_run(13);};
void() torment_run7 =[ $run07, torment_run8 ] {ai_run(14);};
void() torment_run8 =[ $run08, torment_run1 ] {ai_run(13);};
//============================================================================
void() torment_pain1 =[ $pain101, torment_pain2 ] {};
void() torment_pain2 =[ $pain102, torment_pain3 ] {};
void() torment_pain3 =[ $pain103, torment_pain4 ] {};
void() torment_pain4 =[ $pain104, torment_run1 ] {};
//============================================================================
void() torment_die1 =[ $death101, torment_die2 ] {};
void() torment_die2 =[ $death102, torment_die3 ] {};
void() torment_die3 =[ $death103, torment_die4 ] {self.solid = SOLID_NOT;};
void() torment_die4 =[ $death104, torment_die5 ] {};
void() torment_die5 =[ $death105, torment_die6 ] {};
void() torment_die6 =[ $death106, torment_die7 ] {};
void() torment_die7 =[ $death107, torment_die7 ] {banish_monster();};
void() torment_die =
{
// regular death
if (random() <=0.5)
sound (self, CHAN_VOICE, "enemy/torment/death1.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "enemy/torment/death2.wav", 1, ATTN_NORM);
torment_die1 ();
};
//============================================================================
void() torment_char_a1 =[ $run01, torment_char_a2 ] {ai_charge(20);};
void() torment_char_a2 =[ $run02, torment_char_a3 ] {ai_charge(20);};
void() torment_char_a3 =[ $run03, torment_char_a4 ] {ai_charge(21);};
void() torment_char_a4 =[ $run04, torment_char_a5 ] {ai_charge(13);};
void() torment_char_a5 =[ $run05, torment_char_a6 ] {ai_charge(20);};
void() torment_char_a6 =[ $run06, torment_char_a7 ] {ai_charge(13);};
void() torment_char_a7 =[ $run07, torment_char_a8 ] {ai_charge(20);};
void() torment_char_a8 =[ $run08, torment_run1 ] {ai_charge(13);};
//===========================================================================
void() torment_char_b1 =[ $run01, torment_char_b2 ] {TormentCheckContinueCharge();ai_charge(23);};
void() torment_char_b2 =[ $run02, torment_char_b3 ] {ai_charge(17);};
void() torment_char_b3 =[ $run03, torment_char_b4 ] {ai_charge(12);};
void() torment_char_b4 =[ $run04, torment_char_b5 ] {ai_charge(22);};
void() torment_char_b5 =[ $run05, torment_char_b6 ] {ai_charge(18);};
void() torment_char_b6 =[ $run06, torment_char_b7 ] {ai_charge(22);};
void() torment_char_b7 =[ $run07, torment_char_b8 ] {ai_charge(18);};
void() torment_char_b8 =[ $run08, torment_char_b1 ] {ai_charge(8);};
//===========================================================================
void() torment_watk1 =[ $attack101, torment_watk2 ] {ai_charge(9);};
void() torment_watk2 =[ $attack102, torment_watk3 ] {ai_charge(7);};
void() torment_watk3 =[ $attack103, torment_watk4 ] {ai_charge(15);ai_melee();};
void() torment_watk4 =[ $attack104, torment_watk5 ] {ai_charge(8);ai_melee();};
void() torment_watk5 =[ $attack105, torment_watk6 ] {ai_charge(2);ai_melee();};
void() torment_watk6 =[ $attack106, torment_watk7 ] {ai_face();ai_melee();};
void() torment_watk7 =[ $attack107, torment_watk8 ] {ai_face();};
void() torment_watk8 =[ $attack108, torment_watk9 ] {ai_face();};
void() torment_watk9 =[ $attack109, torment_run1 ] {ai_face();};
//===========================================================================
void() torment_hellstaff1 =[ $attack201, torment_hellstaff2 ] {ai_face();HellStaff();};
void() torment_hellstaff2 =[ $attack202, torment_hellstaff3 ] {ai_face();HellStaff();};
void() torment_hellstaff3 =[ $attack203, torment_hellstaff4 ] {ai_face();HellStaff();};
void() torment_hellstaff4 =[ $attack204, torment_hellstaff5 ] {ai_face();HellStaff();};
void() torment_hellstaff5 =[ $attack205, torment_hellstaff6 ] {ai_face();HellStaff();};
void() torment_hellstaff6 =[ $attack206, torment_hellstaff7 ] {ai_face();HellStaff();};
void() torment_hellstaff7 =[ $attack207, torment_hellstaff8 ] {ai_face();HellStaff();};
void() torment_hellstaff8 =[ $attack208, torment_run1 ] {ai_face();HellStaff();};
//===========================================================================
void(entity attacker, float damage) torment_pain =
{
local float r;
r = random();
if (self.pain_finished > time)
return;
if (r <= 0.3)
sound (self, CHAN_VOICE, "enemy/torment/pain1.wav", 1, ATTN_NORM);
else if (r <= 0.6)
sound (self, CHAN_VOICE, "enemy/torment/pain2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "enemy/torment/pain3.wav", 1, ATTN_NORM);
if (time - self.pain_finished > 5)
{ // allways go into pain frame if it has been a while
torment_pain1 ();
self.pain_finished = time + 1;
return;
}
if ((random()*30 > damage) )
return; // didn't flinch
self.pain_finished = time + 1;
torment_pain1 ();
};
void() torment_melee =
{
sound (self, CHAN_WEAPON, "enemy/torment/miss.wav", 1, ATTN_NORM);
torment_watk1 ();
};
void() torment_missile =
{
//Torment shouldnt rely on Hell Staff attack too much
//if (random() <= 0.5)
torment_hellstaff1 ();
};
void() torment_precache =
{
//torment graphics
precache_model ("models/enemies/torment.md2");
precache_model ("progs/flame2.mdl");
//torment sounds
precache_sound ("enemy/torment/alert.wav");
precache_sound ("enemy/torment/attack.wav");
precache_sound ("enemy/torment/death1.wav");
precache_sound ("enemy/torment/death2.wav");
precache_sound ("enemy/torment/miss.wav");
precache_sound ("enemy/torment/pain1.wav");
precache_sound ("enemy/torment/pain2.wav");
precache_sound ("enemy/torment/pain3.wav");
precache_sound ("weapons/demon/firehit.wav");
precache_sound ("weapons/demon/hellstafffire.wav");
precache_sound ("weapons/lock4.wav"); //used for missile touch function
};
/*EWED monster_torment (1 0 0) (-16 -16 -24) (16 16 40) Ambush
*/
void() monster_torment =
{
if (deathmatch)
{
remove(self);
return;
}
//if we are put in the level directly then call torment_precache
if (self.classname != "monster_hell_knight")
torment_precache();
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
setmodel (self, "models/enemies/torment.md2");
setsize (self, '-16 -16 -24', '16 16 40');
// setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
self.health = set_health(175);
self.speed = set_speed(300);
self.dtype = 1; //dodge type back_strafe
self.alpha = 1; //we aren't transparent
self.th_stand = torment_stand1;
self.th_walk = torment_walk1;
self.th_run = torment_run1;
self.th_melee = torment_melee;
self.th_missile = torment_missile;
self.th_pain = torment_pain;
self.th_die = torment_die;
//my new classname is?
self.classname = "monster_torment";
//set up our monflag
self.monflag = "TRUE";
walkmonster_start ();
};
/*
=================
create_tormentbot
Creates a Torment at the specified 'spot'.
This is used by demon portals in Flood Co-op.
=================
*/
void(vector spot) create_tormentbot =
{
local entity bot;
// 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/torment.md2");
setsize (bot, '-16 -16 -24', '16 16 40');
bot.flags = bot.flags | FL_MONSTER;
bot.takedamage = DAMAGE_AIM;
// define his animation
bot.th_stand = torment_stand1;
bot.th_walk = torment_walk1;
bot.th_run = torment_run1;
bot.th_melee = torment_melee;
bot.th_missile = torment_missile;
bot.th_pain = torment_pain;
bot.th_die = torment_die;
bot.health = set_health(175);
bot.speed = set_speed(300);
bot.dtype = 1; //dodge type back_strafe
bot.alpha = 1; //we aren't transparent
// polish him up
bot.classname = "monster_torment";
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";
// begin his thinking
bot.nextthink = time + 0.1 + random();
bot.think = th_stuck;
};