hexen2-siege-hc/warhorse.hc
1998-06-24 00:00:00 +00:00

827 lines
20 KiB
C++

/*
* $Header: /HexenWorld/Siege/warhorse.hc 3 5/25/98 1:39p Mgummelt $
*/
/*
==============================================================================
Q:\art\models\monsters\RdrWar\Horse\Final\warhorse.hc
==============================================================================
*/
// For building the model
$cd Q:\art\models\monsters\RdrWar\Horse\Final
$origin 0 0 0
$base base skin
$skin skin
$flags 0
// Horse frames
$frame HaxeD1 HaxeD2 HaxeD3 HaxeD4 HaxeD5
$frame HaxeD6 HaxeD7 HaxeD8 HaxeD9 HaxeD10
$frame HaxeD11 HaxeD12 HaxeD13 HaxeD14 HaxeD15
//
$frame HgallA1 HgallA2 HgallA3 HgallA4 HgallA5
$frame HgallA6 HgallA7 HgallA8 HgallA9 HgallA10
$frame HgallA11 HgallA12
//
$frame HgallB1 HgallB2 HgallB3 HgallB4 HgallB5
$frame HgallB6 HgallB7 HgallB8 HgallB9 HgallB10
$frame HgallB11 HgallB12 HgallB13 HgallB14 HgallB15
$frame HgallB16
//
$frame HgallC1 HgallC2 HgallC3 HgallC4 HgallC5
$frame HgallC6 HgallC7 HgallC8 HgallC9 HgallC10
$frame HgallC11 HgallC12 HgallC13 HgallC14 HgallC15
$frame HgallC16 HgallC17 HgallC18 HgallC19 HgallC20
//
$frame Hrear1 Hrear2 Hrear3 Hrear4 Hrear5
$frame Hrear6 Hrear7 Hrear8 Hrear9 Hrear10
$frame Hrear11 Hrear12 Hrear13 Hrear14 Hrear15
$frame Hrear16 Hrear17 Hrear18 Hrear19 Hrear20
$frame Hrear21 Hrear22 Hrear23 Hrear24 Hrear25
$frame Hrear26 Hrear27 Hrear28 Hrear29 Hrear30
$frame Hrear31 Hrear32 Hrear33 Hrear34 Hrear35
$frame Hrear36 Hrear37 Hrear38 Hrear39 Hrear40
//
$frame HtranA1 HtranA2 HtranA3 HtranA4 HtranA5
$frame HtranA6 HtranA7 HtranA8 HtranA9 HtranA10
$frame HtranA11 HtranA12 HtranA13 HtranA14 HtranA15
$frame HtranA16
//
$frame HtranB1 HtranB2 HtranB3 HtranB4 HtranB5
$frame HtranB6 HtranB7 HtranB8 HtranB9 HtranB10
$frame HtranB11 HtranB12
$framevalue 0
// Rider Frames
$frame RaxeA1 RaxeA2 RaxeA3 RaxeA4 RaxeA5
$frame RaxeA6 RaxeA7 RaxeA8 RaxeA9 RaxeA10
$frame RaxeA11 RaxeA12
//
$frame RaxeB1 RaxeB2 RaxeB3 RaxeB4 RaxeB5
$frame RaxeB6 RaxeB7 RaxeB8 RaxeB9 RaxeB10
$frame RaxeB11 RaxeB12 RaxeB13 RaxeB14 RaxeB15
$frame RaxeB16
//
$frame RaxeC1 RaxeC2 RaxeC3 RaxeC4 RaxeC5
$frame RaxeC6 RaxeC7 RaxeC8 RaxeC9 RaxeC10
$frame RaxeC11 RaxeC12 RaxeC13 RaxeC14 RaxeC15
$frame RaxeC16 RaxeC17 RaxeC18 RaxeC19 RaxeC20
//
$frame RaxeD1 RaxeD2 RaxeD3 RaxeD4 RaxeD5
$frame RaxeD6 RaxeD7 RaxeD8 RaxeD9 RaxeD10
$frame RaxeD11 RaxeD12 RaxeD13 RaxeD14 RaxeD15
//
$frame RgallA1 RgallA2 RgallA3 RgallA4 RgallA5
$frame RgallA6 RgallA7 RgallA8 RgallA9 RgallA10
$frame RgallA11 RgallA12
//
$frame RgallB1 RgallB2 RgallB3 RgallB4 RgallB5
$frame RgallB6 RgallB7 RgallB8 RgallB9 RgallB10
$frame RgallB11 RgallB12 RgallB13 RgallB14 RgallB15
$frame RgallB16
//
$frame RgallC1 RgallC2 RgallC3 RgallC4 RgallC5
$frame RgallC6 RgallC7 RgallC8 RgallC9 RgallC10
$frame RgallC11 RgallC12 RgallC13 RgallC14 RgallC15
$frame RgallC16 RgallC17 RgallC18 RgallC19 RgallC20
//
$frame Rrear1 Rrear2 Rrear3 Rrear4 Rrear5
$frame Rrear6 Rrear7 Rrear8 Rrear9 Rrear10
$frame Rrear11 Rrear12 Rrear13 Rrear14 Rrear15
$frame Rrear16 Rrear17 Rrear18 Rrear19 Rrear20
$frame Rrear21 Rrear22 Rrear23 Rrear24 Rrear25
$frame Rrear26 Rrear27 Rrear28 Rrear29 Rrear30
$frame Rrear31 Rrear32 Rrear33 Rrear34 Rrear35
$frame Rrear36 Rrear37 Rrear38 Rrear39 Rrear40
//
$frame RtranA1 RtranA2 RtranA3 RtranA4 RtranA5
$frame RtranA6 RtranA7 RtranA8 RtranA9 RtranA10
$frame RtranA11 RtranA12 RtranA13 RtranA14 RtranA15
$frame RtranA16
//
$frame RtranB1 RtranB2 RtranB3 RtranB4 RtranB5
$frame RtranB6 RtranB7 RtranB8 RtranB9 RtranB10
$frame RtranB11 RtranB12
void death_missile_2(float dir);
float war_start[3] =
{
$HgallA1,
$HgallB1,
$HgallC1
};
float war_end[3] =
{
$HgallA12,
$HgallB16,
$HgallC20
};
float war_speed[3] =
{
12,
10,
6
};
// Array to align frames
float WarRiderFrames[23] =
{
$RgallA1, // Animation for fast gallop
$RgallB1, // Animation for medium gallop
$RgallC1, // Animation for slow gallop
$RtranA1, // Animation for start of rear
$Rrear1, // Animation for rear
$RtranB1, // Animation for end of rear
$RaxeA1, // Animation for attack #1
$RaxeA8, // Attack Frame 1
$RaxeA9, // Attack Frame 2
$Rrear39, // Attack Frame 1
$RaxeD1, // Standing / Attack
$RaxeD9, // Attack Frame 1
$RaxeD10, // Attack Frame 2
$RaxeD13, // Attack Frame 3
$RaxeB1, // Animation for attack #2
$RaxeB10, // Attack Frame 1
$RaxeB12, // Attack Frame 2
$RaxeB13, // Attack Frame 3
$RaxeC1, // Animation for attack #3
$RaxeC12, // Attack Frame 1
$RaxeC13, // Attack Frame 2
$RaxeC14, // Attack Frame 3
$RaxeC15 // Attack Frame 4
};
float WH_STAGE_NORMAL = 0;
float WH_STAGE_BEGIN_REAR = 1;
float WH_STAGE_MIDDLE_REAR = 2;
float WH_STAGE_END_REAR = 3;
float WH_STAGE_ATTACK = 4;
float WH_STAGE_STANDING = 5;
// Frame Code
void waraxe_touch(void)
{
if (other.health)
{
if(other.thingtype==THINGTYPE_FLESH)
{
sound(other,CHAN_AUTO,"weapons/slash.wav",1,ATTN_NORM);
MeatChunks (self.origin,randomv('-100 -100 100','100 100 300'), 2,other);
}
if(other.health<self.dmg&&other.classname=="player")
other.decap=TRUE;
// hp_save=other.health;
T_Damage (other, self, self, self.dmg);
if(self.skin==1)
MultiExplode();
// hp_save=hp_save-other.health;
// if(hp_save>0)
// warhorse_gain(hp_save);//He gets your health?
}
remove(self);
}
void waraxe_move(void)
{
vector vec;
// vector v2,v3;
// float neg_offset;
thinktime self : 0.1;
if (!self.owner.flags2 & FL_ALIVE)
{
self.velocity_z -= 20;
return;
}
if (self.lifetime < time)
{
self.velocity_z -= 20;
return;
}
if (self.enemy.health > 0)
{
HomeThink();
vec = vectoangles(self.velocity);
if (self.waraxe_horizontal)
{
self.angles_y = vec_y + 40;
self.angles_x = vec_x + self.cnt;
}
else
{
self.angles_y = vec_y + self.cnt;
}
}
}
void waraxe(entity new_target, vector offset, float horizontal)
{
entity axe;
vector vec;
if(horizontal&&random()<0.3+skill/10)
return;
axe = spawn();
axe.movetype = MOVETYPE_FLYMISSILE;
axe.solid = SOLID_BBOX;
setmodel (axe, "models/boss/waraxe.mdl");
axe.skin = 0;
setsize (axe, '0 0 0', '0 0 0');
axe.lockentity = axe.enemy = new_target;
axe.owner = self;
makevectors(self.angles);
setorigin (axe, self.origin + offset_x*v_right + offset_y*v_forward + offset_z*v_up);
sound(axe,CHAN_WEAPON,"war/fire.wav",1,ATTN_NORM);
axe.waraxe_horizontal = horizontal;
axe.th_die=SUB_Remove;
vec = offset_x*v_right + offset_y*v_forward;
vec = normalize(vec);
axe.speed=random(500,600);
axe.velocity = vec*axe.speed;
axe.angles = vectoangles(axe.velocity);
if (axe.waraxe_horizontal)
{
axe.angles_y += 40;
if (random() < 0.5)
axe.cnt = random(65,80);
else
axe.cnt = random(100,115);
axe.angles_x += axe.cnt;
axe.avelocity = '0 0 800';
axe.turn_time=2; //Lower the number, tighter the turn
axe.skin = 0;
axe.dmg=random(20,30);
}
else
{
axe.angles_x = random(-10,10);
if (random() < 0.5)
axe.cnt = random(70,80);
else
axe.cnt = random(100,110);
axe.angles_y += axe.cnt;
axe.angles_z = -90;
axe.avelocity = '0 0 800';
axe.turn_time=1; //Lower the number, tighter the turn
// 0.5 - 1
axe.skin = 1;
axe.dmg=random(60,80);
}
axe.drawflags = MLS_ABSLIGHT;
axe.abslight = 0.5;
axe.think = waraxe_move;
axe.touch = waraxe_touch;
thinktime axe : HX_FRAME_TIME;
axe.lifetime = time + 5;
}
void war_pain ()
{
if(self.pain_finished>time)
return;
sound(self,CHAN_VOICE,"war/laugh_sm.wav",1,ATTN_NONE);
self.pain_finished=time + 5;
}
void create_warrider(entity horse)
{
entity rider;
rider = spawn();
rider.solid = SOLID_NOT;
rider.movetype = MOVETYPE_NOCLIP;
rider.origin = horse.origin;
rider.angles = self.angles;
setmodel (rider, "models/boss/warrider.mdl");
setsize(rider,'0 0 0','0 0 0');
rider.skin = 0;
horse.movechain = rider;
rider.flags (+) FL_MOVECHAIN_ANGLE;
}
void warhorse_move(void);
void warhorse_rear(void)
{
float retval;
thinktime self : HX_FRAME_TIME;
if (self.monster_stage == WH_STAGE_BEGIN_REAR)
{
self.speed = self.speed / 1.2;
riderpath_move(self.speed);
retval = AdvanceFrame($HtranA1,$HtranA16);
if(self.frame==$HtranA8)
sound(self,CHAN_ITEM,"war/whinbig.wav",1,ATTN_NORM);
if (retval == AF_END)
{
sound(self,CHAN_VOICE,"war/fire_big.wav",1,ATTN_NORM);
self.monster_stage = WH_STAGE_MIDDLE_REAR;
}
self.movechain.frame = WarRiderFrames[3] + (self.frame - $HtranA1);
}
else if (self.monster_stage == WH_STAGE_MIDDLE_REAR)
{
retval = AdvanceFrame($Hrear1,$Hrear40);
if (retval == AF_END)
{
if (self.enemy != world && random() < 0.7)
self.monster_stage = WH_STAGE_STANDING;
else
self.monster_stage = WH_STAGE_END_REAR;
}
self.movechain.frame = WarRiderFrames[4] + (self.frame - $Hrear1);
if (self.movechain.frame == WarRiderFrames[9])
{
if (!self.enemy)
LocateTarget();
if (self.enemy)
waraxe(self.enemy,'1 2 70',0);
}
}
else if (self.monster_stage == WH_STAGE_STANDING)
{
retval = AdvanceFrame($HaxeD1,$HaxeD15);
if (retval == AF_END)
{
if (random() < 0.5)
self.monster_stage = WH_STAGE_END_REAR;
}
self.movechain.frame = WarRiderFrames[10] + (self.frame - $HaxeD1);
if (!self.enemy)
LocateTarget();
if (self.enemy)
{
if (self.movechain.frame == WarRiderFrames[11])
waraxe(self.enemy,'3 3 82',1);
else if (self.movechain.frame == WarRiderFrames[12])
waraxe(self.enemy,'-3 3 70',1);
else if (self.movechain.frame == WarRiderFrames[13])
waraxe(self.enemy,'-1 3 75',1);
}
}
else if (self.monster_stage == WH_STAGE_END_REAR)
{
retval = AdvanceFrame($HtranB1,$HtranB12);
if (self.frame == $HtranB4)
sound (self, CHAN_BODY, "boss/wartrot3.wav", 1, ATTN_NORM);
if (retval == AF_END)
{
self.think = warhorse_move;
self.monster_stage = WH_STAGE_NORMAL;
self.speed = war_speed[self.rider_gallop_mode];
}
else
self.speed = self.speed * 1.3;
riderpath_move(self.speed);
self.movechain.frame = WarRiderFrames[5] + (self.frame - $HtranB1);
}
}
void warhorse_move(void)
{
float retval;
if(!self.enemy.flags2&FL_ALIVE&&self.enemy!=world)
{
self.enemy=world;
sound(self,CHAN_VOICE,"war/laugh.wav",1,ATTN_NONE);
}
self.think = warhorse_move;
thinktime self : HX_FRAME_TIME;
self.movechain.angles_x = self.angles_x = 0;
self.movechain.angles_z = self.angles_z = 0;
retval = AdvanceFrame(war_start[self.rider_gallop_mode],war_end[self.rider_gallop_mode]);
if (!self.path_current)
{
riderpath_init();
}
if(random(100)==1)
sound(self,CHAN_ITEM,"war/whinny.wav",1,ATTN_NORM);
riderpath_move(self.speed);
if (retval == AF_BEGINNING)
{
retval = fabs(self.rider_y_change);
if (retval >= 15)
{
if (self.rider_gallop_mode >= 1)
self.rider_gallop_mode = 2;
else
self.rider_gallop_mode = 1;
}
else
{
if (self.rider_gallop_mode <= 1)
self.rider_gallop_mode = 0;
else
self.rider_gallop_mode = 1;
}
// Force a new gallop frame in
self.frame = war_start[self.rider_gallop_mode];
if (retval < 1 && random() < 0.1)
{
self.think = warhorse_rear;
self.monster_stage = WH_STAGE_BEGIN_REAR;
}
else if (self.rider_gallop_mode == 0)
{
if (!self.enemy)
LocateTarget();
if (self.enemy)
{
self.monster_stage = WH_STAGE_ATTACK;
}
}
else if (self.rider_gallop_mode == 1)
{
if (!self.enemy)
LocateTarget();
if (self.enemy)
{
self.monster_stage = WH_STAGE_ATTACK;
}
}
else if (self.rider_gallop_mode == 2)
{
if (!self.enemy)
LocateTarget();
if (self.enemy)
{
self.monster_stage = WH_STAGE_ATTACK;
}
}
if (self.monster_stage != WH_STAGE_BEGIN_REAR)
{
if (self.rider_gallop_mode == 0)
sound (self, CHAN_BODY, "boss/wartrot1.wav", 1, ATTN_NORM);
else if (self.rider_gallop_mode == 0)
sound (self, CHAN_BODY, "boss/wartrot2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_BODY, "boss/wartrot3.wav", 1, ATTN_NORM);
}
}
if (self.monster_stage == WH_STAGE_ATTACK)
{
if (self.rider_gallop_mode == 0)
{
self.movechain.frame = WarRiderFrames[6] +
(self.frame - war_start[self.rider_gallop_mode]);
if (self.movechain.frame == WarRiderFrames[7])
waraxe(self.enemy,'3 3 82',1);
else if (self.movechain.frame == WarRiderFrames[8])
{
waraxe(self.enemy,'-3 3 70',1);
//waraxe(self.enemy,'0 3 70',1);
}
}
else if (self.rider_gallop_mode == 1)
{
self.movechain.frame = WarRiderFrames[14] +
(self.frame - war_start[self.rider_gallop_mode]);
if (self.movechain.frame == WarRiderFrames[15])
waraxe(self.enemy,'3 3 82',1);
else if (self.movechain.frame == WarRiderFrames[16])
{
waraxe(self.enemy,'-3 3 70',1);
}
else if (self.movechain.frame == WarRiderFrames[17])
{
waraxe(self.enemy,'0 3 70',1);
}
}
else if (self.rider_gallop_mode == 2)
{
self.movechain.frame = WarRiderFrames[18] +
(self.frame - war_start[self.rider_gallop_mode]);
if (self.movechain.frame == WarRiderFrames[19])
waraxe(self.enemy,'3 3 82',1);
else if (self.movechain.frame == WarRiderFrames[20])
{
waraxe(self.enemy,'2 3 78',1);
}
else if (self.movechain.frame == WarRiderFrames[21])
{
waraxe(self.enemy,'0 3 74',1);
}
else if (self.movechain.frame == WarRiderFrames[22])
{
waraxe(self.enemy,'-3 3 70',1);
}
}
}
else
{
self.movechain.frame = WarRiderFrames[self.rider_gallop_mode] +
(self.frame - war_start[self.rider_gallop_mode]);
}
// make sure we use the last attack frame before we go out of the mode
if (retval == AF_END)
{
self.monster_stage = WH_STAGE_NORMAL;
}
if (fabs(war_speed[self.rider_gallop_mode] - self.speed) < 0.2)
self.speed = war_speed[self.rider_gallop_mode];
else if (war_speed[self.rider_gallop_mode] > self.speed)
self.speed += 0.2;
else
self.speed -= 0.2;
}
void war_wait()
{
self.think = warhorse_move;
thinktime self : 1;
}
/*QUAKED rider_war (1 0 0) (-50 -50 -24) (50 50 100) TRIGGER_WAIT
War rider monster. You must place rider_path entites
on the map. The rider will first proceed to the
rider_path point with a path_id of 1.
-------------------------FIELDS-------------------------
map: next map to go to when you kill the rider
target: start spot on the next map
--------------------------------------------------------
*/
void rider_war(void)
{
if (deathmatch)
{
remove(self);
return;
}
precache_model2 ("models/boss/warhorse.mdl");
precache_model2 ("models/boss/warrider.mdl");
precache_model2 ("models/boss/waraxe.mdl");
precache_sound2 ("war/fire_big.wav");
precache_sound2 ("war/die.wav");
precache_sound2 ("war/laugh.wav");
precache_sound2 ("war/laugh_sm.wav");
precache_sound2 ("war/fire.wav");
precache_sound2 ("war/whinny.wav");
precache_sound2 ("war/whinbig.wav");
precache_sound2 ("boss/wartrot1.wav");
precache_sound2 ("boss/wartrot2.wav");
precache_sound2 ("boss/wartrot3.wav");
rider_init();
self.noise="war/die.wav";
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
self.thingtype = THINGTYPE_FLESH;
self.monsterclass = CLASS_BOSS;
self.yaw_speed = 2;
self.experience_value = 2000;
setmodel (self, "models/boss/warhorse.mdl");
self.skin = 0;
self.flags (+) FL_MONSTER;
self.flags2(+) FL_ALIVE;
setsize (self, '-50 -50 0', '50 50 124');
self.hull = HULL_POINT;
self.health = 6000;
self.rider_gallop_mode = 2;
self.speed = war_speed[self.rider_gallop_mode];
self.rider_path_distance = 200;
self.monster_stage = WH_STAGE_NORMAL;
self.mass = 30000;
self.use = war_wait;
self.th_pain=war_pain;
create_warrider(self);
self.th_save = SUB_Null;
self.think = multiplayer_health;
thinktime self : 1;
//war_wait();
}
void rider_quake_touch(void)
{
// if (other.flags & FL_JUMPRELEASED) other.flags -= FL_JUMPRELEASED;
other.flags (-) FL_ONGROUND;
other.adjust_velocity_z = random(80,230);
other.punchangle_x = random(-4,4);
other.punchangle_y = random(-4,4);
other.punchangle_z = random(-4,4);
}
void rider_quake_think(void)
{
if (self.wrq_count <= 0)
{
self.think = self.touch = SUB_Null;
return;
}
thinktime self : HX_FRAME_TIME;
self.ltime = time;
// self.origin_z = random(-1,1);
self.velocity_z = random(-30,30);
if (self.origin_z - self.oldorigin_z > 5)
self.velocity_z = random(-15,-5);
else if (self.origin_z - self.oldorigin_z < -5)
self.velocity_z = random(5,15);
/* self.avelocity_x = random(-5,5);
if (self.angles_x > 3)
self.avelocity_x = random(-30,-10);
if (self.angles_x < -3)
self.avelocity_x = random(10,30);
self.avelocity_y = random(-5,5);
if (self.angles_y > 3)
self.avelocity_y = random(-30,-10);
if (self.angles_y < -3)
self.avelocity_y = random(10,30);
self.avelocity_z = random(-5,5);
if (self.angles_z > 3)
self.avelocity_z = random(-30,-10);
if (self.angles_z < -3)
self.avelocity_z = random(10,30);*/
}
/*QUAKED rider_quake (1 0 0) ?
-------------------------FIELDS-------------------------
--------------------------------------------------------
*/
void rider_quake(void)
{
self.solid = SOLID_BSP;
self.movetype = MOVETYPE_PUSH;
setorigin (self, self.origin);
setmodel (self, self.model);
self.oldorigin = self.origin;
self.wrq_count = 0;
if (self.abslight)
self.drawflags (+) MLS_ABSLIGHT;
}
void rider_quake_center_think(void)
{
entity item;
endeffect(MSG_ALL, self.wrq_effect_id);
item = findradius(self.origin, self.wrq_radius);
while (item)
{
if (item.classname == "rider_quake")
{
item.wrq_count -= 1;
}
item = item.chain;
}
self.think = SUB_Null;
}
void rider_quake_center_use(void)
{
entity item;
vector real_origin;
return;
if (self.think != SUB_Null)
return;
self.think = rider_quake_center_think;
thinktime self : random(7,22);
self.wrq_radius = 500;
// real_origin_x = self.absmin_x + ((self.absmax_x - self.absmin_x) / 2);
// real_origin_y = self.absmin_y + ((self.absmax_y - self.absmin_y) / 2);
// real_origin_z = self.absmin_z + ((self.absmax_z - self.absmin_z) / 2);
real_origin = self.origin;
self.wrq_effect_id = starteffect(CE_QUAKE, real_origin, (self.wrq_radius/3));
item = findradius(self.origin, self.wrq_radius);
while (item)
{
if (item.classname == "rider_quake")
{
item.think = rider_quake_think;
thinktime item : HX_FRAME_TIME;
item.ltime = time;
item.touch = rider_quake_touch;
item.wrq_count += 1;
}
item = item.chain;
}
}
/*QUAKED rider_quake_center (1 0 0) (-8 -8 -8) (8 8 8)
-------------------------FIELDS-------------------------
--------------------------------------------------------
*/
void rider_quake_center(void)
{
setorigin (self, self.origin);
setmodel (self, "models/null.spr");
self.use = rider_quake_center_use;
self.think = SUB_Null;
}