hexen2/H2MP/hcode/archer.hc
2000-11-10 00:00:00 +00:00

1177 lines
28 KiB
C++

/*
* $Header: /H2 Mission Pack/HCode/archer.hc 17 3/19/98 12:17a Mgummelt $
*/
/*
==============================================================================
Q:\art\models\monsters\archerK\final\archer.hc
==============================================================================
*/
// For building the model
$cd Q:\art\models\monsters\archerK\final
$origin 0 0 0
$base base skin
$skin skin
$flags 0
// backup anim
$frame backup1 backup2 backup3 backup4 backup5
$frame backup6 backup7 backup8
// death anim
$frame deathA1 deathA2 deathA3 deathA4 deathA5
$frame deathA6 deathA7 deathA8 deathA9 deathA10
$frame deathA11 deathA12 deathA13 deathA14 deathA15
$frame deathA16 deathA17 deathA18 deathA19 deathA20
$frame deathA21 deathA22
// draw anim
$frame draw1 draw2 draw3 draw4 draw5
$frame draw6 draw7 draw8 draw9 draw10
$frame draw11 draw12 draw13
// duck anim
$frame duck1 duck2 duck3 duck4 duck5
$frame duck6 duck7 duck8 duck9 duck10
$frame duck11 duck12 duck13 duck14
// fire anim
$frame fire1 fire2 fire3 fire4
// pain anim
$frame pain1 pain2 pain3 pain4 pain5
$frame pain6 pain7 pain8 pain9 pain10
$frame pain11 pain12 pain13 pain14 pain15
$frame pain16
// patrol anim
$frame patrol1 patrol2 patrol3 patrol4 patrol5
$frame patrol6 patrol7 patrol8 patrol9 patrol10
$frame patrol11 patrol12 patrol13 patrol14 patrol15
$frame patrol16 patrol17 patrol18 patrol19 patrol20
$frame patrol21 patrol22
// redraw anim
$frame redraw1 redraw2 redraw3 redraw4 redraw5
$frame redraw6 redraw7 redraw8 redraw9 redraw10
$frame redraw11 redraw12
// transition A anim
$frame tranA1 tranA2 tranA3 tranA4 tranA5
$frame tranA6 tranA7 tranA8 tranA9 tranA10
$frame tranA11 tranA12 tranA13
// transition B anim
$frame tranB1 tranB2 tranB3 tranB4 tranB5
$frame tranB6 tranB7 tranB8 tranB9 tranB10
$frame tranB11 tranB12 tranB13 tranB14 tranB15
$frame tranB16
// transition C anim
$frame tranC1 tranC2 tranC3 tranC4 tranC5
$frame tranC6 tranC7 tranC8 tranC9 tranC10
// transition D anim
$frame tranD1 tranD2 tranD3 tranD4 tranD5
$frame tranD6 tranD7 tranD8 tranD9
// wait A anim
$frame waitA1 waitA2 waitA3 waitA4 waitA5
$frame waitA6 waitA7 waitA8 waitA9 waitA10
$frame waitA11 waitA12 waitA13 waitA14 waitA15
$frame waitA16 waitA17 waitA18
// wait B anim
$frame waitB1 waitB2 waitB3 waitB4 waitB5
$frame waitB6 waitB7 waitB8 waitB9 waitB10
$frame waitB11 waitB12
// walk anim
$frame walk1 walk2 walk3 walk4 walk5
$frame walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15
$frame walk16
void archer_run(void);
void archer_stand(void);
void archerredraw(void);
void archerdraw(void);
void archerdrawhold(void);
void archermissile(void);
void archer_check_defense(void);
float ARCHER_STUCK = 2; // Archer can't run
float GREEN_ARROW = 0;
float RED_ARROW = 1;
float GOLD_ARROW = 2;
float BLUE_ARROW = 3;
float archer_check_shot(void)
{
vector spot1,spot2;
makevectors(self.angles);
// see if any entities are in the way of the shot
spot1 = self.origin + v_right * 10 + v_up * 36;
spot2 = self.enemy.origin + self.enemy.view_ofs;
traceline (spot1, spot2, FALSE, self);
if (trace_ent.thingtype >= THINGTYPE_WEBS)
traceline(trace_endpos, spot2, FALSE, trace_ent);
if (trace_ent != self.enemy)
{
if ((trace_ent.thingtype!=THINGTYPE_GLASS) || !trace_ent.takedamage ||
(trace_ent.flags & FL_MONSTER && trace_ent.classname!="player_sheep"))
{
return FALSE;
}
}
return TRUE;
}
void archer_duck () [++ $duck1..$duck14]
{
ai_face();
if(cycle_wrapped)
{
setsize(self,'-16 -16 0','16 16 56');
if(infront(self.enemy))
self.think=archermissile;
else
self.think=archerdrawhold;
thinktime self : 0;
return;
}
else if (self.frame==$duck1)
if (self.classname == "monster_archer")
sound (self, CHAN_VOICE, "archer/growl.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "archer/pain2.wav", 1, ATTN_NORM);
else if (self.frame == $duck5)
setsize(self,'-16 -16 0','16 16 28');
else if (self.frame==$duck7)
{
archer_check_defense();
thinktime self :0.2;
}
}
void archer_check_defense()
{
entity enemy_proj;
if(random(2)>skill/10+self.skin/2)
return;
if (self.enemy.last_attack+0.5<time&&self.oldenemy.last_attack+0.5<time)
return;
enemy_proj=look_projectiles();
if(!enemy_proj)
if(lineofsight(self,self.enemy))
{
enemy_proj=self.enemy;
self.level=vlen(self.enemy.origin-self.origin)/1000;
}
else
return;
if(mezzo_check_duck(enemy_proj))
{
if(self.think==archer_duck)
self.frame=$duck6;
else
{
self.think=archer_duck;
thinktime self : 0;
}
return;
}
}
void archer_arrow_touch(void)
{
float damg;
vector delta;
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
if (self.owner.classname == "monster_archer"||self.owner.netname=="monster_archer_ice")
damg = random(5,7);
else
{
if (self.classname == "red_arrow")
damg = random(8,12);
else // the gold arrow
damg = random(13,17);
}
if ((other.classname == "player") && (self.classname == "gold_arrow"))
{
delta = other.origin - self.origin;
other.velocity = delta * 10;
if (other.flags & FL_ONGROUND)
other.flags (-) FL_ONGROUND;
other.velocity_z = 150;
}
T_Damage (other, self, self.owner, damg );
self.origin = self.origin - 8 * normalize(self.velocity) - '0 0 40';
sound (self, CHAN_WEAPON, "weapons/explode.wav", 1, ATTN_NORM);
if (self.classname == "gold_arrow")
CreateSpark (self.origin);
else if (self.classname == "red_arrow")
CreateRedSpark (self.origin);
else if (self.classname == "blue_arrow")
CreateBSpark (self.origin);
else
CreateGreenSpark (self.origin);
remove(self);
}
void archer_dying (void) [++ $deathA1..$deathA22]
{
stopSound(self,CHAN_WEAPON);
//sound (self, CHAN_WEAPON, "misc/null.wav", 1, ATTN_NORM);
if (self.health < -80)
{
chunk_death();
remove(self);
}
if (cycle_wrapped)
{
self.frame = $deathA22;
MakeSolidCorpse();
}
}
void() archer_die =
{
// check for gib
if (self.health < -30)
{
chunk_death();
return;
}
else
{
if (self.classname == "monster_archer")
sound (self, CHAN_VOICE, "archer/death.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "archer/death2.wav", 1, ATTN_NORM);
}
archer_dying();
};
/*-----------------------------------------
archer_pain - flinch in pain
-----------------------------------------*/
void archer_pain_anim () [++ $pain1 .. $pain16]
{
if (self.frame == $pain2)
{
if (self.classname == "monster_archer")
sound (self, CHAN_VOICE, "archer/pain.wav", 1, ATTN_NORM);
else
sound (self, CHAN_VOICE, "archer/pain2.wav", 1, ATTN_NORM);
}
if (self.frame==$pain16)
{
self.pain_finished = time + random(4,6);
archerredraw();
}
}
void archer_pain (entity attacker, float damg)
{
if ((self.frame >= $pain1) && (self.frame <= $pain16)) // Still going through pain anims
return;
if (self.attack_state == AS_MISSILE)
return;
// Hurt him, will he flinch or fight back?
setsize(self,'-16 -16 0','16 16 56');
if ((self.pain_finished > time) || (random() < .5))
{
archerredraw();
}
else
archer_pain_anim();
}
void archer_launcharrow (float arrowtype,vector spot1,vector spot2)
{
self.last_attack=time;
makevectors(self.angles);
if (arrowtype==GREEN_ARROW)
{
sound (self, CHAN_WEAPON, "archer/arrowg.wav", 1, ATTN_NORM);
Create_Missile(self,spot1,spot2, "models/akarrow.mdl","green_arrow",0,1000,archer_arrow_touch);
}
else if (arrowtype==RED_ARROW)
{
sound (self, CHAN_WEAPON, "archer/arrowr.wav", 1, ATTN_NORM);
CreateRedFlash(spot1);
Create_Missile(self,spot1,spot2,"models/akarrow.mdl","red_arrow",1,1000,archer_arrow_touch);
}
else if(arrowtype==BLUE_ARROW)
{
sound (self, CHAN_WEAPON, "archer/arrowg2.wav", 1, ATTN_NORM);
Create_Missile(self,spot1,spot2,"models/akarrow2.mdl","blue_arrow",0,1000,archer_arrow_touch);
}
else
{
sound (self, CHAN_WEAPON, "archer/arrowg.wav", 1, ATTN_NORM);
CreateRedFlash(spot1);
Create_Missile(self,spot1,spot2,"models/akarrow.mdl","gold_arrow",2,1000,archer_arrow_touch);
}
newmis.drawflags(+)MLS_ABSLIGHT;
newmis.abslight=0.5;
thinktime newmis : 2.5;
}
/*-----------------------------------------
archerdrawdone - drawing his bow to fire
-----------------------------------------*/
void archerdrawdone () [-- $tranA7..$tranA1]
{
archer_check_defense();
walkmove(self.angles_y,0.5,FALSE);
if(visible(self.enemy))
ai_face();
if(cycle_wrapped)
{
self.pausetime = time + random(.5,2);
self.attack_state = AS_WAIT;
archer_run();
}
}
/*-----------------------------------------
archermissile - fire his arrow
-----------------------------------------*/
void archermissile () [++ $fire1..$fire4]
{
float enemy_range,chance,ok,tspeed;
vector spot1, spot2;
self.attack_state = AS_MISSILE;
if(visible(self.enemy))
ai_face();
else
{
self.think=self.th_run;
thinktime self : 0;
return;
}
if (self.frame == $fire2) // FIRE!!!!
{
makevectors(self.angles);
spot1 = self.origin + v_forward*4 + v_right * 10 + v_up * 36;
if(self.classname=="monster_archer_lord"||(self.netname=="monster_archer_ice"&&random()<0.3))
{
tspeed=vlen(self.enemy.velocity);
if(tspeed>100)
spot2=extrapolate_pos_for_speed(spot1,1000,self.enemy,0.3);
}
if(spot2=='0 0 0')
{
spot2 = self.enemy.origin + self.enemy.view_ofs;
traceline (spot1, spot2, FALSE, self);
if(trace_ent.thingtype>=THINGTYPE_WEBS)
traceline (trace_endpos, spot2, FALSE, trace_ent);
if (trace_ent == self.enemy)
ok=TRUE;
else if((trace_ent.health<=25||trace_ent.thingtype>=THINGTYPE_WEBS)&&trace_ent.takedamage&&(!trace_ent.flags&FL_MONSTER||trace_ent.classname=="player_sheep"))
ok=TRUE;
}
else
ok=TRUE;
if(ok)
{
enemy_range = range(self.enemy);
if (enemy_range < RANGE_MELEE) // Which arrow to use?
chance = 0.80;
else if (enemy_range < RANGE_NEAR)
chance = 0.50;
else if (enemy_range < RANGE_MID)
chance = 0.30;
else if (enemy_range < RANGE_FAR)
chance = 0.10;
if (self.netname=="monster_archer_ice")
archer_launcharrow(BLUE_ARROW,spot1,spot2);
else if (self.classname=="monster_archer")
{
if (random(1) < chance)
archer_launcharrow(RED_ARROW,spot1,spot2);
else
archer_launcharrow(GREEN_ARROW,spot1,spot2);
}
else // Archer Lord
{
if (random(1) < chance)
archer_launcharrow(GOLD_ARROW,spot1,spot2);
else
archer_launcharrow(RED_ARROW,spot1,spot2);
}
if(skill>=4)
self.attack_finished=0;
else
self.attack_finished = time + random(.5,1);
if(!self.skin)
chance-=0.3;
chance+=skill/10;
// Reattack?
if (random () > chance) // Is he done?
archerdrawdone();
}
else
{
if(skill>=4)
self.attack_finished=0;
else
self.attack_finished = time + random();
stopSound(self,CHAN_WEAPON);
//sound (self, CHAN_WEAPON, "misc/null.wav", 1, ATTN_NORM);
archer_run();
return;
}
}
if(cycle_wrapped)
{
self.frame = $draw10 ;
archerredraw();
}
else if(visible(self.enemy))
ai_face();
}
/*-----------------------------------------
archerredraw - redrawing his bow to fire
-----------------------------------------*/
void archerredraw () [++ $redraw1..$redraw12]
{
self.attack_state = AS_MISSILE;
archer_check_defense();
if (self.frame == $redraw8)
sound (self, CHAN_WEAPON, "archer/draw.wav", 1, ATTN_NORM);
if (cycle_wrapped)
archermissile();
else if(visible(self.enemy))
ai_face();
else
{
self.think=self.th_run;
thinktime self : 0;
return;
}
}
/*-----------------------------------------
archerdrawhold - waiting for right chance to attack
-----------------------------------------*/
void archerdrawhold ()
{
float chance,startframe,endframe;
if(visible(self.enemy))
ai_face();
else
{
self.think=self.th_run;
thinktime self : 0;
return;
}
archer_check_defense();
startframe=$waitB1;
endframe=$waitB12;
if (!self.spawnflags & ARCHER_STUCK)
{
if (vlen(self.enemy.origin - self.origin)<=200)
{
if(infront(self.enemy))
if(walkmove(self.angles_y+180,3,FALSE))
{
startframe=$backup1;
endframe=$backup8;
}
}
}
AdvanceFrame(startframe,endframe);
self.think=archerdrawhold;
thinktime self : 0.05;
enemy_range = range(self.enemy);
if (enemy_range < RANGE_NEAR && random() < 0.4)
archermissile();
else if (cycle_wrapped||random()<skill/20+self.skin/10)
{
if (!archer_check_shot())
{
stopSound(self,CHAN_WEAPON);
//sound (self, CHAN_WEAPON, "misc/null.wav", 1, ATTN_NORM);
self.attack_state = AS_STRAIGHT;
self.think = archer_run;
thinktime self : HX_FRAME_TIME;
return;
}
if (self.classname == "monster_archer") // Monster archer's not so smart
{
if (enemy_range <= RANGE_MELEE)
chance = 1;
else if (enemy_range <= RANGE_NEAR)
chance = 0.70;
else if (enemy_range <= RANGE_MID)
chance = 0.60;
else if (enemy_range <= RANGE_FAR)
chance = 0.50;
}
else
chance = 1;
if (random() < chance)
archermissile();
}
}
/*-----------------------------------------
archerdraw - drawing his bow to fire
-----------------------------------------*/
void archerdraw () [++ $tranA1..$tranA13]
{
archer_check_defense();
if (self.frame == $tranA1) // See if he should even try to shoot
{
if (!archer_check_shot())
{
self.attack_state = AS_STRAIGHT;
self.think = archer_run;
thinktime self : HX_FRAME_TIME;
return;
}
}
if (self.frame == $tranA6)
sound (self, CHAN_WEAPON, "archer/draw.wav", 1, ATTN_NORM);
if ((self.frame >= $tranA1) && (self.frame <= $tranA13))
walkmove(self.angles_y+180,.28,FALSE);
if (cycle_wrapped) // Archer has drawn the arrow
archerdrawhold();
else if (visible(self.enemy))
ai_face();
else
{
self.think=self.th_run;
thinktime self : 0;
return;
}
if ((random(1)<.10) && (self.frame == $walk1))
{
if(self.netname=="monster_archer_ice")
sound (self, CHAN_BODY, "archer/growl4.wav", 1, ATTN_NORM);
else if (self.classname == "monster_archer")
sound (self, CHAN_BODY, "archer/growl.wav", 1, ATTN_NORM);
else
{
if (random() < .70)
sound (self, CHAN_BODY, "archer/growl2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_BODY, "archer/growl3.wav", 1, ATTN_NORM);
}
}
}
/*-----------------------------------------
archer_run - run towards the enemy
-----------------------------------------*/
void archer_run(void)
{
self.think = archer_run;
thinktime self : HX_FRAME_TIME;
archer_check_defense();
if ((random(1)<.10) && (self.frame == $walk1))
{
if(self.netname=="monster_archer_ice")
sound (self, CHAN_BODY, "archer/growl4.wav", 1, ATTN_NORM);
else if (self.classname == "monster_archer")
sound (self, CHAN_VOICE, "archer/growl.wav", 1, ATTN_NORM);
else
{
if (random() < .70)
sound (self, CHAN_BODY, "archer/growl2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_BODY, "archer/growl3.wav", 1, ATTN_NORM);
}
}
if ((self.spawnflags & ARCHER_STUCK) || (self.attack_state == AS_WAIT))
{
AdvanceFrame($waitA1,$waitA18);
ai_run(0);
}
else
{
AdvanceFrame($walk1,$walk16);
ai_run(self.speed*2);
}
}
/*-----------------------------------------
archer_walk - walking his beat
-----------------------------------------*/
void archer_walk(void) [++ $patrol1..$patrol22]
{
thinktime self : HX_FRAME_TIME + .01; // Make him move a little slower so his run will look faster
archer_check_defense();
if ((random()<.05) && (self.frame == $patrol1))
{
if(self.netname=="monster_archer_ice")
sound (self, CHAN_BODY, "archer/growl4.wav", 1, ATTN_NORM);
else if (self.classname == "monster_archer")
sound (self, CHAN_VOICE, "archer/growl.wav", 1, ATTN_NORM);
else
{
if (random() < .70)
sound (self, CHAN_BODY, "archer/growl2.wav", 1, ATTN_NORM);
else
sound (self, CHAN_BODY, "archer/growl3.wav", 1, ATTN_NORM);
}
}
if (self.spawnflags & ARCHER_STUCK) // No moving
{
self.frame = $patrol1; // FIXME: this should be the wait animations
ai_walk(0);
}
else
ai_walk(self.speed);
}
/*-----------------------------------------
archer_stand - standing and waiting
-----------------------------------------*/
void archer_stand(void) [++ $waitA1..$waitA18]
{
if (random()<0.5)
{
archer_check_defense();
ai_stand();
}
}
/*QUAKED monster_archer (1 0.3 0) (-16 -16 0) (16 16 50) AMBUSH STUCK JUMP x DORMANT NO_DROP FROZEN
The Archer Knight monster
-------------------------FIELDS-------------------------
Health : 80
Experience Pts: 25
Favorite TV shows: Friends & Baywatch
Favorite Color: Blue
Likes: Shooting arrows into people and long walks along the beach
Dislikes: Anything having to do with Pauly Shore
--------------------------------------------------------
*/
void monster_archer ()
{
if (deathmatch)
{
remove(self);
return;
}
if(!self.th_init)
{
self.th_init=monster_archer;
self.init_org=self.origin;
}
if (!self.flags2 & FL_SUMMONED&&!self.flags2&FL2_RESPAWN)
{
precache_archer();
}
if(!self.health)
self.health = 80;
if(!self.max_health)
self.max_health=self.health;
if(self.netname=="monster_archer_ice")
CreateEntityNew(self,ENT_ARCHER,"models/archer2.mdl",archer_die);
else
CreateEntityNew(self,ENT_ARCHER,"models/archer.mdl",archer_die);
self.th_stand = archer_stand;
self.th_walk = archer_walk;
self.th_run = archer_run;
self.th_melee = archerdraw;
self.th_missile = archerdraw;
self.th_pain = archer_pain;
self.decap = 0;
if(!self.speed)
self.speed=2.3;
if(!self.yaw_speed)
self.yaw_speed = 10;
self.headmodel = "models/archerhd.mdl";
if(!self.spawnflags&ARCHER_STUCK)
self.mintel = 7;
self.monsterclass = CLASS_GRUNT;
self.experience_value = self.init_exp_val = 25;
self.flags (+) FL_MONSTER;
self.view_ofs = '0 0 40';
self.hull=HULL_PLAYER;
walkmonster_start();
}
/*QUAKED monster_archer_lord (1 0.3 0) (-16 -16 0) (16 16 50) AMBUSH STUCK JUMP x DORMANT NO_DROP FROZEN
The Archer Lord monster
-------------------------FIELDS-------------------------
Health : 325
Experience Pts: 200
Favorite Cities: Madrid & Las Vegas
Favorite Flower: Orchid
What people don't know about me: I cry at sad movies
What people say when they see me: Don't shoot!! Don't shoot!!
--------------------------------------------------------
*/
void monster_archer_lord ()
{
if (deathmatch)
{
remove(self);
return;
}
if(!self.th_init)
{
self.th_init=monster_archer_lord;
self.init_org=self.origin;
}
if (!self.flags2 & FL_SUMMONED&&!self.flags2&FL2_RESPAWN)
{
precache_model("models/archer.mdl");
precache_model("models/archerhd.mdl");
precache_model("models/gspark.spr");
precache_sound ("archer/arrowg.wav");
precache_sound ("archer/arrowr.wav");
precache_sound ("archer/growl2.wav");
precache_sound ("archer/growl3.wav");
precache_sound ("archer/growl4.wav");
precache_sound ("archer/pain2.wav");
precache_sound ("archer/sight2.wav");
precache_sound ("archer/death2.wav");
precache_sound ("archer/draw.wav");
}
if(!self.experience_value)
self.experience_value = 200;
if(!self.health)
self.health = 325;
CreateEntityNew(self,ENT_ARCHER,"models/archer.mdl",archer_die);
self.th_stand = archer_stand;
self.th_walk = archer_walk;
self.th_run = archer_run;
self.th_melee = archerdraw;
self.th_missile = archerdraw;
self.th_pain = archer_pain;
self.decap = 0;
self.headmodel = "models/archerhd.mdl";
if(!self.spawnflags&ARCHER_STUCK)
self.mintel = 7;
if(!self.speed)
self.speed=2.3;
self.monsterclass = CLASS_HENCHMAN;
self.skin = 1;
self.flags (+) FL_MONSTER;
self.yaw_speed = 10;
self.view_ofs = '0 0 40';
self.init_exp_val = self.experience_value;
walkmonster_start();
}
/*QUAKED monster_archer_ice (1 0.3 0) (-16 -16 0) (16 16 50) AMBUSH STUCK JUMP x DORMANT NO_DROP FROZEN
The Archer monster with snow booties
-------------------------FIELDS-------------------------
Health : 80
Experience Pts: 25
Favorite TV shows: Northern Exposure
Favorite Color: Off-White
Likes: Shooting arrows into people and ice fishing
Dislikes: Sunshine and happiness
--------------------------------------------------------
*/
void monster_archer_ice ()
{
if(!self.th_init)
{
self.th_init=monster_archer_ice;
self.init_org=self.origin;
}
self.netname=self.classname;
self.classname="monster_archer";
monster_archer();
}
/*
=================
ArcherCheckAttack
=================
*/
/*
float ArcherCheckAttack (void)
{
local vector spot1, spot2;
local entity targ;
local float chance;
// if (enemy_range <= RANGE_MELEE) // Enemy is too close...attack
// {
// self.attack_state = AS_MISSILE;
self.pain_finished = 0;
// self.attack_finished = 0;
// }
if (self.attack_finished > time)
return FALSE;
if (!enemy_vis)
return FALSE;
if (enemy_range == RANGE_FAR)
{
if (self.attack_state != AS_STRAIGHT)
{
self.attack_state = AS_STRAIGHT;
archer_run ();
}
return FALSE;
}
targ = self.enemy;
makevectors(self.angles);
// see if any entities are in the way of the shot
spot1 = self.origin + v_right * 10 + v_up * 36;
spot2 = targ.origin + targ.view_ofs;
traceline (spot1, spot2, FALSE, self);
if(trace_ent.thingtype>=THINGTYPE_WEBS)
traceline (trace_endpos, spot2, FALSE, trace_ent);
if (trace_ent != targ)
if((trace_ent.health>25&&trace_ent.thingtype!=THINGTYPE_GLASS)||!trace_ent.takedamage||(trace_ent.flags&FL_MONSTER&&trace_ent.classname!="player_sheep"))
{
self.attack_state = AS_STRAIGHT;
return FALSE;
}
// Chances of attack
// 50% at MID range
// 65% at NEAR range
// 80% at MELEE range
enemy_range = range(self.enemy);
if (enemy_range == RANGE_MELEE)
chance = 0.40;
else if (enemy_range == RANGE_NEAR)
chance = 0.3;
else if (enemy_range == RANGE_MID)
chance = 0.2;
else
chance = 0;
if ((random () < chance) && (self.attack_state != AS_MISSILE)) // Will he attack?
{
self.attack_state = AS_MISSILE;
return TRUE;
}
if (enemy_range == RANGE_MID)
{
if (random (1) < .5) // Will he side step?
self.attack_state = AS_SLIDING;
else
self.attack_state = AS_STRAIGHT;
}
else
{
if (self.attack_state != AS_SLIDING)
self.attack_state = AS_SLIDING;
}
return FALSE;
}
*/
/*
* $Log: /H2 Mission Pack/HCode/archer.hc $
*
* 17 3/19/98 12:17a Mgummelt
* last bug fixes
*
* 16 3/13/98 3:27a Mgummelt
* Replaced all sounds that played a null.wav with stopSound commands
*
* 15 3/09/98 3:05p Mgummelt
*
* 14 3/04/98 3:39p Mgummelt
*
* 13 3/03/98 7:31p Mgummelt
*
* 12 2/27/98 11:52a Mgummelt
*
* 11 2/25/98 6:10p Mgummelt
*
* 10 2/12/98 5:55p Jmonroe
* remove unreferenced funcs
*
* 9 2/05/98 12:30p Mgummelt
*
* 8 2/04/98 4:58p Mgummelt
* spawnflags on monsters cleared out
*
* 7 1/20/98 10:58a Mgummelt
*
* 6 1/19/98 6:20p Mgummelt
*
* 5 1/16/98 11:11a Mgummelt
*
* 4 1/14/98 7:43p Mgummelt
*
* 104 10/30/97 2:29p Jheitzman
*
* 103 10/29/97 4:05p Mgummelt
*
* 102 10/28/97 1:00p Mgummelt
* Massive replacement, rewrote entire code... just kidding. Added
* support for 5th class.
*
* 100 9/09/97 11:48a Rlove
*
* 99 9/03/97 9:14p Mgummelt
* Fixing targetting AI
*
* 98 9/02/97 7:02p Mgummelt
*
* 96 9/02/97 6:33p Mgummelt
*
* 95 9/02/97 4:15p Rlove
*
* 94 9/01/97 12:07a Mgummelt
*
* 93 8/31/97 11:33p Mgummelt
*
* 92 8/30/97 6:58p Mgummelt
*
* 91 8/30/97 12:22a Rjohnson
* Precaching for monster spawners
*
* 90 8/29/97 4:17p Mgummelt
* Long night
*
* 89 8/29/97 3:04a Mgummelt
*
* 88 8/29/97 1:00a Mgummelt
*
* 87 8/27/97 10:52p Mgummelt
*
* 86 8/27/97 8:11p Mgummelt
*
* 84 8/27/97 7:07p Mgummelt
*
* 83 8/27/97 4:17p Mgummelt
*
* 82 8/26/97 6:44p Jweier
*
* 78 8/26/97 9:00a Mgummelt
*
* 77 8/23/97 4:26p Rlove
*
* 76 8/21/97 10:05a Rlove
*
* 75 8/20/97 11:35p Mgummelt
*
* 74 8/20/97 8:07p Rlove
*
* 73 8/20/97 6:30a Rlove
*
* 69 8/19/97 4:14p Rlove
*
* 64 7/24/97 3:53p Rlove
*
* 62 7/21/97 3:03p Rlove
*
* 60 7/18/97 11:44a Rlove
*
* 57 7/15/97 7:21p Rlove
*
* 56 7/15/97 9:08a Rlove
*
* 55 7/12/97 9:09a Rlove
* Reworked Assassin Punch Dagger
*
* 51 7/03/97 5:06p Rlove
*
* 50 7/03/97 8:47a Rlove
*
* 47 6/30/97 9:41a Rlove
*
* 46 6/27/97 10:18a Rlove
* Monsters drop stuff on death
*
* 45 6/25/97 9:48a Rlove
*
* 44 6/20/97 8:25a Rlove
*
* 43 6/19/97 4:43p Rlove
* Now he's got an attitude.
*
* 40 6/19/97 9:13a Rlove
*
* 38 6/19/97 8:50a Rlove
*
* 37 6/18/97 4:30p Rlove
* Rewrote entity spawning code
*
* 36 6/17/97 10:20a Rlove
*
* 35 6/16/97 9:12a Rlove
* Doesn't growl so much anymore
*
* 34 6/15/97 3:01p Mgummelt
*
* 33 6/14/97 1:12p Rlove
*
* 32 6/12/97 12:13p Rlove
* Archer arrows generate red or green sparks
*
* 31 6/11/97 6:08p Rlove
*
* 30 6/11/97 9:57a Rlove
* Added sounds to the old boy.
*
* 29 6/02/97 7:58p Mgummelt
*
* 28 5/23/97 3:43p Mgummelt
*
* 27 5/22/97 6:30p Mgummelt
*
* 26 5/22/97 3:29p Mgummelt
*
* 25 5/20/97 8:42a Rlove
*
* 24 5/19/97 11:36p Mgummelt
*
* 23 5/16/97 2:12p Mgummelt
*
* 22 5/13/97 2:26p Rlove
*
* 19 5/12/97 11:06a Rlove
*
* 18 5/12/97 10:31a Rlove
*
* 14 5/07/97 11:03a Rlove
*
* 12 5/02/97 11:50a Rlove
*
* 11 4/29/97 4:08p Rlove
*
* 10 4/21/97 8:47p Mgummelt
*
* 9 4/21/97 6:14p Mgummelt
*
* 8 3/21/97 9:38a Rlove
* Created CHUNK.HC and MATH.HC, moved brush_die to chunk_death so others
* can use it.
*
* 7 3/20/97 12:31p Rlove
* More updates to monster AI
*
* 6 3/12/97 4:23p Rlove
* New Monster AI
*
* 5 3/10/97 8:29a Rlove
* Halfway through rewriting Monster AI
*
* 4 3/04/97 3:57p Aleggett
* Added done_precache checking for monster spawner
*
* 3 2/26/97 3:14p Rlove
* Changes to basic monster ai
*
* 2 2/19/97 11:58a Rlove
*
* 1 2/19/97 10:01a Rlove
*/