1230 lines
31 KiB
C++
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();
|
|
};
|