hexen2-siege-hc/cat2.hc

412 lines
10 KiB
C++

/*QUAKED obj_catapult2 (0 .5 .8) (-150 -150 0) (150 150 28) ?
"speed" Throw speed (300 default)
"wait" wait before resetting (3 default)
"health" Just how tough is it (defaults to 1000)
"mass" How hard is it to push (defaults to 1000)
"thingtype" Defaults to THINGTYPE_WOOD
"aflag" - Max distance it can be pushed from start pos (default 256)
"-1" disables this
"sounds"
0) no sound
1) stone
2) base
3) stone chain
4) screechy metal
*/
void catapult_ready (void)
{
//FIXME: No linking in touch, do it all in here with a tracearea (is that working?) and findradius
// if(self.flags&FL_ONGROUND&&world.model!="maps/siege3.bsp")
// self.movetype = MOVETYPE_NONE;
if(self.origin!=self.oldorigin||self.angles!=self.o_angle)
{
entity found;
vector dir,org,fmins,fmaxs;
// dprint("updating dependancies\n");
makevectors(self.angles);
dir=normalize(v_forward);
org=self.origin+dir*-4*self.level;
org_z=self.absmax_z;
found=nextent(world);
while(found)
{
//Find ground entity
fmins=found.mins;
fmaxs=found.maxs;
fmins_z=0;
fmaxs_z=8;
tracearea(found.origin+'0 0 1',found.origin-'0 0 8',fmins,fmaxs,FALSE,found);
if(trace_ent!=self)
found.catapulter=world;
if(vhlen(found.origin-org)<2*self.level&&found.catapulter==self)
{
float repos_dist,repos_dist_cnt,repos_dir_angle;
vector repos_dir;
entity save_ent;
// dprint(found.classname);
// dprint(" updated\n");
repos_dir=org+found.pos_ofs - found.origin;
repos_dist=vlen(repos_dir);
repos_dir=normalize(repos_dir);
repos_dir_angle=vectoyaw(repos_dir);
save_ent=self;
self=found;
while(repos_dist_cnt<repos_dist)
{
repos_dist_cnt+=1;
if(!walkmove(repos_dir_angle,1,FALSE))
repos_dist_cnt=repos_dist;
}
self=save_ent;
// setorigin(found,org+found.pos_ofs);
found.angles=self.angles+found.angle_ofs;
found.velocity='0 0 0';
found.flags(+)FL_ONGROUND;
}
found=nextent(found);
}
}
if(self.angles_y>self.o_angle_y)
AdvanceFrame(33,42);
else if(self.angles_y<self.o_angle_y)
AdvanceFrame(42,33);
self.o_angle=self.angles;
self.oldorigin=self.origin;
self.think=catapult_ready;
thinktime self : 0;
}
void() catapult_reset =
{
if(self.frame==22)
{
sound(self,CHAN_VOICE,"misc/catdrop.wav",1,ATTN_NORM);
self.frame=0;
}
if(self.frame>=20)
{
sound(self,CHAN_VOICE,"misc/catreset.wav",1,ATTN_NORM);
self.frame=20;
self.think=catapult_ready;
thinktime self : 0;
}
else
{
self.frame+=1;
self.think=catapult_reset;
thinktime self : 0.05;
}
};
void catapult_wait (void)
{
entity firstcat, catdude;
firstcat=catdude=find(world,classname,other.catapulter.classname);
while(catdude)
{
if(other.catapulter==self)
other.catapulter=world;
catdude=find(catdude,classname,other.catapulter.classname);
if(catdude==firstcat)
catdude=world;
}
self.think=catapult_reset;
thinktime self : self.wait;
}
void catapult_fire (void)
{
if(self.frame==20||self.frame>22)
{
sound(self,CHAN_VOICE,"misc/catlnch.wav",1,ATTN_NORM);
entity found;
vector dir,org,addvel;
float distance, force,centrifugal,throwback;
found=nextent(world);
makevectors(self.angles);
dir=normalize(v_forward);
org=self.origin+dir*-4*self.level;
org_z=self.absmax_z;
while(found)
{
distance=vhlen(found.origin-org);
// if(found.catapulter==self)
if(distance<2*self.level&&found.origin_z>self.origin_z+self.maxs_z*0.75)//&&found.catapulter==self)
{
// inertia?
found.catapult_time=time+3;
found.catapulter=world;
traceline(found.origin,found.origin-'0 0 33',FALSE,found);
if(trace_ent!=self)
{//off back edge, throw backwards
throwback=TRUE;
centrifugal=vhlen(found.origin-org);
force=self.speed + random(-100,100) + centrifugal*4;//Ignore mass, Not exact physics, but feels better
addvel=dir*-1*force+v_right*random(-50,50);//Give some left-right innacuracy to it
force=self.speed + random(-100,100)+ centrifugal*4;
addvel_z=force;
}
else
{
throwback=FALSE;
centrifugal=vhlen(found.origin-self.origin);
force=self.speed + random(-100,100) + centrifugal*4;//4 Ignore mass, Not exact physics, but feels better
addvel=dir*force+v_right*random(-50,50);//Give some left-right innacuracy to it
force=self.speed + random(-100,100)+ centrifugal*4;
addvel_z=force;//FIXME: CAP at ???
}
// if(found.playerclass==CLASS_DWARF)
// addvel*=1.05;
found.velocity+=addvel;
if(!found.touch)
found.touch=obj_push;
found.flags(-)FL_ONGROUND;
if(found.classname=="player"&&found.playerclass!=CLASS_SUCCUBUS)
{
found.teleport_time=time+1.7;//No mario
}
if(!found.flags2&FL_ALIVE)
{
found.velocity=found.velocity*1.3;
if(throwback)
found.avelocity=found.velocity*(48-centrifugal)*random(-1,1);
else
found.avelocity=found.velocity*random(-1,1);
found.movetype=MOVETYPE_BOUNCE;
}
if(found.model=="models/sheep.mdl")
{
if(found.classname!="player")
{
found.velocity=found.velocity*1.3;
found.teleport_time+=666;//impact damage forever
found.touch=found.th_die;
found.enemy = self.enemy;
if(found.trigger_field)
remove(found.trigger_field);
}
found.avelocity=found.velocity*random(-1,1);
found.movetype=MOVETYPE_BOUNCE;
sound(found,CHAN_VOICE,"misc/sheepfly.wav",1,ATTN_NORM);
found.pain_finished=time+1;
}
if(found.model=="models/barrel.mdl")
{
found.touch = found.th_die;//Maybe make them always explode on touch
if(found.netname=="obj_barrel_gfire")
sound(self,CHAN_BODY,"misc/gflaunch.wav",1,ATTN_NORM);
if(found.trigger_field)
remove(found.trigger_field);
found.enemy = self.enemy;
found.think = found.th_die;
thinktime found : 5;
}
}
found=nextent(found);
}
}
if(self.frame>=22)
{
self.frame=22;
self.think=catapult_wait;
thinktime self : 0;
}
else
{
self.frame+=1;
self.think=catapult_fire;
thinktime self : 0.05;
}
}
void catapult_pain (void)
{
if(!self.enemy.flags2&FL_ALIVE&&self.enemy.classname!="blood missile")
return;
if(self.frame==20||self.frame>22)
catapult_fire();
}
void catapult2_touch(void)
{
if(other.solid==SOLID_BSP||other==self.movechain||other==world)
return;
/* dprint(other.classname);
dprint("\n");
dprint(ftos(other.absmin_z));
dprint(" > ");
dprint(ftos(self.absmax_z));
dprint("?\n");*/
if(other.origin_z-(other.mins_z*0.75)>=self.origin_z+(self.maxs_z*0.75))
{
if(other.solid!=SOLID_TRIGGER&&other.movetype&&other.catapulter!=self&&other.catapult_time<time+0.1)
{
vector dir,org;
float distance;
makevectors(self.angles);
dir=normalize(v_forward);
org=self.origin+dir*-4*self.level;
org_z=self.absmax_z;
distance=vhlen(other.origin-org);
if(distance<=2*self.level)
{
// dprint(other.classname);
// dprint(" locked and loaded!\n");
other.catapult_time=time+0.1;
other.catapulter=self;
other.velocity=self.velocity;
other.pos_ofs=other.origin-org;
other.angle_ofs=self.angles-other.angles;
}
other.flags(+)FL_ONGROUND;
}
}
//WAS pushable...
else if(other.classname=="player"&&(vlen(other.velocity)>100||coop||deathmatch)&&other.flags&FL_ONGROUND&&(other.impulse==13||self.last_use_time + 2>time))
{//only players can directly push it
// Push or spin
vector dir1, dir2,move_vel,dest_spot;
float magnitude,dot_forward,inertia;//,dot_right;
if(other.impulse == 13)
self.last_use_time = time;
self.angles_x=self.angles_z=0;
makevectors(self.angles);
magnitude=400;//vlen(other.velocity);
inertia=1/(self.mass/10);
dir1=normalize(self.origin-other.origin);
dir2=normalize(v_forward);
dir1_z=dir2_z=0;
dot_forward= dir1*dir2;
if(dot_forward >0.8)
{
move_vel=dir2*magnitude*inertia*5;
dest_spot=self.origin+(move_vel*0.01);
if(self.aflag!=-1)
if(vhlen(dest_spot-self.wallspot)>=self.aflag)
return;
// walkmove(self.angles_y,1,FALSE);
// dprint("Move forward\n");
self.velocity=move_vel;//FIXME: adds up if do += (for multiple pushers)
// dprint(vtos(self.velocity));
self.flags(-)FL_ONGROUND;
AdvanceFrame(23,32);
}
else if(dot_forward<-0.8)
{
move_vel=dir2*-1*magnitude*inertia*5;
dest_spot=self.origin+(move_vel*0.01);
if(self.aflag!=-1)
if(vhlen(dest_spot-self.wallspot)>=self.aflag)
return;
// dprint("Move backwards\n");
// walkmove(self.angles_y,-1,FALSE);
self.velocity=move_vel;//FIXME: adds up if do += (for multiple pushers)
self.flags(-)FL_ONGROUND;
AdvanceFrame(32,23);
}
// if(self.movechain)
// setorigin(self.movechain,self.origin+'0 0 26');
/* else
{
dir1=normalize(other.velocity);
dir2=normalize(v_right);
dot_right= dir1*dir2;
if(dot_right >0.2)
{
if(dot_forward >0.2)
{
self.angles_y-=1*magnitude/100;
}
else if(dot_forward<-0.2)
{
self.angles_y+=1*magnitude/100;
}
}
else if(dot_right<-0.2)
{
if(dot_forward >0.2)
{
self.angles_y+=1*magnitude/100;
}
else if(dot_forward<-0.2)
{
self.angles_y-=1*magnitude/100;
}
}
}*/
}
}
void obj_catapult2 (void)
{
precache_model("models/cattest.mdl");
precache_sound ("misc/catlnch.wav");
precache_sound ("misc/catreset.wav");
precache_sound ("misc/catdrop.wav");
self.solid = SOLID_BBOX;
self.movetype = MOVETYPE_PUSHPULL;
self.touch=catapult2_touch;
// setmodel (self, "models/catapult.mdl");
setmodel (self, "models/cattest.mdl");
setsize(self,'-145 -145 0','145 145 26');
self.hull=HULL_SCORPION;
setorigin (self, self.origin);
self.wallspot=self.origin;
if(self.aflag==0)
self.aflag=256;//Max dist to move from origin- not working? Set to movetyp NONE if gets too far? then can;t turn...
self.classname="catapult";
self.level = 30;
self.frame=20;
self.th_pain=catapult_pain;
self.th_weapon=catapult_fire;
if (!self.speed)
self.speed = 300;//Too strong?
if (self.wait==0)
self.wait = 3;
self.th_die = chunk_death;
self.takedamage = DAMAGE_YES;
self.use=catapult_fire;
if(!self.thingtype)
self.thingtype = THINGTYPE_WOOD;
if(!self.mass)
self.mass = 1000;
if (!self.health)
self.health=1000;
self.max_health = self.health = self.health*2;
self.think=catapult_ready;
thinktime self : 0;
spawn_push_trigger(10);
}