hexen2-hw-hc/medusa.hc

952 lines
25 KiB
C++

/*
* $Header: /HexenWorld/HCode/medusa.hc 2 3/27/98 1:34p Mgummelt $
*/
/*
==============================================================================
Q:\art\models\monsters\medusa\medusa.hc
MG
==============================================================================
*/
// For building the model
$cd Q:\art\models\monsters\medusa
$origin 0 0 0
$base BASE-F skin
$skin skin
$skin SKIN2
$flags 0
//MEDUSA.MDL
//
$frame looklf1 looklf2 looklf3 looklf4 looklf5
$frame looklf6 looklf7 looklf8 looklf9 looklf10
$frame looklf11 looklf12 looklf13 looklf14 looklf15
$frame looklf16 looklf17 looklf18 looklf19 looklf20
$frame looklf21 looklf22 looklf23 looklf24 looklf25
$frame looklf26 looklf27 looklf28 looklf29
//
$frame lookrt1 lookrt2 lookrt3 lookrt4 lookrt5
$frame lookrt6 lookrt7 lookrt8 lookrt9 lookrt10
$frame lookrt11 lookrt12 lookrt13 lookrt14 lookrt15
$frame lookrt16 lookrt17 lookrt18 lookrt19 lookrt20
$frame lookrt21 lookrt22 lookrt23 lookrt24 lookrt25
$frame lookrt26 lookrt27 lookrt28 lookrt29
//
$frame medusa1 medusa2 medusa3 medusa4 medusa5
$frame medusa6 medusa7 medusa8 medusa9 medusa10
$frame medusa11 medusa12 medusa13 medusa14 medusa15
$frame medusa16 medusa17 medusa18 medusa19 medusa20
$frame medusa21 medusa22 medusa23 medusa24 medusa25
$frame medusa26 medusa27 medusa28 medusa29
//
$frame ratatt1 ratatt2 ratatt3 ratatt4 ratatt5
$frame ratatt6 ratatt7 ratatt8 ratatt9 ratatt10
$frame ratatt11 ratatt12 ratatt13 ratatt14 ratatt15
$frame ratatt16 ratatt17 ratatt18 ratatt19 ratatt20
$frame ratatt21 ratatt22 ratatt23 ratatt24 ratatt25
$frame ratatt26 ratatt27 ratatt28 ratatt29
//
$frame ratlft1 ratlft2 ratlft3 ratlft4 ratlft5
$frame ratlft6 ratlft7 ratlft8 ratlft9 ratlft10
$frame ratlft11 ratlft12 ratlft13 ratlft14 ratlft15
$frame ratlft16 ratlft17 ratlft18 ratlft19 ratlft20
$frame ratlft21 ratlft22 ratlft23 ratlft24 ratlft25
$frame ratlft26 ratlft27 ratlft28 ratlft29
//
$frame ratrit1 ratrit2 ratrit3 ratrit4 ratrit5
$frame ratrit6 ratrit7 ratrit8 ratrit9 ratrit10
$frame ratrit11 ratrit12 ratrit13 ratrit14 ratrit15
$frame ratrit16 ratrit17 ratrit18 ratrit19 ratrit20
$frame ratrit21 ratrit22 ratrit23 ratrit24 ratrit25
$frame ratrit26 ratrit27 ratrit28 ratrit29
//
$frame stand1 stand2 stand3 stand4 stand5
$frame stand6 stand7 stand8 stand9 stand10
$frame stand11 stand12 stand13 stand14 stand15
$frame stand16 stand17 stand18 stand19 stand20
$frame stand21 stand22 stand23 stand24 stand25
$frame stand26 stand27 stand28 stand29
//
$frame swipe1 swipe2 swipe3 swipe4 swipe5
$frame swipe6 swipe7 swipe8 swipe9 swipe10
$frame swipe11 swipe12 swipe13 swipe14 swipe15
$frame swipe16 swipe17 swipe18 swipe19 swipe20
$frame swipe21 swipe22 swipe23 swipe24 swipe25
$frame swipe26 swipe27 swipe28 swipe29
//MEDUSA2.MDL
$framevalue 0
//
$frame adecap1 adecap2 adecap3 adecap4 adecap5
$frame adecap6 adecap7 adecap8 adecap9 adecap10
$frame adecap11 adecap12 adecap13 adecap14 adecap15
$frame adecap16 adecap17 adecap18 adecap19 adecap20
$frame adecap21 adecap22 adecap23 adecap24 adecap25
$frame adecap26 adecap27 adecap28 adecap29 adecap30
$frame adecap31 adecap32 adecap33 adecap34 adecap35
$frame adecap36 adecap37 adecap38 adecap39 adecap40
$frame adecap41 adecap42 adecap43 adecap44 adecap45
$frame adecap46 adecap47 adecap48 adecap49 adecap50
$frame adecap51 adecap52 adecap53 adecap54 adecap55
$frame adecap56 adecap57 adecap58 adecap59 adecap60
$frame adecap61 adecap62 adecap63 adecap64 adecap65
$frame adecap66 adecap67 adecap68 adecap69 adecap70
$frame adecap71 adecap72 adecap73 adecap74 adecap75
$frame adecap76 adecap77 adecap78 adecap79 adecap80
$frame adecap81 adecap82 adecap83 adecap84 adecap85
$frame adecap86 adecap87 adecap88
//
$frame bdecap1 bdecap2 bdecap3 bdecap4 bdecap5
$frame bdecap6 bdecap7 bdecap8 bdecap9 bdecap10
$frame bdecap11 bdecap12 bdecap13 bdecap14 bdecap15
$frame bdecap16 bdecap17 bdecap18 bdecap19 bdecap20
$frame bdecap21 bdecap22 bdecap23 bdecap24 bdecap25
//
$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 pain1 pain2 pain3 pain4 pain5
$frame pain6 pain7 pain8 pain9 pain10
$frame pain11
//
$frame rnatlf1 rnatlf2 rnatlf3 rnatlf4 rnatlf5
$frame rnatlf6 rnatlf7 rnatlf8 rnatlf9 rnatlf10
$frame rnatlf11 rnatlf12 rnatlf13 rnatlf14 rnatlf15
$frame rnatlf16 rnatlf17 rnatlf18 rnatlf19 rnatlf20
$frame rnatlf21
//
$frame rnatrt1 rnatrt2 rnatrt3 rnatrt4 rnatrt5
$frame rnatrt6 rnatrt7 rnatrt8 rnatrt9 rnatrt10
$frame rnatrt11 rnatrt12 rnatrt13 rnatrt14 rnatrt15
$frame rnatrt16 rnatrt17 rnatrt18 rnatrt19 rnatrt20
$frame rnatrt21
//
$frame runatt1 runatt2 runatt3 runatt4 runatt5
$frame runatt6 runatt7 runatt8 runatt9 runatt10
$frame runatt11 runatt12 runatt13 runatt14 runatt15
$frame runatt16 runatt17 runatt18 runatt19 runatt20
$frame runatt21 runatt22 runatt23 runatt24 runatt25
$frame runatt26 runatt27 runatt28 runatt29
//====================================================================
float MEDUSA_LOOK = 0;
float MEDUSA_RATTLE = 1;
float MEDUSA_HEADBUTT = 2;
float MEDUSA_SNAKES = 3;
void(entity attacker,float total_damage)medusa_pain;
void()medusa_attack_right;
void()medusa_attack_left;
void()medusa_attack;
void(float action)MedusaSelectDir;
void medusa_check_use_model (string modelstring)
{
if(self.model!=modelstring)
{
setmodel(self,modelstring);
setsize(self,'-16 -16 0','16 16 56');
}
}
void snake_remove ()
{
particleexplosion(self.origin,random(176,192),30,20);
remove(self);
}
void() SnakeHit =
{
if(other==self.owner||(other.owner==self.owner&&other.classname=="snakearrow"))
return;
starteffect(CE_MEDUSA_HIT,self.origin);
sound(other,CHAN_AUTO,"medusa/hitplayr.wav",1,ATTN_NORM);
if(other.takedamage)
{
other.bloodloss=other.bloodloss+1;
SpawnPuff(other.origin,'0 0 0',self.dmg,other);
//Snakehit sprite
T_Damage(other,self,self.owner,self.dmg);
}
snake_remove();
};
void snake_fly ()
{
particle4(self.origin,10,256+random(176,192),PARTICLETYPE_GRAV,3);
if(random()<0.1)
CreateGreenSmoke(self.origin,'0 0 0',HX_FRAME_TIME);
HomeThink();
self.think=snake_fly;
thinktime self : 0.05;
}
void FireSnakeArrow (vector offset)
{
//FIXME: add a greenish particle trail?
self.last_attack=time;
makevectors(self.angles);
//identity
newmis=spawn();
newmis.owner=self;
newmis.classname="snakearrow";
//Movement and solidity
newmis.movetype=MOVETYPE_FLYMISSILE;
newmis.solid=SOLID_BBOX;
//rendering
newmis.abslight=0.3;
newmis.drawflags(+)MLS_ABSLIGHT;
//velocity
newmis.speed=500;
newmis.o_angle=normalize((self.goalentity.origin+self.goalentity.view_ofs) - (self.origin+self.view_ofs+offset));
newmis.velocity=newmis.o_angle*newmis.speed;
newmis.angles=vectoangles(newmis.velocity);
//impact
newmis.touch=SnakeHit;
newmis.dmg=3;
//behaviour
newmis.lockentity=newmis.enemy=self.enemy;//lockentity means it will never track any other ent
newmis.veer=50; //slight veering, random course modifications
newmis.th_die=snake_remove;
newmis.think=snake_fly;
newmis.hoverz=TRUE; //slow down on turns
thinktime newmis : 0;
//appearance,size, and position, always in this order!!!
setmodel(newmis,"models/snakearr.mdl");
setsize(newmis,'0 0 0','0 0 0');
setorigin(newmis,self.origin+self.view_ofs+v_forward*8+offset);
}
void MedusaAttacks (void)
{
vector source, org;
float damg;
if(self.monster_stage==MEDUSA_SNAKES)
{
self.attack_finished=time+2;
sound (self,CHAN_WEAPON,"medusa/attack2.wav",1,ATTN_NORM);
FireSnakeArrow(v_up*12);
FireSnakeArrow(v_right*12);
FireSnakeArrow(v_right*-12);
}
else
{
self.attack_finished=time+1;
makevectors (self.angles+self.angle_ofs);
source = self.origin+self.view_ofs;
traceline (source, source + v_forward*48, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos + (v_forward * 4);
sound (self, CHAN_WEAPON, "weapons/gauntht1.wav", 1, ATTN_NORM);
if (trace_ent.takedamage)
{
damg = random(10,18);
SpawnPuff (org, '0 0 0', 20,trace_ent);
T_Damage (trace_ent, self, self, damg);
//punchangle
// if(other.classname=="player")
// other.punchangle=???
}
else
{ // hit wall
SpawnPuff (trace_endpos, '0 0 0', 20,self);
medusa_pain(self,0);
}
}
}
void()medusa_attack_left = [++ $rnatlf1 .. $rnatlf21]
{
medusa_check_use_model("models/medusa2.mdl");
if(self.frame==$rnatlf21)
self.think=self.th_run;
else if(self.frame==$rnatlf4)
MedusaAttacks();
};
void()medusa_attack_right = [++ $rnatrt1 .. $rnatrt21]
{
medusa_check_use_model("models/medusa2.mdl");
if(self.frame==$rnatrt21)
self.think=self.th_run;
else if(self.frame==$rnatrt4)
MedusaAttacks();
};
void()medusa_attack = [++ $runatt1 .. $runatt29]
{
medusa_check_use_model("models/medusa2.mdl");
if(self.frame==$runatt29)
self.think= self.th_run;
else if(self.frame==$runatt12)
MedusaAttacks();
};
void()MedusaGazeLoop;
void MedusaGaze (vector org, vector destiny, entity loser) [++ $medusa1 .. $medusa29]
{
//Anim?
//sound, temp ent
self.last_attack=time;
if(!self.aflag)
{
sound (self,CHAN_WEAPON,"medusa/attack1.wav",1,ATTN_NORM);
self.aflag=TRUE;
}
medusa_check_use_model("models/medusa.mdl");
ai_face();
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_STREAM_GAZE);
WriteByte (MSG_BROADCAST, 1+STREAM_ATTACHED);
WriteByte (MSG_BROADCAST, 4);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
WriteCoord (MSG_BROADCAST, destiny_x);
WriteCoord (MSG_BROADCAST, destiny_y);
WriteCoord (MSG_BROADCAST, destiny_z);
if(loser.health<=10&&!loser.artifact_active&ART_INVINCIBILITY)
{
sound(loser,CHAN_BODY,"medusa/stoned.wav",1,ATTN_NORM);
self.attack_finished=time+7;
loser.skin = GLOBAL_SKIN_STONE;
loser.think=loser.th_pain=loser.th_run=SUB_Null;
loser.attack_finished=loser.teleport_time=loser.pausetime = time+10000000000;
loser.nextthink=-1;
loser.th_die = chunk_death;
loser.thingtype = THINGTYPE_GREYSTONE;
loser.health = 10;
loser.touch = obj_push;
loser.flags(-)FL_FLY;
loser.flags(-)FL_SWIM;
if(loser.classname!="player")
loser.movetype = MOVETYPE_STEP;//step?
else
loser.o_angle=loser.v_angle;
loser.solid = SOLID_BBOX;
loser.artifact_active(+)ARTFLAG_STONED;
//Greying palette effect
}
else
{
T_Damage(loser,self,self,3);
if(loser.classname=="player"&&random()<0.2+skill/10+self.skin/5)
{
loser.o_angle=loser.v_angle;
loser.pausetime=time+random(0.05,0.3);
if(random()<0.5)
{
loser.attack_finished=time+random(0.05,0.3);
if(random()<0.5)
thinktime loser : 0.2;
}
}
}
if(lineofsight(self,loser)&&!loser.artifact_active&ARTFLAG_STONED)
{
self.goalentity=loser;
self.think=MedusaGazeLoop;
thinktime self : 0.1;
}
else
{
self.aflag=FALSE;
stopSound(self,CHAN_WEAPON);
//sound (self,CHAN_WEAPON,"misc/null.wav",1,ATTN_NORM);
self.attack_finished=time+2;
self.think=self.th_run;
thinktime self : 0;
}
}
void MedusaGazeLoop()
{
MedusaGaze(self.origin+self.view_ofs,self.goalentity.origin+self.goalentity.view_ofs,self.goalentity);
}
void MedusaSwipe () [++ $swipe1 .. $swipe29]
{
self.last_attack=time;
if(cycle_wrapped)
{
self.attack_finished=time+1;
self.think=self.th_run;
thinktime self : 0;
}
else if(self.frame==$swipe1)
{
sound(self,CHAN_VOICE,"medusa/sight.wav",1,ATTN_NORM);
sound(self,CHAN_BODY,"weapons/vorpswng.wav",1,ATTN_NORM);
}
else if(self.frame>=$swipe6 &&self.frame<=$swipe10)
{
makevectors(self.angles);
traceline(self.origin+'0 0 23',self.origin+'0 0 23'-v_forward*72+v_right*($swipe7 - self.frame)*10,FALSE,self);
if(trace_ent.takedamage)
{
T_Damage(trace_ent,self,self,7);
sound(trace_ent,CHAN_BODY,"weapons/met2flsh.wav",1,ATTN_NORM);
SpawnPuff(trace_endpos,'0 0 0',7,trace_ent);
trace_ent.velocity+=v_right*-200;
trace_ent.velocity_z+=100;
trace_ent.flags(-)FL_ONGROUND;
}
}
else if(self.frame>$swipe10)
ai_face();
}
float MedusaCheckAttack (void)
{
vector org,dir,destiny;
float r, loscheck1,loscheck2;
if(random()<0.5 - skill/10 - self.skin/5||self.enemy==world)
return FALSE;
org=self.origin+self.view_ofs;
if (time < self.attack_finished)
return FALSE;
if (!enemy_vis)
{
if(self.goalentity.classname=="waypoint")
{
if(visible2ent(self.enemy,self.goalentity))
{
MedusaSelectDir(MEDUSA_SNAKES);
return TRUE;
}
}
return FALSE;
}
if(!enemy_infront)
{
if(enemy_range==RANGE_MELEE)
{
MedusaSwipe();
return TRUE;
}
}
if (enemy_range == RANGE_FAR)
{
if (self.attack_state != AS_STRAIGHT)
self.attack_state = AS_STRAIGHT;
return FALSE;
}
// see if any entities are in the way of the shot
dir = self.enemy.origin + self.enemy.view_ofs;
traceline (org, dir, FALSE, self);
if (trace_ent != self.enemy)
{ // don't have a clear shot, so move to a side
if (self.attack_state != AS_SLIDING)
self.attack_state == AS_SLIDING;
return FALSE;
}
else
self.attack_state == AS_STRAIGHT;
destiny = self.enemy.origin+self.enemy.view_ofs;
//FIXME: account for z difference
loscheck1=lineofsight(self.enemy,self);
loscheck2=lineofsight(self,self.enemy);
r=random();
if(!self.enemy.artifact_active&ARTFLAG_STONED&&loscheck1&& (loscheck2|| (r<0.1&&infront_of_ent(self,self.enemy)) ) )
{
MedusaGaze(org,destiny,self.enemy);
return TRUE;
}
if (enemy_range == RANGE_MELEE)
{
MedusaSelectDir(MEDUSA_HEADBUTT);
return TRUE;
}
else if (enemy_range == RANGE_NEAR)
r = 0.2;
else if (enemy_range == RANGE_MID)
r = 0.3;
if (random () < r)
{
MedusaSelectDir(MEDUSA_SNAKES);
return TRUE;
}
return FALSE;
}
//====================================================================
void()medusa_look_right;
void MedusaHeadTouch ()
{
if(self.velocity!='0 0 0'&&!other.flags2&FL_ALIVE)
sound(self,CHAN_AUTO,"weapons/hithurt2.wav",1,ATTN_NORM);
}
void()MedusaHeadDying;
void MedusaHeadDead () [++ 0 .. 45]
{
thinktime self : 0.1;
ai_face();
if(self.frame==20)
sound(self,CHAN_VOICE,"medusa/sight.wav",0.5,ATTN_NORM);
else if(self.frame==45)
{
self.aflag=TRUE;
self.think=MedusaHeadDying;
}
}
void MedusaHeadDying () [++ 46 .. 105]
{
if(pointcontents(self.origin)==CONTENT_SOLID)
{
chunk_death();
return;
}
if(self.velocity=='0 0 0')
if(!self.aflag)
{
if(self.angles_x<-10||self.angles_x>10)
self.angles_x=0;
if(self.angles_z<-10||self.angles_z>10)
self.angles_z=0;
self.solid = SOLID_BBOX;
self.think=MedusaHeadDead;
thinktime self : 0;
}
else if(self.frame==105)
{
self.skin=1;
self.think=init_corpseblink;
thinktime self : 5;
}
}
void MedusaThrowHead ()
{
newmis = spawn();
newmis.owner=self;
newmis.enemy=newmis.goalentity=self.enemy;
newmis.yaw_speed=3;
setmodel (newmis, self.headmodel);
self.headmodel="";
setsize (newmis, '-3 -3 -3', '3 3 3');
setorigin(newmis,self.absmax - '0 0 15');
newmis.velocity = randomv('-200 -200 200','200 200 600');
newmis.movetype = MOVETYPE_BOUNCE;
if(pointcontents(newmis.origin)==CONTENT_SOLID)
newmis.solid = SOLID_NOT;
else
newmis.solid = SOLID_BBOX;
newmis.takedamage=DAMAGE_YES;
newmis.thingtype=self.thingtype;
newmis.th_die=chunk_death;
newmis.touch=MedusaHeadTouch;
newmis.health=25;
newmis.scale=2;
newmis.avelocity_x = random(600);
newmis.avelocity_y = random(600);
newmis.avelocity_z = random(600);
newmis.think=MedusaHeadDying;
thinktime newmis : 0;
}
void medusa_decap_drop ()[++ $bdecap1 .. $bdecap25]
{
if(self.frame==$bdecap9)
sound(self,CHAN_BODY,"player/land.wav",1,ATTN_NORM);
else if(self.frame==$bdecap25)
MakeSolidCorpse();
}
void medusa_decap_loop ()[++ $adecap1..$adecap88]
{
if(random()<0.5)
self.angles_y+=random(-3,3);
walkmove(self.angles_y,self.speed*random(),FALSE);
if(random()<0.2)
{
sound (self, CHAN_VOICE, "misc/decomp.wav", 0.3, ATTN_NORM);
SpawnPuff (self.origin+'0 0 56', '0 0 35',5,self);
}
if(self.frame==$adecap48)
sound(self,CHAN_BODY,"medusa/rattle.wav",1,ATTN_NORM);
if(cycle_wrapped)
{
self.think=medusa_decap_drop;
thinktime self : 0;
}
}
void medusa_decap_init ()
{
float throwdist;
throwdist=self.health;
ThrowGib("models/medsnake.mdl",throwdist);
ThrowGib("models/medsnake.mdl",throwdist);
ThrowGib("models/medsnake.mdl",throwdist);
sound(self,CHAN_VOICE,"player/gib2.wav",1,ATTN_NORM);
MedusaThrowHead();
SpawnPuff (self.origin+'0 0 56', '0 0 35',5,self);
medusa_decap_loop();
}
void medusa_die (void) [++ $death01..$death20]
{
medusa_check_use_model("models/medusa2.mdl");
if(self.decap)
medusa_decap_init();
else if(self.health<=-80)
{
MedusaThrowHead();
chunk_death();
}
else
{
if(self.frame==$death20)
MakeSolidCorpse();
else if(self.frame==$death01)
sound(self,CHAN_VOICE,"medusa/death.wav",1,ATTN_NORM);
}
}
void medusa_pain_anim () [++ $pain1 .. $pain11]
{
//sound
medusa_check_use_model("models/medusa2.mdl");
if (cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
else if(self.frame==$pain1)
sound(self,CHAN_VOICE,"medusa/pain.wav",1,ATTN_NORM);
}
void medusa_pain (entity attacker,float total_damage)
{
if(random()<0.6&&total_damage<50&&attacker!=self)
return;
medusa_pain_anim();
}
void()medusa_look_left = [++ $looklf1 .. $looklf29]
{
medusa_check_use_model("models/medusa.mdl");
if(self.oldthink==self.th_run)
ai_run(self.speed);
else
{
if(self.oldthink==self.th_stand)
ai_stand();
else if(self.oldthink==self.th_walk)
ai_walk(5);
}
if(cycle_wrapped)
{
self.think=self.oldthink;
if(self.think!=self.th_run)
if(random()<0.2)
self.think=medusa_look_right;
thinktime self : 0;
}
};
void()medusa_look_right = [++ $lookrt1 .. $lookrt29]
{
medusa_check_use_model("models/medusa.mdl");
if(self.oldthink==self.th_run)
ai_run(self.speed);
else
{
if(self.oldthink==self.th_stand)
ai_stand();
else if(self.oldthink==self.th_walk)
ai_walk(5);
}
if(cycle_wrapped)
{
self.think=self.oldthink;
if(self.think!=self.th_run)
if(random()<0.2)
self.think=medusa_look_left;
thinktime self : 0;
}
};
void()medusa_rattle_left = [++ $ratlft1 .. $ratlft29]
{
//sound
medusa_check_use_model("models/medusa.mdl");
if(cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
};
void()medusa_rattle_right = [++ $ratrit1 .. $ratrit29]
{
//sound
medusa_check_use_model("models/medusa.mdl");
if(cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
};
void()medusa_rattle = [++ $ratatt1 .. $ratatt29]
{
//sound
medusa_check_use_model("models/medusa.mdl");
if(cycle_wrapped)
{
thinktime self : 0;
self.think=self.th_run;
}
};
void MedusaSelectDir (float action)
{
vector enemy_dir;
float dot;
medusa_check_use_model("models/medusa.mdl");
self.monster_stage=action;
if(action>=MEDUSA_HEADBUTT)
{
self.last_attack=time;
sound (self,CHAN_VOICE,"medusa/hiss.wav",1,ATTN_NORM);
medusa_check_use_model("models/medusa2.mdl");
}
else if(action==MEDUSA_RATTLE)
sound(self,CHAN_BODY,"medusa/rattle.wav",1,ATTN_NORM);
makevectors(self.angles);
enemy_dir=normalize(self.enemy.origin-self.origin);
dot=v_right*enemy_dir;
if(dot>0.3)
{
self.angle_ofs_y=-90;
if(action>=MEDUSA_HEADBUTT)
self.think=medusa_attack_right;
else if(action==MEDUSA_RATTLE)
self.think=medusa_rattle_right;
else
self.think=medusa_look_right;
}
else if(dot<-0.3)
{
self.angle_ofs_y=-90;
if(action>=MEDUSA_HEADBUTT)
self.think=medusa_attack_left;
else if(action==MEDUSA_RATTLE)
self.think=medusa_rattle_left;
else
self.think=medusa_look_left;
}
else
{
self.angle_ofs_y=0;
if(action>=MEDUSA_HEADBUTT)
self.think=medusa_attack;
else if(action==MEDUSA_RATTLE)
self.think=medusa_rattle;
else
return;
}
thinktime self : 0;
}
void medusa_hunt () [++ $medusa1 .. $medusa29]
{
medusa_check_use_model("models/medusa.mdl");
if(random()<0.1)
ai_run(0);
else
ai_run(self.speed);
if(!enemy_vis)
if(random()<0.1&&random()<0.5)
if(random()<0.5)
MedusaSelectDir(MEDUSA_RATTLE);
else
{
self.oldthink=self.th_run;
MedusaSelectDir(MEDUSA_LOOK);
}
}
void medusa_walk () [++ $medusa1 .. $medusa29]
{
medusa_check_use_model("models/medusa.mdl");
self.monster_awake=FALSE;
if(random()<0.1)
ai_walk(0);
else
ai_walk(5);
if(cycle_wrapped)
{
if(random()<0.3)
{
self.oldthink=self.th_walk;
if(random()<0.5)
{
thinktime self : 0;
self.think=medusa_look_left;
}
else
{
thinktime self : 0;
self.think=medusa_look_right;
}
}
}
// MedusaCheckAttack();
if(random()<0.1&&random()<0.5)
sound(self,CHAN_VOICE,"medusa/hiss.wav",1,ATTN_NORM);
}
void medusa_stand () [++$stand1..$stand29]
{
medusa_check_use_model("models/medusa.mdl");
self.monster_awake=FALSE;
ai_stand();
if(random()<0.1)
{
self.oldthink=self.th_stand;
if(random()<0.5)
{
thinktime self : 0;
self.think=medusa_look_left;
}
else
{
thinktime self : 0;
self.think=medusa_look_right;
}
}
if(random()<0.1&&random()<0.3)
sound(self,CHAN_VOICE,"medusa/hiss.wav",1,ATTN_NORM);
}
/*QUAKED monster_medusa_green (1 0.3 0) (-16 -16 0) (16 16 56) AMBUSH STUCK JUMP PLAY_DEAD DORMANT
The medusa monster with its nasty sharp pointy teeth
-------------------------FIELDS-------------------------
--------------------------------------------------------
*/
void monster_medusa_green (void)
{
if (deathmatch)
{
remove(self);
return;
}
precache_model2("models/medusa.mdl");
precache_model2("models/medusa2.mdl");
precache_model2("models/snakearr.mdl");
precache_model2("models/medhit.spr");
precache_model2("models/medhead.mdl");
precache_model2("models/medsnake.mdl");
precache_sound2("medusa/rattle.wav");
precache_sound2("medusa/hiss.wav");
precache_sound2("medusa/sight.wav");
precache_sound2("medusa/attack1.wav");
precache_sound2("medusa/attack2.wav");
precache_sound2("medusa/pain.wav");
precache_sound2("medusa/death.wav");
precache_sound2("medusa/stoned.wav");
precache_sound2("medusa/hitplayr.wav");
// if(random()<0.5)
// self.skin=1;
self.headmodel="models/medhead.mdl";
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_STEP;
self.takedamage=DAMAGE_YES;
self.thingtype=THINGTYPE_FLESH;
self.monsterclass=CLASS_LEADER;
self.mintel = 20;//Very smart- excellent tracker
self.mass = 15;
self.view_ofs = '0 0 53';
self.speed=5;
self.yaw_speed = 5;
self.classname="monster_medusa";
self.health = 700;
self.experience_value = 500;
self.th_stand=medusa_stand;
self.th_run=medusa_hunt;
self.th_walk=medusa_walk;
self.th_die=medusa_die;
self.th_pain=medusa_pain;
self.th_missile=medusa_rattle;
self.th_melee=medusa_attack;
setmodel (self, "models/medusa.mdl");
setsize(self, '-28 -28 0', '28 28 56');
self.hull=HULL_PLAYER;
walkmonster_start();
}
void monster_medusa (void)
{
monster_medusa_green();
}
/*QUAKED monster_medusa_red (1 0.3 0) (-16 -16 0) (16 16 56) AMBUSH STUCK JUMP PLAY_DEAD DORMANT
The medusa monster with its nasty sharp pointy teeth
-------------------------FIELDS-------------------------
--------------------------------------------------------
*/
void monster_medusa_red (void)
{
// self.skin=1;
monster_medusa_green();
self.health = 250;
self.experience_value = 125;
}