504 lines
16 KiB
C++
504 lines
16 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
Hell Hound
|
|
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 idle108 idle109 idle110
|
|
$frame idle111 idle112 idle113 idle114 idle115 idle116 idle117 idle118 idle119 idle120
|
|
$frame idle121 idle122 idle123 idle124 idle125 idle126 idle127 idle128 idle129 idle130
|
|
$frame idle131 idle132 idle133 idle134 idle135 idle136 idle137 idle138 idle139 idle140
|
|
|
|
$frame idle201 idle202 idle203 idle204 idle205 idle206 idle207 idle208 idle209 idle210
|
|
$frame idle211 idle212 idle213 idle214 idle215 idle216 idle217 idle218 idle219 idle220
|
|
$frame idle221 idle222 idle223 idle224 idle225 idle226 idle227 idle228 idle229 idle230
|
|
$frame idle231 idle232 idle233 idle234 idle235 idle236 idle237 idle238 idle239 idle240
|
|
|
|
$frame bark1 bark2 bark3 bark4 bark5 bark6 bark7 bark8
|
|
|
|
$frame attack101 attack102 attack103 attack104 attack105 attack106
|
|
|
|
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
|
|
|
|
$frame run1 run2 run3 run4 run5 run6 run7 run8
|
|
|
|
$frame pain1 pain2 pain3 pain4
|
|
|
|
$frame death101 death102 death103 death104 death105 death106 death107 death108 death109 death110
|
|
$frame death111
|
|
|
|
$frame death201 death202 death203 death204 death205 death206 death207 death208 death209 death210
|
|
$frame death211 death212 death213 death214 death215 death216 death217 death218 death219 death220
|
|
$frame death221
|
|
|
|
$frame attack201 attack202 attack203 attack204 attack205 attack206 attack207 attack208
|
|
|
|
void() hhound_leap1;
|
|
void() hhound_run1;
|
|
void() hhound_idlesound;
|
|
|
|
/*
|
|
================
|
|
hhound_bite
|
|
|
|
================
|
|
*/
|
|
void() hhound_bite =
|
|
{
|
|
local vector delta;
|
|
local float ldmg;
|
|
|
|
if (!self.enemy)
|
|
return;
|
|
|
|
ai_charge(10);
|
|
|
|
if (!CanDamage (self.enemy, self))
|
|
return;
|
|
|
|
delta = self.enemy.origin - self.origin;
|
|
|
|
if (vlen(delta) > 100)
|
|
return;
|
|
|
|
ldmg = (random() + random() + random()) * 8;
|
|
T_Damage (self.enemy, self, self, ldmg);
|
|
};
|
|
|
|
void() hhound_JumpTouch =
|
|
{
|
|
local float ldmg;
|
|
|
|
if (self.health <= 0)
|
|
return;
|
|
|
|
if (other.takedamage)
|
|
{
|
|
if ( vlen(self.velocity) > 300 )
|
|
{
|
|
ldmg = 10 + 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 = hhound_leap1;
|
|
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 = hhound_run1;
|
|
self.nextthink = time + 0.1;
|
|
};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_stand1 =[ $idle101, hhound_stand2 ] {ai_stand();hhound_idlesound();};
|
|
void() hhound_stand2 =[ $idle102, hhound_stand3 ] {ai_stand();};
|
|
void() hhound_stand3 =[ $idle103, hhound_stand4 ] {ai_stand();};
|
|
void() hhound_stand4 =[ $idle104, hhound_stand5 ] {ai_stand();};
|
|
void() hhound_stand5 =[ $idle105, hhound_stand6 ] {ai_stand();};
|
|
void() hhound_stand6 =[ $idle106, hhound_stand7 ] {ai_stand();};
|
|
void() hhound_stand7 =[ $idle107, hhound_stand8 ] {ai_stand();};
|
|
void() hhound_stand8 =[ $idle108, hhound_stand9 ] {ai_stand();};
|
|
void() hhound_stand9 =[ $idle109, hhound_stand10 ] {ai_stand();};
|
|
void() hhound_stand10 =[ $idle110, hhound_stand11 ] {ai_stand();};
|
|
void() hhound_stand11 =[ $idle111, hhound_stand12 ] {ai_stand();};
|
|
void() hhound_stand12 =[ $idle112, hhound_stand13 ] {ai_stand();};
|
|
void() hhound_stand13 =[ $idle113, hhound_stand14 ] {ai_stand();};
|
|
void() hhound_stand14 =[ $idle114, hhound_stand15 ] {ai_stand();};
|
|
void() hhound_stand15 =[ $idle115, hhound_stand16 ] {ai_stand();};
|
|
void() hhound_stand16 =[ $idle116, hhound_stand17 ] {ai_stand();};
|
|
void() hhound_stand17 =[ $idle117, hhound_stand18 ] {ai_stand();};
|
|
void() hhound_stand18 =[ $idle118, hhound_stand19 ] {ai_stand();};
|
|
void() hhound_stand19 =[ $idle119, hhound_stand20 ] {ai_stand();};
|
|
void() hhound_stand20 =[ $idle120, hhound_stand21 ] {ai_stand();};
|
|
void() hhound_stand21 =[ $idle121, hhound_stand22 ] {ai_stand();};
|
|
void() hhound_stand22 =[ $idle122, hhound_stand23 ] {ai_stand();};
|
|
void() hhound_stand23 =[ $idle123, hhound_stand24 ] {ai_stand();};
|
|
void() hhound_stand24 =[ $idle124, hhound_stand25 ] {ai_stand();};
|
|
void() hhound_stand25 =[ $idle125, hhound_stand26 ] {ai_stand();};
|
|
void() hhound_stand26 =[ $idle126, hhound_stand27 ] {ai_stand();};
|
|
void() hhound_stand27 =[ $idle127, hhound_stand28 ] {ai_stand();};
|
|
void() hhound_stand28 =[ $idle128, hhound_stand29 ] {ai_stand();};
|
|
void() hhound_stand29 =[ $idle129, hhound_stand30 ] {ai_stand();};
|
|
void() hhound_stand30 =[ $idle130, hhound_stand31 ] {ai_stand();};
|
|
void() hhound_stand31 =[ $idle131, hhound_stand32 ] {ai_stand();};
|
|
void() hhound_stand32 =[ $idle132, hhound_stand33 ] {ai_stand();};
|
|
void() hhound_stand33 =[ $idle133, hhound_stand34 ] {ai_stand();};
|
|
void() hhound_stand34 =[ $idle134, hhound_stand35 ] {ai_stand();};
|
|
void() hhound_stand35 =[ $idle135, hhound_stand36 ] {ai_stand();};
|
|
void() hhound_stand36 =[ $idle136, hhound_stand37 ] {ai_stand();};
|
|
void() hhound_stand37 =[ $idle137, hhound_stand38 ] {ai_stand();};
|
|
void() hhound_stand38 =[ $idle138, hhound_stand39 ] {ai_stand();};
|
|
void() hhound_stand39 =[ $idle139, hhound_stand40 ] {ai_stand();};
|
|
void() hhound_stand40 =[ $idle140, hhound_stand1 ] {ai_stand();};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_walk1 =[ $walk1 , hhound_walk2 ] {ai_walk(8);hhound_idlesound();};
|
|
void() hhound_walk2 =[ $walk2 , hhound_walk3 ] {ai_walk(8);};
|
|
void() hhound_walk3 =[ $walk3 , hhound_walk4 ] {ai_walk(8);};
|
|
void() hhound_walk4 =[ $walk4 , hhound_walk5 ] {ai_walk(8);};
|
|
void() hhound_walk5 =[ $walk5 , hhound_walk6 ] {ai_walk(8);};
|
|
void() hhound_walk6 =[ $walk6 , hhound_walk7 ] {ai_walk(8);};
|
|
void() hhound_walk7 =[ $walk7 , hhound_walk8 ] {ai_walk(8);};
|
|
void() hhound_walk8 =[ $walk8 , hhound_walk1 ] {ai_walk(8);};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_run1 =[ $walk1 , hhound_run2 ] {ai_run(24);hhound_idlesound();};
|
|
void() hhound_run2 =[ $walk2 , hhound_run3 ] {ai_run(24);};
|
|
void() hhound_run3 =[ $walk3 , hhound_run4 ] {ai_run(24);};
|
|
void() hhound_run4 =[ $walk4 , hhound_run5 ] {ai_run(24);};
|
|
void() hhound_run5 =[ $walk5 , hhound_run6 ] {ai_run(24);};
|
|
void() hhound_run6 =[ $walk6 , hhound_run7 ] {ai_run(24);};
|
|
void() hhound_run7 =[ $walk7 , hhound_run8 ] {ai_run(24);};
|
|
void() hhound_run8 =[ $walk8 , hhound_run1 ] {ai_run(24);};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_atta1 =[ $attack101, hhound_atta2 ] {ai_charge(10);};
|
|
void() hhound_atta2 =[ $attack102, hhound_atta3 ] {ai_charge(10);};
|
|
void() hhound_atta3 =[ $attack103, hhound_atta4 ] {ai_charge(10);};
|
|
void() hhound_atta4 =[ $attack104, hhound_atta5 ] {hhound_bite();};
|
|
void() hhound_atta5 =[ $attack105, hhound_atta6 ] {ai_charge(10);};
|
|
void() hhound_atta6 =[ $attack106, hhound_run1 ] {ai_charge(10);};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_attb1 =[ $attack201, hhound_attb2 ] {ai_charge(10);};
|
|
void() hhound_attb2 =[ $attack202, hhound_attb3 ] {ai_charge(10);};
|
|
void() hhound_attb3 =[ $attack203, hhound_attb4 ] {ai_charge(10);};
|
|
void() hhound_attb4 =[ $attack204, hhound_attb5 ] {hhound_bite();};
|
|
void() hhound_attb5 =[ $attack205, hhound_attb6 ] {ai_charge(10);};
|
|
void() hhound_attb6 =[ $attack206, hhound_attb7 ] {ai_charge(10);};
|
|
void() hhound_attb7 =[ $attack207, hhound_attb8 ] {ai_charge(10);};
|
|
void() hhound_attb8 =[ $attack208, hhound_run1 ] {ai_charge(10);};
|
|
|
|
void() hhound_melee =
|
|
{
|
|
if (random() > 0.5)
|
|
{
|
|
sound (self, CHAN_VOICE, "enemy/hhound/attack1.wav", 1, ATTN_NORM);
|
|
hhound_atta1 ();
|
|
}
|
|
else
|
|
{
|
|
sound (self, CHAN_VOICE, "enemy/hhound/attack2.wav", 1, ATTN_NORM);
|
|
hhound_attb1 ();
|
|
}
|
|
};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_leap1 =[ $run1, hhound_leap2 ] {ai_face();};
|
|
void() hhound_leap2 =[ $run2, hhound_leap3 ]
|
|
{
|
|
ai_face();
|
|
|
|
self.touch = hhound_JumpTouch;
|
|
makevectors (self.angles);
|
|
self.origin_z = self.origin_z + 1;
|
|
self.velocity = v_forward * 300 + '0 0 200';
|
|
if (self.flags & FL_ONGROUND)
|
|
self.flags = self.flags - FL_ONGROUND;
|
|
};
|
|
|
|
void() hhound_leap3 =[ $run3, hhound_leap4 ] {};
|
|
void() hhound_leap4 =[ $run4, hhound_leap5 ] {};
|
|
void() hhound_leap5 =[ $run5, hhound_leap6 ] {};
|
|
void() hhound_leap6 =[ $run6, hhound_leap7 ] {};
|
|
void() hhound_leap7 =[ $run7, hhound_leap8 ] {};
|
|
void() hhound_leap8 =[ $run8, hhound_leap8 ] {};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_pain1 =[ $pain1 , hhound_pain2 ] {};
|
|
void() hhound_pain2 =[ $pain2 , hhound_pain3 ] {};
|
|
void() hhound_pain3 =[ $pain3 , hhound_pain4 ] {};
|
|
void() hhound_pain4 =[ $pain4 , hhound_run1 ] {};
|
|
|
|
void() hhound_pain =
|
|
{
|
|
local float r;
|
|
|
|
//pick between 4 pain sounds
|
|
r = random();
|
|
if (r <= 0.25)
|
|
sound (self, CHAN_VOICE, "enemy/hhound/pain1.wav", 1, ATTN_NORM);
|
|
else if (r <= 0.5)
|
|
sound (self, CHAN_VOICE, "enemy/hhound/pain2.wav", 1, ATTN_NORM);
|
|
else if (r <= 0.75)
|
|
sound (self, CHAN_VOICE, "enemy/hhound/pain3.wav", 1, ATTN_NORM);
|
|
else
|
|
sound (self, CHAN_VOICE, "enemy/hhound/pain4.wav", 1, ATTN_NORM);
|
|
|
|
hhound_pain1 ();
|
|
};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_die1 =[ $death101, hhound_die2 ] {};
|
|
void() hhound_die2 =[ $death102, hhound_die3 ] {};
|
|
void() hhound_die3 =[ $death103, hhound_die4 ] {};
|
|
void() hhound_die4 =[ $death104, hhound_die5 ] {};
|
|
void() hhound_die5 =[ $death105, hhound_die6 ] {};
|
|
void() hhound_die6 =[ $death106, hhound_die7 ] {};
|
|
void() hhound_die7 =[ $death107, hhound_die8 ] {};
|
|
void() hhound_die8 =[ $death108, hhound_die9 ] {};
|
|
void() hhound_die9 =[ $death109, hhound_die10 ] {};
|
|
void() hhound_die10 =[ $death110, hhound_die11 ] {};
|
|
void() hhound_die11 =[ $death111, hhound_die11 ] {banish_monster();};
|
|
|
|
//============================================================================
|
|
|
|
void() hhound_dieb1 =[ $death201, hhound_dieb2 ] {};
|
|
void() hhound_dieb2 =[ $death202, hhound_dieb3 ] {};
|
|
void() hhound_dieb3 =[ $death203, hhound_dieb4 ] {};
|
|
void() hhound_dieb4 =[ $death204, hhound_dieb5 ] {};
|
|
void() hhound_dieb5 =[ $death205, hhound_dieb6 ] {};
|
|
void() hhound_dieb6 =[ $death206, hhound_dieb7 ] {};
|
|
void() hhound_dieb7 =[ $death207, hhound_dieb8 ] {};
|
|
void() hhound_dieb8 =[ $death208, hhound_dieb9 ] {};
|
|
void() hhound_dieb9 =[ $death209, hhound_dieb10 ] {};
|
|
void() hhound_dieb10 =[ $death210, hhound_dieb11 ] {};
|
|
void() hhound_dieb11 =[ $death211, hhound_dieb12 ] {};
|
|
void() hhound_dieb12 =[ $death212, hhound_dieb13 ] {};
|
|
void() hhound_dieb13 =[ $death213, hhound_dieb14 ] {};
|
|
void() hhound_dieb14 =[ $death214, hhound_dieb15 ] {};
|
|
void() hhound_dieb15 =[ $death215, hhound_dieb16 ] {};
|
|
void() hhound_dieb16 =[ $death216, hhound_dieb17 ] {};
|
|
void() hhound_dieb17 =[ $death217, hhound_dieb18 ] {};
|
|
void() hhound_dieb18 =[ $death218, hhound_dieb19 ] {};
|
|
void() hhound_dieb19 =[ $death219, hhound_dieb20 ] {};
|
|
void() hhound_dieb20 =[ $death220, hhound_dieb21 ] {};
|
|
void() hhound_dieb21 =[ $death221, hhound_dieb21 ] {banish_monster();};
|
|
|
|
|
|
void() hhound_die =
|
|
{
|
|
// regular death
|
|
sound (self, CHAN_VOICE, "enemy/hhound/death.wav", 1, ATTN_NORM);
|
|
self.solid = SOLID_NOT;
|
|
|
|
if (random() > 0.5)
|
|
hhound_die1 ();
|
|
else
|
|
hhound_dieb1 ();
|
|
};
|
|
|
|
//============================================================================
|
|
|
|
/*
|
|
==============
|
|
CheckhhoundMelee
|
|
|
|
Returns TRUE if a melee attack would hit right now
|
|
==============
|
|
*/
|
|
float() CheckhhoundMelee =
|
|
{
|
|
if (enemy_range == RANGE_MELEE)
|
|
{ // FIXME: check canreach
|
|
self.attack_state = AS_MELEE;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
};
|
|
|
|
/*
|
|
==============
|
|
CheckhhoundJump
|
|
|
|
==============
|
|
*/
|
|
float() CheckhhoundJump =
|
|
{
|
|
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 < 80)
|
|
return FALSE;
|
|
|
|
if (d > 150)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
};
|
|
|
|
float() hhoundCheckAttack =
|
|
{
|
|
local vector vec;
|
|
|
|
// if close enough for slashing, go for it
|
|
if (CheckhhoundMelee ())
|
|
{
|
|
self.attack_state = AS_MELEE;
|
|
return TRUE;
|
|
}
|
|
|
|
if (CheckhhoundJump ())
|
|
{
|
|
self.attack_state = AS_MISSILE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
};
|
|
|
|
void() hhound_idlesound =
|
|
{
|
|
if (random() <= 0.2)
|
|
{
|
|
if (random() <= 0.5)
|
|
sound (self, CHAN_VOICE, "enemy/hhound/alert1.wav", 1, ATTN_NORM);
|
|
else
|
|
sound (self, CHAN_VOICE, "enemy/hhound/idle.wav", 1, ATTN_NORM);
|
|
}
|
|
};
|
|
|
|
//===========================================================================
|
|
|
|
/*QUAKED monster_hhound (1 0 0) (-32 -32 -24) (32 32 40) Ambush
|
|
|
|
*/
|
|
void() monster_hhound =
|
|
{
|
|
if (deathmatch)
|
|
{
|
|
remove(self);
|
|
return;
|
|
}
|
|
|
|
precache_model ("models/enemies/hhound.md2");
|
|
|
|
precache_sound ("enemy/hhound/alert1.wav");
|
|
precache_sound ("enemy/hhound/attack1.wav");
|
|
precache_sound ("enemy/hhound/attack2.wav");
|
|
precache_sound ("enemy/hhound/death.wav");
|
|
precache_sound ("enemy/hhound/idle.wav");
|
|
precache_sound ("enemy/hhound/pain1.wav");
|
|
precache_sound ("enemy/hhound/pain2.wav");
|
|
precache_sound ("enemy/hhound/pain3.wav");
|
|
precache_sound ("enemy/hhound/pain4.wav");
|
|
precache_sound ("enemy/hhound/rage.wav");
|
|
|
|
self.solid = SOLID_SLIDEBOX;
|
|
self.movetype = MOVETYPE_STEP;
|
|
|
|
setmodel (self, "models/enemies/hhound.md2");
|
|
|
|
setsize (self, '-32 -32 -24', '32 32 40');
|
|
// setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
|
|
self.health = set_health(30);
|
|
self.speed = set_speed(800);
|
|
self.dtype = 2; //dodge type forward_strafe
|
|
self.alpha = 1; //we aren't transparent
|
|
|
|
self.th_stand = hhound_stand1;
|
|
self.th_walk = hhound_walk1;
|
|
self.th_run = hhound_run1;
|
|
self.th_pain = hhound_pain;
|
|
self.th_die = hhound_die;
|
|
self.th_melee = hhound_melee;
|
|
self.th_missile = hhound_leap1;
|
|
|
|
//my new classname is?
|
|
self.classname = "monster_hhound";
|
|
|
|
//set up our monflag
|
|
self.monflag = "TRUE";
|
|
|
|
walkmonster_start();
|
|
};
|
|
|
|
/*
|
|
=================
|
|
create_hhoundbot
|
|
|
|
Creates a Hell Hound at the specified 'spot'.
|
|
This is used by the Captain, he summons Hell Hounds, Dwellers, and Axe Mercenaries.
|
|
=================
|
|
*/
|
|
void(vector spot) create_hhoundbot =
|
|
{
|
|
|
|
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/hhound.md2");
|
|
setsize (bot, '-32 -32 -24', '32 32 40');
|
|
bot.flags = bot.flags | FL_MONSTER;
|
|
bot.takedamage = DAMAGE_AIM;
|
|
|
|
// define his animation
|
|
bot.th_stand = hhound_stand1;
|
|
bot.th_walk = hhound_walk1;
|
|
bot.th_run = hhound_run1;
|
|
bot.th_die = hhound_die;
|
|
bot.th_melee = hhound_melee;
|
|
bot.th_missile = hhound_leap1;
|
|
bot.th_pain = hhound_pain;
|
|
bot.health = set_health(30);
|
|
bot.speed = set_speed(800);
|
|
bot.dtype = 2; //dodge type forward_strafe
|
|
bot.alpha = 1; //we aren't transparent
|
|
|
|
// polish him up
|
|
bot.classname = "monster_hhound";
|
|
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;
|
|
};
|
|
|