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

1230 lines
31 KiB
C++

/*
YAKMAN.HC
MG
*/
//
$frame bwalk1 bwalk2 bwalk3 bwalk4 bwalk5
$frame bwalk6 bwalk7 bwalk8 bwalk9 bwalk10
$frame bwalk11 bwalk12 bwalk13 bwalk14 bwalk15
$frame bwalk16 bwalk17 bwalk18 bwalk19 bwalk20
$frame bwalk21 bwalk22 bwalk23 bwalk24
//
$frame charge1 charge2 charge3 charge4 charge5
$frame charge6 charge7 charge8 charge9 charge10
$frame charge11 charge12
//
$frame death1 death2 death3 death4 death5
$frame death6 death7 death8 death9 death10
$frame death11 death12 death13 death14 death15
$frame death16 death17 death18 death19 death20
$frame death21 death22 death23 death24 death25
//
$frame gorech1 gorech2 gorech3 gorech4 gorech5
$frame gorech6 gorech7 gorech8 gorech9 gorech10
$frame gorech11 gorech12
//
$frame howl1 howl2 howl3 howl4 howl5
$frame howl6 howl7 howl8 howl9 howl10
$frame howl11 howl12 howl13 howl14 howl15
$frame howl16 howl17 howl18 howl19 howl20
$frame howl21 howl22 howl23 howl24 howl25
$frame howl26 howl27 howl28 howl29 howl30
$frame howl31 howl32 howl33 howl34 howl35
$frame howl36
//
$frame jump1 jump2 jump3 jump4 jump5
$frame jump6 jump7 jump8 jump9 jump10
$frame jump11 jump12 jump13 jump14 jump15
$frame jump16 jump17 jump18 jump19 jump20
$frame jump21 jump22 jump23 jump24
//
$frame pain1 pain2 pain3 pain4 pain5
$frame pain6 pain7 pain8
//
$frame shake1 shake2 shake3 shake4 shake5
$frame shake6 shake7 shake8 shake9 shake10
$frame shake11 shake12 shake13 shake14 shake15
$frame shake16 shake17 shake18 shake19 shake20
//
$frame shard1 shard2 shard3 shard4 shard5
$frame shard6 shard7 shard8 shard9 shard10
$frame shard11 shard12 shard13 shard14 shard15
$frame shard16 shard17 shard18 shard19 shard20
$frame shard21 shard22 shard23 shard24 shard25
$frame shard26 shard27 shard28 shard29 shard30
$frame shard31 shard32
//
$frame slidel1 slidel2 slidel3 slidel4 slidel5
//
$frame slider1 slider2 slider3 slider4 slider5
//
$frame wait1 wait2 wait3 wait4 wait5
$frame wait6 wait7 wait8 wait9 wait10
$frame wait11 wait12 wait13 wait14 wait15
$frame wait16 wait17 wait18 wait19 wait20
$frame wait21 wait22 wait23 wait24
//
$frame walk1 walk2 walk3 walk4 walk5
$frame walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15
$frame walk16 walk17 walk18 walk19 walk20
$frame walk21 walk22 walk23 walk24
/*
$frame charge wait walk
//
$frame charge01 charge02 charge03 charge04 charge05
$frame charge06 charge07 charge08 charge09 charge10
$frame charge11 charge12
//
$frame wait01 wait02 wait03 wait04 wait05
$frame wait06 wait07 wait08 wait09 wait10
$frame wait11 wait12 wait13 wait14 wait15
$frame wait16 wait17 wait18 wait19 wait20
$frame wait21 wait22 wait23 wait24
//
$frame walk1 walk2 walk3 walk4 walk5
$frame walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15
$frame walk16 walk17 walk18 walk19 walk20
$frame walk21 walk22 walk23 walk24
//
$frame death01 death02 death03 death04 death05
$frame death06 death07 death08 death09 death10
$frame death11 death12 death13 death14 death15
$frame death16 death17 death18 death19 death20
$frame death21 death22 death23 death24 death25
//
$frame gorech01 gorech02 gorech03 gorech04 gorech05
$frame gorech06 gorech07 gorech08 gorech09 gorech10
$frame gorech11 gorech12
//
$frame howl01 howl02 howl03 howl04 howl05
$frame howl06 howl07 howl08 howl09 howl10
$frame howl11 howl12 howl13 howl14 howl15
$frame howl16 howl17 howl18 howl19 howl20
$frame howl21 howl22 howl23 howl24 howl25
$frame howl26 howl27 howl28 howl29 howl30
$frame howl31 howl32 howl33 howl34 howl35
$frame howl36
//
$frame jump01 jump02 jump03 jump04 jump05
$frame jump06 jump07 jump08 jump09 jump10
$frame jump11 jump12 jump13 jump14 jump15
$frame jump16 jump17 jump18 jump19 jump20
$frame jump21 jump22 jump23 jump24
//
$frame pain1 pain2 pain3 pain4 pain5
$frame pain6 pain7 pain8
//
$frame shake01 shake02 shake03 shake04 shake05
$frame shake06 shake07 shake08 shake09 shake10
$frame shake11 shake12 shake13 shake14 shake15
$frame shake16 shake17 shake18 shake19 shake20
//
$frame shard01 shard02 shard03 shard04 shard05
$frame shard06 shard07 shard08 shard09 shard10
$frame shard11 shard12 shard13 shard14 shard15
$frame shard16 shard17 shard18 shard19 shard20
$frame shard21 shard22 shard23 shard24 shard25
$frame shard26 shard27 shard28 shard29 shard30
$frame shard31 shard32
//
$frame slidel1 slidel2 slidel3 slidel4 slidel5
//
$frame slider1 slider2 slider3 slider4 slider5
*/
//void() yakman_skid;
//void() yakman_block;
//void() yakman_block_wait;
//void() yakman_jump;
//void() yakman_roar;
void() yakman_in_air;
//void() yakman_run_loop;
//void()yakman_charge;
void yakman_idle_sound ()
{
string soundstr;
if(self.invisible_finished>time)
return;
self.invisible_finished=time+1;
if(random()<0.5)
soundstr="yakman/snort1.wav";
else
soundstr="yakman/snort2.wav";
sound(self,CHAN_VOICE,soundstr,1,ATTN_NORM);
}
void yakman_step_right2 ()
{
vector rollangle;
makevectors(self.angles);
rollangle=vectoangles(v_right);
if(walkmove(rollangle_y,10-self.cnt/2,FALSE))
{
particle(self.origin-v_right*(10 - self.cnt/2), '0 0 70', 344, 10);
if(random()<0.2)
CreateWhiteSmoke(self.origin-v_right*(10-self.cnt/2),'0 0 8',HX_FRAME_TIME * 2);
}
if(self.cnt==17)
{
self.cnt=0;
thinktime self : 0;
if(!self.flags&FL_ONGROUND)
self.think=yakman_in_air;
else
self.think=self.th_run;
}
else
{
self.cnt+=1;
self.think=yakman_step_right2;
thinktime self : 0.05;
}
}
void yakman_step_right1 () [++ $slider1 .. $slider5]
{
vector rollangle;
makevectors(self.angles);
rollangle=vectoangles(v_right);
walkmove(rollangle_y,10,FALSE);
if(self.frame==$slider5)
{
thinktime self : 0.05;
self.think=yakman_step_right2;
sound(self,CHAN_AUTO,"mezzo/skid.wav",1,ATTN_NORM);
}
}
void yakman_step_left2 ()
{
vector rollangle;
makevectors(self.angles);
rollangle=vectoangles(v_right);
if(walkmove(rollangle_y,-10+self.cnt/2,FALSE))
{
particle(self.origin+v_right*(10-self.cnt/2), '0 0 70', 344, 10);
if(random()<0.2)
CreateWhiteSmoke(self.origin+v_right*(10-self.cnt/2),'0 0 8',HX_FRAME_TIME * 2);
}
if(self.cnt==17)
{
self.cnt=0;
thinktime self : 0;
if(!self.flags&FL_ONGROUND)
self.think=yakman_in_air;
else
self.think=self.th_run;
}
else
{
self.cnt+=1;
self.think=yakman_step_left2;
thinktime self : 0.05;
}
}
void yakman_step_left1 () [++ $slidel1 .. $slidel5]
{
vector rollangle;
makevectors(self.angles);
rollangle=vectoangles(v_right);
walkmove(rollangle_y,-10,FALSE);
if(self.frame==$slidel5)
{
thinktime self : 0.05;
self.think=yakman_step_left2;
sound(self,CHAN_AUTO,"mezzo/skid.wav",1,ATTN_NORM);
}
}
void yakman_choose_step (entity proj)
{//FIXME: Check to see if the enemy is infront or behind?
float proj_dir;
proj_dir=check_heading_left_or_right(proj);
if(proj_dir==0)
proj_dir=random(300) - 150;
//FIXME: Probably shouldn't try to roll in the other direction
makevectors(self.angles);
if(solid_under(self.origin, self.origin+v_right*105*proj_dir))
tracearea(self.origin, self.origin+v_right*105*proj_dir,self.mins,self.maxs,FALSE,self);
else
trace_fraction=FALSE;
if(trace_fraction==1)
{
traceline(trace_endpos, trace_endpos-'0 0 300',TRUE,self);
if(pointcontents(trace_endpos)!=CONTENT_EMPTY)
trace_fraction=FALSE;
else
trace_fraction=TRUE;
}
if(trace_fraction==1)
{
if(proj_dir>0)
{
thinktime self : 0;
self.think=yakman_step_right1;
}
else
{
thinktime self : 0;
self.think=yakman_step_left1;
}
return;
}
}
void yakman_block() [++ $bwalk1 .. $bwalk24]
{//FIXME, maybe deflect stuff?
self.cnt+=1;
walkmove(self.angles_y,3,FALSE);
if(self.cnt>=11)
{
self.cnt=0;
self.takedamage=DAMAGE_YES;
self.think=self.th_run;//FIXME: check defense again?
}
}
void yakman_check_defense ()
{
if((self.enemy.last_attack+0.5<time&&self.oldenemy.last_attack+0.5<time)||self.aflag)
return;
entity enemy_proj;
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(!infront(enemy_proj))
return;
if(random()<0.3)
{
self.touch=SUB_Null;
self.weaponframe_cnt=0;
yakman_choose_step(enemy_proj);
}
else if(self.frame>=$walk5 &&self.frame<=$walk10)
{
self.touch=SUB_Null;
self.weaponframe_cnt=0;
self.takedamage=DAMAGE_NO;
self.frame=$bwalk7;
self.think=yakman_block;
thinktime self : 0;
}
else if(self.frame>=$walk17 &&self.frame<=$walk22)
{
self.touch=SUB_Null;
self.weaponframe_cnt=0;
self.takedamage=DAMAGE_NO;
self.frame=$bwalk19;
self.think=yakman_block;
thinktime self : 0;
}
else
return;
}
void yakman_charge_stop () [++ $gorech1 .. $gorech12]
{
if(cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
}
void yakman_slam (entity loser)
{
if(!loser.takedamage)
return;
if(!loser.movetype||loser.mass>100||(loser.solid==SOLID_BSP&&!loser.takedamage))
return;
if(!infront(loser)||loser.safe_time>time)
return;
if(loser.solid!=SOLID_BSP)
if(loser.origin_z>self.absmax_z - 6||loser.absmax_z<self.origin_z + 6)
return;
float inertia;
vector punchdir,meat_spot,throwdir;
//Head rear anim
sound(self,CHAN_BODY,"yakman/slam.wav",1,ATTN_NORM);
sound(self,CHAN_VOICE,"yakman/grunt.wav",1,ATTN_NORM);
if(loser.mass<10)
inertia=1;
else
inertia=loser.mass/10;
makevectors(self.angles);
punchdir=v_forward*300+'0 0 300';
T_Damage(loser,self,self,5*(self.skin+2)*(self.aflag+1)*(coop + 1));
meat_spot=loser.origin;
meat_spot_z=self.origin_z+50;
MeatChunks (meat_spot,v_right*random(-200,200)+'0 0 200',3,loser);
MeatChunks (meat_spot,v_right*random(-200,200)+'0 0 200',3,loser);
MeatChunks (meat_spot,v_right*random(-200,200)+'0 0 200',3,loser);
SpawnPuff (meat_spot, '0 0 0', 20,loser);
throwdir=punchdir*(1/inertia);
if(loser.flags2&FL_ALIVE)
{
if(loser.velocity_z<throwdir_z)
loser.velocity_z=throwdir_z;//so you don't throw them too high
}
else
loser.velocity_z=throwdir_z*random(1,2);//so you don't throw them too high
loser.velocity_x+=throwdir_x;
loser.velocity_y+=throwdir_y;
loser.flags(-)FL_ONGROUND;
self.ltime+=1;
loser.safe_time=time+.1;//So can't kill them instantly if they're moving against him or pinned on a wall
if(self.think!=yakman_charge_stop)
{
thinktime self : 0;
self.think=yakman_charge_stop;
self.touch=SUB_Null;
}
}
void yakman_touch ()
{
yakman_slam(other);
}
void yakman_die2 () [++ $death1 .. $death25]
{
if (self.health < -40)
{
chunk_death();
return;
}
else if(self.frame==$death15)
sound(self,CHAN_BODY,"player/land.wav",1,ATTN_NORM);
else if(self.frame==$death25)
self.think=MakeSolidCorpse;
}
void yakman_die () [++ $howl1 .. $howl12]
{
if (self.health < -40)
{
chunk_death();
return;
}
if(cycle_wrapped)
yakman_die2();
else if(self.frame==$howl1)
sound(self,CHAN_VOICE,"yakman/die.wav",1,ATTN_NORM);
}
void yakman_flinch ()
{
ai_back(1);
GolemFlinch(12,35);
self.touch=SUB_Null;
self.think=self.th_run;
thinktime self : 0.05;
}
void yakman_pain_seq () [++ $pain1 .. $pain8]
{
ai_back(1);
if(self.frame==$pain1)
self.touch=SUB_Null;
else if(self.frame==$pain8)
{
self.think=self.th_run;
thinktime self : 0.05;
}
}
void yakman_shakeoff () [++ $shake1 .. $shake20]
{
if(self.frame==$shake1)
self.touch=SUB_Null;
else if(self.frame==$shake20)
{
self.think=self.th_run;
thinktime self : 0.05;
}
}
void yakman_pain (entity attacker, float damage)
{
// if(self.monster_awake)
if(!self.enemy||!visible(self.enemy)||(world.model=="maps/monsters.bsp"&&random()<0.2&&self.enemy.enemy!=self))//Last part for The PIT!!!
{
if(self.enemy!=world&&self.enemy!=attacker)
self.oldenemy=self.enemy;
self.enemy=attacker;
}
if(random()*self.health>damage||self.pain_finished>time)//only react to 33 percent of current health damage
return;
self.cnt=0;
self.monster_awake=TRUE;
self.weaponframe_cnt=self.level=0;//If interrupted in attack
sound(self,CHAN_VOICE,"yakman/pain.wav",1,ATTN_NORM);
self.pain_finished=time+1+self.skin/2;
if(random()*self.health>damage*2)
self.think=yakman_flinch;
else
{
if(random()<0.5)
self.think=yakman_pain_seq;
else
self.think=yakman_shakeoff;
}
thinktime self : 0;
}
void yakman_land () [++ $jump19 .. $jump24]
{
//SOUND?
// dprint("landing\n");
self.touch=SUB_Null;
if(cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
if(self.frame==$jump19)
sound(self,CHAN_BODY,"player/land.wav",1,ATTN_NORM);
}
void yakman_in_air ()
{
// dprint("in air\n");
// ai_face();
self.frame=$jump18;
if(!self.flags&FL_ONGROUND)
{
if(random()<0.1)
{
tracearea(self.origin,self.origin + '0 0 -1',self.mins,self.maxs,FALSE,self);
if(trace_fraction<1&&(trace_ent.solid==SOLID_BBOX||trace_ent.solid==SOLID_SLIDEBOX))
self.flags(+)FL_ONGROUND;
}
}
if(self.flags&FL_ONGROUND)
{
thinktime self : 0;
self.think=yakman_land;
}
else
{
if(self.velocity=='0 0 0')
self.velocity='0 0 -60';
self.think=yakman_in_air;
thinktime self : 0.05;
}
}
void yakman_jump () [++ $jump1 .. $jump17]
{//FIXME: does damage when he hits someone in mid-jump?
//SOUND?
// dprint("jumping\n");
ai_face();
self.touch=impact_touch_hurt_no_push;
if(!self.level)
{
if(self.flags&FL_ONGROUND)
{
thinktime self : 0;
self.think=yakman_land;
}
}
else if(self.frame==$jump7)
{
self.flags(-)FL_ONGROUND;
self.level=FALSE;
}
if(self.frame==$jump17)
{
thinktime self : 0.05;
self.think=yakman_in_air;
}
}
void yak_shard_think ()
{
if(self.scale>0.05)
{
self.scale-=0.05;
self.movedir=normalize(self.wallspot-self.origin);
makevectors(self.angles);
if(v_forward*self.movedir<0.75)
remove(self);
else
{
self.think=yak_shard_think;
thinktime self : 0.05;
}
}
else
remove(self);
}
float YAK_SHARD_RADIUS = 128;
float YAK_SHARD_MIN_SPEED = 30;
float YAK_SHARD_ADD_SPEED = 150;
/*
void make_yak_power (vector org)
{
entity newshard;
newshard=spawn();
newshard.solid=SOLID_NOT;
newshard.movetype=MOVETYPE_NOCLIP;
newshard.drawflags(+)MLS_POWERMODE;//|DRF_TRANSLUCENT;
newshard.scale=random()+1;
setmodel(newshard,"models/powersh.mdl");
setsize(newshard,'0 0 0','0 0 0');
setorigin(newshard,org+randomv('-1 -1 -1','1 1 1')*YAK_SHARD_RADIUS);
newshard.speed=random()*YAK_SHARD_ADD_SPEED+YAK_SHARD_MIN_SPEED;
newshard.velocity=normalize(org-newshard.origin);
newshard.velocity=newshard.velocity*newshard.speed;
newshard.angles=vectoangles(newshard.velocity);
newshard.avelocity_z=random()*600 - 300;
newshard.think=yak_shard_think;
thinktime newshard : 0.05;
}
*/
void yakman_fire_stop () [++ $shard15 .. $shard23]
{
if(cycle_wrapped)
{
if(skill>=4)
self.attack_finished=0;
else
self.attack_finished=time + 0.5;
if(self.enemy.frozen>0)
{
self.think= self.th_melee;
thinktime self : 0.05;
}
else
{
self.think=self.th_run;
thinktime self : 0.05;
}
}
}
/*
void yak_snowball_hit ()
{
if(other.takedamage&&other.health&&other!=self.owner)
T_Damage(other,self,self.owner,self.dmg);
//sound(self,CHAN_AUTO,"crusader/icewall.wav",0.1,ATTN_NORM);
//particleexplosion(self.origin,14,20,5);
self.th_die();
//remove(self);
}
*/
void sheep_hit ()
{//FIXME: Red gory explosion
if(other.takedamage&&other.health&&other!=self.owner)
{
T_Damage(other,self,self.owner,self.dmg);
self.dmg/=2;
}
T_RadiusDamage(self,self.owner,self.dmg,self.owner);
sound (self, CHAN_AUTO, "player/megagib.wav", 1, ATTN_NONE);
self.solid=SOLID_NOT;
setsize(self,'-60 -60 -60','60 60 60');
self.scale=1;
chunk_death();
}
float YAK_SNOWBALL_DMG_ADD = 10;
float YAK_SNOWBALL_DMG_MIN = 20;
void yakman_shoot_snowball (float offset)
{
entity snowball;
vector org,to_enemy;
//PARTICLE TRAIL
makevectors(self.angles);
self.effects(+)EF_MUZZLEFLASH;
snowball=spawn();
snowball.owner = self;
snowball.solid=SOLID_BBOX;
snowball.classname="snowball";
snowball.movetype = MOVETYPE_BOUNCEMISSILE;
snowball.dmg=random()*YAK_SNOWBALL_DMG_ADD+YAK_SNOWBALL_DMG_MIN;
snowball.touch = FreezeTouch;//yak_snowball_hit;
snowball.th_die=shatter;
snowball.deathtype="ice shatter";
setmodel(snowball,"models/yakball.mdl");
snowball.think=SUB_Remove;
thinktime snowball : 3;
snowball.drawflags=MLS_ABSLIGHT;
snowball.abslight=0.5;
setsize(snowball,'0 0 0','0 0 0');
org=self.origin+self.proj_ofs+v_forward*64;
snowball.speed=(random(300)+600);
to_enemy=normalize(self.enemy.origin+self.enemy.view_ofs-org);
if(fov(self.enemy,self,45))
snowball.velocity=to_enemy;
else
{
snowball.velocity=v_forward;
snowball.velocity_z=to_enemy_z;
}
snowball.velocity+=v_right*offset;
if(self.enemy.velocity_x||self.enemy.velocity_y)
snowball.velocity=snowball.velocity+v_right*(random(0.2) - 0.1);
snowball.velocity=snowball.velocity*snowball.speed;
snowball.avelocity_z=random()*600 - 300;
setorigin(snowball,org);
}
void yakman_fire () [++ $shard15 .. $shard23]
{
if(self.enemy.frozen>0)
{
self.weaponframe_cnt=self.level=0;
self.think=self.th_melee;
thinktime self : 0.05;
}
else
{
ai_face();
if(self.frame==$shard16)
yakman_shoot_snowball(-0.33);
else if(self.frame==$shard18)
yakman_shoot_snowball(0);
else if(self.frame==$shard20)
yakman_shoot_snowball(0.33);
else if(cycle_wrapped)
if(self.weaponframe_cnt<self.level&&clear_path(self.enemy,FALSE))
{
self.weaponframe_cnt+=1;
// self.angles_y+=random()*2*self.yaw_speed-self.yaw_speed;
}
else
{
self.weaponframe_cnt=self.level=0;
self.th_pain=yakman_pain;
self.think=yakman_fire_stop;
thinktime self : 0.05;
}
}
}
void yakman_ready_fire () [++ $shard1 .. $shard14]
{
//float shardcount;
//vector org;
//SOUND
//CHARGE PARTICLE EFFECT- forget it, no-one liked it! Losers.
ai_face();
if(cycle_wrapped)
{
self.level=rint(random()*4+3);
self.think=yakman_fire;
thinktime self : 0.05;
}
else if(self.frame==$shard1)
sound(self,CHAN_AUTO,"yakman/icespell.wav",1,ATTN_NORM);
}
void yakman_charge () [++ $charge1 .. $charge12]
{
// self.frame=$charge;
// self.think=yakman_charge;
// thinktime self : 0.05;
float enemy_dist;
self.weaponframe_cnt+=1;
if(self.weaponframe_cnt>48)
{
self.touch=SUB_Null;
self.weaponframe_cnt=0;
thinktime self : 0;
self.think=self.th_run;//yakman_charge_leap;
}
else if(self.weaponframe_cnt==1)
{
self.last_attack=time;
self.ltime=0;
self.touch=yakman_touch;
if(skill>=4)
self.attack_finished=0;
else
self.attack_finished=time+1.25;
}
if(random(24)<=1)
yakman_idle_sound();
enemy_dist=vlen(self.enemy.origin-self.origin);
if(enemy_dist>256&&random()<0.3 - self.skin/10)
{//Shoot
self.touch=SUB_Null;
self.weaponframe_cnt=0;
thinktime self : 0;
self.think=self.th_missile;
return;
}
else if(enemy_dist>128)
if(random()<0.1)
yakman_check_defense();
if(self.t_width<time)
{
if(self.lefty)
{
sound(self,CHAN_ITEM,"yakman/hoof.wav",1,ATTN_NORM);
self.lefty=FALSE;
}
else
{
sound(self,CHAN_WEAPON,"yakman/hoof.wav",1,ATTN_NORM);
self.lefty=TRUE;
}
self.t_width=time+0.2;
}
ai_face();
if(!walkmove(self.angles_y,15,TRUE))
{
if(trace_ent.takedamage)
yakman_slam(trace_ent);
else if(CheckJump(TRUE))
return;//??
else //if(trace_ent.solid==SOLID_BSP)
movetogoal(7);
//movestep(0,0,7,FALSE);
}
}
void yakman_throw_sheep () [-- $bwalk18 .. $bwalk7]
{
ai_face();
if(self.frame==$bwalk12)
yakman_shoot_snowball(666);
else if(cycle_wrapped)
self.think=self.th_run;
}
void yakman_melee (float ofs)
{
float zofs;
vector dir;
ai_face();
makevectors(self.angles);
dir_z=ofs - 10;
dir+=v_right*(ofs - 10)+v_forward*(100 - fabs(20 - ofs));
dir=normalize(dir);
zofs = (self.enemy.origin_z+self.enemy.view_ofs_z) - (self.origin_z+37);
if(zofs>48)
zofs=48;
else if(zofs<-48)
zofs=-48;
traceline(self.origin+'0 0 37'+'0 0 1'*zofs,self.origin+'0 0 37'+dir*100+'0 0 1'*zofs,FALSE,self);
if(trace_fraction==1)
return;
if(self.t_width<time)
{
MetalHitSound(trace_ent.thingtype);
self.t_width=time+1;
}
if(trace_ent.takedamage)
{
float inertia;
vector punchdir,throwdir;
if(trace_ent.mass<10)
inertia=1;
else
inertia=trace_ent.mass/10;
makevectors(self.angles);
punchdir=v_forward*30+'0 0 30';
throwdir=punchdir*(1/inertia);
trace_ent.velocity+=throwdir;
/*
if(trace_ent.velocity_z<throwdir_z)
trace_ent.velocity_z=throwdir_z;//so you don't throw them too high
trace_ent.velocity_x+=throwdir_x;
trace_ent.velocity_y+=throwdir_y;
*/
trace_ent.flags(-)FL_ONGROUND;
T_Damage(trace_ent,self,self,2*(self.skin+1)*(coop + 1));
}
if(trace_ent.thingtype==THINGTYPE_FLESH&&ofs==5)
{//fixme- change dir of chunks based on which dir swipe is in
MeatChunks (trace_endpos,v_right*random(-100,-300)+'0 0 200', 3,trace_ent);
sound(self,CHAN_AUTO,"weapons/slash.wav",1,ATTN_NORM);
}
SpawnPuff (trace_endpos, '0 0 0', 3,trace_ent);
}
void yakman_backhand_right () [++ $bwalk7 .. $bwalk18]
{
ai_charge(6);
self.cnt+=1;
if(self.cnt>3)
yakman_melee(self.cnt - 3);
if(self.frame==$bwalk18)
self.think=self.th_run;
}
void yakman_backhand_left () [++ $bwalk1 .. $bwalk24]
{
ai_charge(6);
self.cnt+=1;
if(self.cnt>3)
yakman_melee(self.cnt - 3);
if(self.frame==$bwalk6)
self.think=self.th_run;
}
void yakman_back_step_swipe_right () [-- $bwalk18 .. $bwalk7]
{
ai_charge(-3);
self.cnt+=1;
if(self.cnt>3)
yakman_melee(self.cnt - 3);
if(self.frame==$bwalk7)
self.think=self.th_run;
}
void yakman_back_step_swipe_left () [-- $bwalk24 .. $bwalk1]
{
ai_charge(-3);
self.cnt+=1;
if(self.cnt>3)
yakman_melee(self.cnt - 3);
if(self.frame==$bwalk19)
self.think=self.th_run;
}
void yakman_swipe_or_charge ()
{
self.cnt=0;
self.last_attack=time;
if(vlen(self.origin-self.enemy.origin)<=64)
{
sound(self,CHAN_WEAPON,"weapons/vorpswng.wav",1,ATTN_NORM);
if(random()<0.5)
sound(self,CHAN_VOICE,"yakman/grunt.wav",1,ATTN_NORM);
if((random()<0.5&&self.level!=1)||self.level==2)
{
self.level=1;
yakman_back_step_swipe_right();
}
else
{
self.level=2;
self.frame=$bwalk6;
yakman_back_step_swipe_left();
}
}
else if(vlen(self.origin-self.enemy.origin)<=128)
{
if(random()<0.2)
yakman_slam(self.enemy);
else
{
sound(self,CHAN_WEAPON,"weapons/vorpswng.wav",1,ATTN_NORM);
if(random()<0.5)
yakman_idle_sound();//sound(self,CHAN_VOICE,"ezzo/grunt.wav",1,ATTN_NORM);
if((random()<0.5&&self.level!=3)||self.level==4)
{
self.level=3;
yakman_backhand_right();
}
else
{
self.level=4;
self.frame=$bwalk19;
yakman_backhand_left();
}
}
}
else
{
self.weaponframe_cnt=0;
self.think=yakman_charge;
}
thinktime self : 0;
}
void yakman_shoot_or_charge ()
{
if((fabs(self.enemy.origin_z-self.origin_z)<48&&vlen(self.origin-self.enemy.origin)<512&&random()<0.7+self.skin/10)||self.enemy.frozen>0)
{
if(vlen(self.origin-self.enemy.origin)<100)
self.th_melee();//yakman_slam(self.enemy);
else
{
self.weaponframe_cnt=0;
self.think=yakman_charge;//If close enough and on about same level, charge
}
}
else
{
if(random()<=0.01)
self.think=yakman_throw_sheep;
else
{
self.th_pain=self.touch=SUB_Null;
self.think=yakman_ready_fire;
}
}
thinktime self : 0;
}
void yakman_howl () [++ $howl1 .. $howl36]
{
if(self.frame==$howl36)
{
self.last_attack=time+3;
thinktime self : 0;
self.think=self.oldthink;
}
else if(self.frame==$howl1)
{
self.monster_awake=TRUE;
sound(self,CHAN_VOICE,"yakman/roar.wav",1,ATTN_NORM);
}
}
void yakman_run () [++ $walk1 .. $walk24]
{
// self.frame=$walk;
// self.think=self.th_run;
// thinktime self : 0.05;
if(self.velocity!='0 0 0')
self.velocity='0 0 0';
if(random()<=0.07)
yakman_idle_sound();
yakman_check_defense();
if(!self.enemy.flags2&FL_ALIVE&&self.enemy!=world)
{
self.monster_awake=FALSE;
if(visible(self.enemy)&&infront(self.enemy))
{
self.enemy=world;
self.oldthink=self.th_run;
self.think=yakman_howl;
}
thinktime self : 0;
}
else
{
ai_face();
self.attack_state=AS_STRAIGHT;
ai_run(self.speed);
}
}
void yakman_walk () [++ $walk1 .. $walk24]
{
// self.frame=$walk;
// self.think=self.th_walk;
// thinktime self : 0.05;
if(random()<=0.04)
yakman_idle_sound();
// yakman_check_defense();
if(self.target)
ai_walk(self.speed);
}
void yakman_stand () [++ $wait1 .. $wait24]
{
// self.frame=$wait;
// self.think=self.th_stand;
// thinktime self : 0.05;
if(random()<=0.01)
yakman_idle_sound();
if(random()<0.5)
ai_stand();
}
/*QUAKED monster_yakman (1 0.3 0) (-28 -28 0) (28 28 80) AMBUSH STUCK JUMP x DORMANT
The Yakman Cometh... and the Yakman taketh away...
skin: 0 - white: more often uses ice, and less often charges
1 - brown: white even chance of charge or ice
2 - black: most health, most likely to charge.
*/
void() monster_yakman =
{
if (deathmatch)
{
remove(self);
return;
}
if(!self.th_init)
{
self.th_init=monster_yakman;
self.init_org=self.origin;
}
if (!self.flags2 & FL_SUMMONED&&!self.flags2&FL2_RESPAWN)
{
precache_model4 ("models/yakman.mdl");
precache_model4 ("models/yakball.mdl");
precache_model4 ("models/iceshot2.mdl");
precache_model4 ("models/powersh.mdl");
precache_model4 ("models/sheepmis.mdl");
precache_sound4 ("yakman/slam.wav");
precache_sound4 ("yakman/pain.wav");
precache_sound4 ("yakman/hoof.wav");
precache_sound4 ("yakman/grunt.wav");
precache_sound4 ("yakman/snort1.wav");
precache_sound4 ("yakman/snort2.wav");
precache_sound4 ("yakman/roar.wav");
precache_sound4 ("yakman/die.wav");
precache_sound3 ("crusader/icewall.wav");
precache_sound4 ("yakman/icespell.wav");
precache_sound3 ("crusader/icefire.wav");
precache_sound3 ("misc/tink.wav"); //Ice shots bounce
precache_sound3 ("mezzo/skid.wav");
/*
precache_model4 ("models/yakref.spr");
precache_model4 ("models/h_yak.mdl");
precache_sound4 ("yakman/skid.wav");
precache_sound4 ("yakman/roar.wav");
precache_sound4 ("yakman/reflect.wav");
precache_sound4 ("yakman/die.wav");
precache_sound4 ("yakman/growl.wav");
precache_sound4 ("yakman/snort.wav");
precache_sound4 ("yakman/attack.wav");
*/
}
self.solid = SOLID_SLIDEBOX;
self.takedamage=DAMAGE_YES;
self.thingtype=THINGTYPE_FLESH;
self.movetype = MOVETYPE_STEP;
self.view_ofs = '0 0 80';
self.proj_ofs = '0 0 64';
self.noise="yakman/grunt.wav";
if(!self.skin)
{
if(random()<0.50-skill/10)
self.skin=0;
else if(random()<0.9-skill/10)
self.skin=1;
else
self.skin=2;
}
else if(self.skin>2)
{
dprintf("Yak skin value is too high %s\n",self.skin);
self.skin=2;
}
if(!self.speed)
self.speed=4;
if(!self.yaw_speed)
self.yaw_speed = 10;
if(!self.health)
self.health = 250+self.skin*30;
if(!self.max_health)
self.max_health=self.health;
if(!self.experience_value)
self.experience_value = 200;
if(!self.mass)
self.mass = 30;
if(!self.mintel)
self.mintel = 15;//Animal sense of smell makes him a good tracker
self.monsterclass = CLASS_HENCHMAN;
/*
if(self.classname=="monster_yakman_lord")
{
self.monsterclass = CLASS_LEADER;
self.experience_value = 300;
self.health=400;
self.skin=1;
}
*/
self.classname="monster_yakman";
self.th_stand=yakman_stand;
self.th_walk=yakman_walk;
self.th_run=yakman_run;
self.th_pain=yakman_pain;
self.th_melee=yakman_swipe_or_charge;
self.th_missile=yakman_shoot_or_charge;
self.th_jump=yakman_jump;
self.th_die=yakman_die;
self.spawnflags (+) JUMP;
setmodel (self, "models/yakman.mdl");
// self.headmodel="models/h_yak.mdl";
// self.scale=.8;
// self.drawflags(+)SCALE_ORIGIN_BOTTOM;
setsize(self, '-16 -16 0', '16 16 80');
// setsize(self, '-28 -28 0', '28 28 80');
// self.hull=HULL_GOLEM;
// self.hull=HULL_SCORPION;
self.hull=HULL_PLAYER;// need one bigger than player, like 46 46 80
self.frame=$shard32;
self.init_exp_val = self.experience_value;
walkmonster_start();
};