ew-progs/ew/monsters/teneb.qc

519 lines
14 KiB
C++
Raw Permalink Normal View History

2011-09-06 00:00:00 +00:00
/*
==============================================================================
Teneb
coded by Michael Rogers a.k.a Xsniper
http://xsniper.virtualave.net/
some code done by iD software
This is one of the coolest monsters in the game, was very fun brining him to life!
==============================================================================
*/
$cd /models/enemies
$origin 0 0 24
$base base
$skin base
$frame idle101 idle102 idle103 idle104 idle105 idle106 idle107 idle108 idle109 idle110
$frame idle111 idle112 idle113 idle114 idle115 idle116 idle117 idle118 idle119 idle120
$frame idle201 idle202 idle203 idle204 idle205 idle206 idle207 idle208 idle209 idle210
$frame idle211 idle212 idle213 idle214 idle215 idle216 idle217 idle218 idle219 idle220
$frame run01 run02 run03 run04 run05 run06
$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
$frame attack301 attack302 attack303 attack304
$frame attack401 attack402 attack403 attack404
$frame attack501 attack502 attack503 attack504 attack505 attack506 attack507
$frame pain101 pain102 pain103 pain104
$frame pain201 pain202 pain203 pain204 pain205
$frame death101 death102 death103 death104 death105 death106 death006
void() teneb_jump1;
void() teneb_jump7;
void() teneb_idlesound;
void() teneb_goinvisible;
void() teneb_govisible;
/*
==============================================================================
teneb
==============================================================================
*/
/*
==============
ChecktenebMelee
Returns TRUE if a melee attack would hit right now
==============
*/
float() ChecktenebMelee =
{
if (enemy_range == RANGE_MELEE)
{ // FIXME: check canreach
self.attack_state = AS_MELEE;
return TRUE;
}
return FALSE;
};
/*
==============
ChecktenebJump
==============
*/
float() ChecktenebJump =
{
local vector dist;
local float d;
if (self.origin_z + self.mins_z > self.enemy.origin_z + self.enemy.mins_z
+ 0.75 * self.enemy.size_z)
return FALSE;
if (self.origin_z + self.maxs_z < self.enemy.origin_z + self.enemy.mins_z
+ 0.25 * self.enemy.size_z)
return FALSE;
dist = self.enemy.origin - self.origin;
dist_z = 0;
d = vlen(dist);
if (d < 100)
return FALSE;
if (d > 200)
{
if (random() < 0.9)
return FALSE;
}
return TRUE;
};
float() tenebCheckAttack =
{
local vector vec;
// if close enough for slashing, go for it
if (ChecktenebMelee ())
{
self.attack_state = AS_MELEE;
return TRUE;
}
if (ChecktenebJump ())
{
self.attack_state = AS_MISSILE;
return TRUE;
}
return FALSE;
};
//===========================================================================
void(float side) teneb_Melee =
{
local float ldmg;
local vector delta;
ai_face ();
walkmove (self.ideal_yaw, 12); // allow a little closing
delta = self.enemy.origin - self.origin;
if (vlen(delta) > 100)
return;
if (!CanDamage (self.enemy, self))
return;
sound (self, CHAN_WEAPON, "weapons/demon/clawhit.wav", 1, ATTN_NORM);
ldmg = 10 + 5*random();
T_Damage (self.enemy, self, self, ldmg);
makevectors (self.angles);
};
void() teneb_JumpTouch =
{
local float ldmg;
if (self.health <= 0)
return;
if (other.takedamage)
{
if ( vlen(self.velocity) > 400 )
{
ldmg = 40 + 10*random();
T_Damage (other, self, self, ldmg);
}
}
if (!checkbottom(self))
{
if (self.flags & FL_ONGROUND)
{ // jump randomly to not get hung up
//dprint ("popjump\n");
self.touch = SUB_Null;
self.think = teneb_jump1;
self.nextthink = time + 0.1;
// self.velocity_x = (random() - 0.5) * 600;
// self.velocity_y = (random() - 0.5) * 600;
// self.velocity_z = 200;
// self.flags = self.flags - FL_ONGROUND;
}
return; // not on ground yet
}
self.touch = SUB_Null;
self.think = teneb_jump7;
self.nextthink = time + 0.1;
};
//============================================================================
void() teneb_stand1 =[ $idle101, teneb_stand2 ] {ai_stand();teneb_idlesound();};
void() teneb_stand2 =[ $idle102, teneb_stand3 ] {ai_stand();};
void() teneb_stand3 =[ $idle103, teneb_stand4 ] {ai_stand();};
void() teneb_stand4 =[ $idle104, teneb_stand5 ] {ai_stand();};
void() teneb_stand5 =[ $idle105, teneb_stand6 ] {ai_stand();};
void() teneb_stand6 =[ $idle106, teneb_stand7 ] {ai_stand();};
void() teneb_stand7 =[ $idle107, teneb_stand8 ] {ai_stand();};
void() teneb_stand8 =[ $idle108, teneb_stand9 ] {ai_stand();};
void() teneb_stand9 =[ $idle109, teneb_stand10 ] {ai_stand();};
void() teneb_stand10 =[ $idle110, teneb_stand11 ] {ai_stand();};
void() teneb_stand11 =[ $idle111, teneb_stand12 ] {ai_stand();};
void() teneb_stand12 =[ $idle112, teneb_stand13 ] {ai_stand();};
void() teneb_stand13 =[ $idle113, teneb_stand14 ] {ai_stand();};
void() teneb_stand14 =[ $idle104, teneb_stand15 ] {ai_stand();};
void() teneb_stand15 =[ $idle105, teneb_stand16 ] {ai_stand();};
void() teneb_stand16 =[ $idle106, teneb_stand17 ] {ai_stand();};
void() teneb_stand17 =[ $idle107, teneb_stand18 ] {ai_stand();};
void() teneb_stand18 =[ $idle108, teneb_stand19 ] {ai_stand();};
void() teneb_stand19 =[ $idle109, teneb_stand20 ] {ai_stand();};
void() teneb_stand20 =[ $idle120, teneb_stand1 ] {ai_stand();};
//============================================================================
void() teneb_walk1 =[ $walk01, teneb_walk2 ] {ai_walk(8);teneb_idlesound();};
void() teneb_walk2 =[ $walk02, teneb_walk3 ] {ai_walk(6);};
void() teneb_walk3 =[ $walk03, teneb_walk4 ] {ai_walk(6);};
void() teneb_walk4 =[ $walk04, teneb_walk5 ] {ai_walk(7);};
void() teneb_walk5 =[ $walk05, teneb_walk6 ] {ai_walk(4);};
void() teneb_walk6 =[ $walk06, teneb_walk7 ] {ai_walk(6);};
void() teneb_walk7 =[ $walk07, teneb_walk8 ] {ai_walk(10);};
void() teneb_walk8 =[ $walk08, teneb_walk9 ] {ai_walk(10);};
void() teneb_walk9 =[ $walk09, teneb_walk10 ] {ai_walk(4);};
void() teneb_walk10 =[ $walk10, teneb_walk11 ] {ai_walk(6);};
void() teneb_walk11 =[ $walk11, teneb_walk12 ] {ai_walk(10);};
void() teneb_walk12 =[ $walk12, teneb_walk1 ] {ai_walk(10);};
//============================================================================
void() teneb_run1 =[ $run01, teneb_run2 ] {ai_run(20);teneb_idlesound();};
void() teneb_run2 =[ $run02, teneb_run3 ] {ai_run(15);};
void() teneb_run3 =[ $run03, teneb_run4 ] {ai_run(36);};
void() teneb_run4 =[ $run04, teneb_run5 ] {ai_run(20);};
void() teneb_run5 =[ $run05, teneb_run6 ] {ai_run(15);};
void() teneb_run6 =[ $run06, teneb_run1 ] {ai_run(36);};
//============================================================================
void() teneb_jump1 =[ $attack501, teneb_jump2 ] {ai_face();};
void() teneb_jump2 =[ $attack502, teneb_jump3 ] {ai_face();};
void() teneb_jump3 =[ $attack503, teneb_jump4 ]
{
ai_face();
self.touch = teneb_JumpTouch;
makevectors (self.angles);
self.origin_z = self.origin_z + 1;
self.velocity = v_forward * 600 + '0 0 250';
if (self.flags & FL_ONGROUND)
self.flags = self.flags - FL_ONGROUND;
};
void() teneb_jump4 =[ $attack504, teneb_jump5 ] {};
void() teneb_jump5 =[ $attack505, teneb_jump6 ] {};
void() teneb_jump6 =[ $attack506, teneb_jump1 ]
{
self.nextthink = time + 3;
// if three seconds pass, assume teneb is stuck and jump again
};
void() teneb_jump7 =[ $attack507, teneb_run1 ] {};
//============================================================================
void() teneb_atta1 =[ $attack101, teneb_atta2 ] {ai_charge(20);teneb_govisible();};
void() teneb_atta2 =[ $attack102, teneb_atta3 ] {ai_charge(25);};
void() teneb_atta3 =[ $attack103, teneb_atta4 ] {ai_charge(30);teneb_Melee(200);};
void() teneb_atta4 =[ $attack104, teneb_atta5 ] {ai_charge(25);};
void() teneb_atta5 =[ $attack105, teneb_atta6 ] {ai_charge(20);};
void() teneb_atta6 =[ $attack106, teneb_atta7 ] {ai_charge(30);};
void() teneb_atta7 =[ $attack107, teneb_atta8 ] {ai_charge(25);teneb_Melee(-200);};
void() teneb_atta8 =[ $attack108, teneb_atta9 ] {ai_charge(20);};
void() teneb_atta9 =[ $attack109, teneb_run1 ] {ai_charge(30);teneb_goinvisible();};
//============================================================================
void() teneb_attb1 =[ $attack301, teneb_attb2 ] {ai_charge(20);teneb_govisible();ai_melee();};
void() teneb_attb2 =[ $attack302, teneb_attb3 ] {ai_charge(25);ai_melee();};
void() teneb_attb3 =[ $attack303, teneb_attb4 ] {ai_charge(30);ai_melee();};
void() teneb_attb4 =[ $attack304, teneb_run1 ] {ai_charge(25);ai_melee();teneb_goinvisible();};
//============================================================================
void() teneb_paina1 =[ $pain101, teneb_paina2 ] {};
void() teneb_paina2 =[ $pain102, teneb_paina3 ] {};
void() teneb_paina3 =[ $pain103, teneb_paina4 ] {};
void() teneb_paina4 =[ $pain104, teneb_run1 ] {};
//============================================================================
void() teneb_painb1 =[ $pain201, teneb_painb2 ] {};
void() teneb_painb2 =[ $pain202, teneb_painb3 ] {};
void() teneb_painb3 =[ $pain203, teneb_painb4 ] {};
void() teneb_painb4 =[ $pain204, teneb_painb5 ] {};
void() teneb_painb5 =[ $pain205, teneb_run1 ] {};
void(entity attacker, float damage) teneb_pain =
{
if (self.touch == teneb_JumpTouch)
return;
if (self.pain_finished > time)
return;
self.pain_finished = time + 1;
//OUCH THAT HURT!
sound (self, CHAN_VOICE, "enemy/teneb/pain1.wav", 1, ATTN_NORM);
if (random()*200 > damage)
return; // didn't flinch
if (random() <= 0.5)
teneb_paina1 ();
else
teneb_painb1 ();
};
//============================================================================
void() teneb_die1 =[ $death101, teneb_die2 ] {};
void() teneb_die2 =[ $death102, teneb_die3 ] {};
void() teneb_die3 =[ $death103, teneb_die4 ] {};
void() teneb_die4 =[ $death104, teneb_die5 ] {};
void() teneb_die5 =[ $death105, teneb_die6 ] {};
void() teneb_die6 =[ $death106, teneb_die7 ] {self.solid = SOLID_NOT;};
void() teneb_die7 =[ $death006, teneb_die7 ] {banish_monster();};
void() teneb_die =
{
//ARG I'M DIEING TELL THE WORLD ABOUT IT! MAKE SOME NOISE BABY!
sound (self, CHAN_VOICE, "enemy/teneb/death.wav", 1, ATTN_NORM);
//Make sure they can see me die
teneb_govisible();
//Just die already!
teneb_die1 ();
};
//============================================================================
void() teneb_attack =
{
//TAKE THIS! GRRR I SOUND FEROCIOUS!
if (random() <= 0.9)
sound (self, CHAN_VOICE, "enemy/teneb/pain2.wav", 1, ATTN_NORM);
//Hmm... should I claw him or bite him?
if (random() <= 0.7)
teneb_atta1(); //I think I'll claw him most of the time!
else
teneb_attb1(); //Sometimes I like to chew on things... ;)
};
void() teneb_missile =
{
//TAKE THIS! GRRR I SOUND FEROCIOUS!
if (random() <= 0.9)
sound (self, CHAN_VOICE, "enemy/teneb/pain2.wav", 1, ATTN_NORM);
//I'm gonna jump all over him!
teneb_jump1();
};
void() teneb_idlesound =
{
local float r;
//make a lot of noise, but not all the time
if (random() <= 0.7)
{
//pick one of three random sounds
r = random();
if (r <= 0.33)
sound (self, CHAN_VOICE, "enemy/teneb/idle2.wav", 1, ATTN_NORM);
else if (r <= 0.66)
sound (self, CHAN_VOICE, "enemy/teneb/idle3.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "enemy/teneb/idle4.wav", 1, ATTN_NORM);
}
};
void() teneb_goinvisible =
{
//setmodel (self, "");
//setsize (self, '-32 -32 -24', '32 32 64');
self.alpha = set_fade(0.2);
};
void() teneb_govisible =
{
//setmodel (self, "models/enemies/teneb.md2");
//setsize (self, '-32 -32 -24', '32 32 64');
self.alpha = 1;
};
//============================================================================
/*QUAKED monster_teneb (1 0 0) (-32 -32 -24) (32 32 64) Ambush
*/
void() monster_teneb =
{
if (deathmatch)
{
remove(self);
return;
}
precache_model ("models/enemies/teneb.md2");
precache_sound ("enemy/teneb/death.wav"); //death sound
precache_sound ("enemy/teneb/idle2.wav"); //idle sound
precache_sound ("enemy/teneb/idle3.wav"); //idle sound
precache_sound ("enemy/teneb/idle4.wav"); //idle sound
precache_sound ("enemy/teneb/pain1.wav"); //pain sound
precache_sound ("enemy/teneb/pain2.wav"); //attack sound
precache_sound ("weapons/demon/clawhit.wav"); //attack sound
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
setmodel (self, "models/enemies/teneb.md2");
setsize (self, '-32 -32 -24', '32 32 64');
// setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
self.health = set_health(300);
self.speed = set_speed(900);
self.dtype = 4; //dodge type do nothing
self.th_stand = teneb_stand1;
self.th_walk = teneb_walk1;
self.th_run = teneb_run1;
self.th_die = teneb_die;
self.th_melee = teneb_attack;
self.th_missile = teneb_missile;
self.th_pain = teneb_pain;
//my new classname is?
self.classname = "monster_teneb";
//set up our monflag
self.monflag = "TRUE";
//difficulty optimization
remove_monster();
//start out invisible
teneb_goinvisible();
walkmonster_start();
};
/*
=================
create_tenebbot
Creates a Teneb at the specified 'spot'.
This is used by demon portals in Flood Co-op.
=================
*/
void(vector spot) create_tenebbot =
{
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/teneb.md2");
setsize (bot, '-32 -32 -24', '32 32 64');
bot.flags = bot.flags | FL_MONSTER;
bot.takedamage = DAMAGE_AIM;
// define his animation
bot.th_stand = teneb_stand1;
bot.th_walk = teneb_walk1;
bot.th_run = teneb_run1;
bot.th_die = teneb_die;
bot.th_melee = teneb_attack;
bot.th_missile = teneb_missile;
bot.th_pain = teneb_pain;
bot.health = set_health(300);
bot.speed = set_speed(900);
bot.dtype = 4; //dodge type do nothing
// polish him up
bot.classname = "monster_teneb";
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";
//start out invisible
bot.alpha = set_fade(0.2);
// begin his thinking
bot.nextthink = time + 0.1 + random();
bot.think = th_stuck;
};