hexen2-hw-hc/plats_mp.hc

634 lines
15 KiB
C++

float SLOPE = 16; //Trains- follow angle for vec between path_corners
float ANGLEMATCH = 32;
float USE_ORIGIN = 64;
float ANGLE_WAIT = 128;
void() train_next_mp;
void() func_train_find_mp;
void rider_die(){}
void() train_blocked_mp =
{
// dprint("train blocked\n");
if (time < self.attack_finished) return;
self.attack_finished = time + 0.5;
if(self.dmg==-1&&self.anglespeed>0)
{
float on_top,in_front,to_right,other_dist;
vector avel, other_dir, throw_dir;
avel = normalize(self.avelocity);
makevectors(self.angles);
other_dir = normalize(other.origin-self.origin);
other_dist = vlen(other.origin - self.origin);
if(v_forward*other_dir>0)//in front
in_front=TRUE;
if(v_right*other_dir>0)//to right
to_right=TRUE;
if(v_up*other_dir>0)//on top
on_top=TRUE;
if(avel_x>0)//pitch
if(on_top)
throw_dir_z+=self.anglespeed;
else
throw_dir_z+=self.anglespeed*-1;
if(avel_y>0)//yaw
if(in_front)
throw_dir+=v_right*self.anglespeed;
else
throw_dir+=v_right*self.anglespeed*-1;
if(avel_z>0)//roll
if(!to_right)
throw_dir_z+=self.anglespeed;
else
throw_dir_z+=self.anglespeed*-1;
other.velocity=throw_dir;
other.flags(-)FL_ONGROUND;
}
else
T_Damage (other, self, self, self.dmg);
};
void() train_use_mp =
{
if(self.movechain.model=="models/soulskul.mdl")
{//Hack to make Jeremy happy
self.weaponmodel="";
self.movechain.think=rider_die;
thinktime self.movechain : 0.1;
}
if(self.wait==-1)
self.use=SUB_Null;
if (self.spawnflags & TRAIN_GLOW)
{
self.effects = EF_BRIGHTLIGHT;
}
if (self.decap != 1)
{ //Moving?
self.decap = 1;
if (self.think != train_next_mp)
{
// dprintf("Train wait %s first used by",self.wait);
// dprint(other.classname);
// dprint("\n");
self.think = func_train_find_mp;
train_next_mp();
}
}
else
{
if (self.spawnflags & TRAIN_RETURN)
self.decap = 0;
else
{
// dprintf("Train wait %s used whilst moving by",self.wait);
// dprint(other.classname);
// dprint("\n");
self.decap = 2;
}
}
};
void() train_wait_mp =
{
//Check to make sure train is active
//dprintf("wait func- my wait is :%s\n",self.wait);
if(self.decap!=2)
{
//dprint("Train not 2 decap\n");
self.think = train_next_mp;
if(self.wait==-2)
{
//dprint("Train breaking\n");
stopSound(self,CHAN_UPDATE);
//sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, "misc/null.wav", 1, ATTN_NONE);
//dprint("Train wait of -2\n");
if(self.th_die)
{
if(self.pausetime)
{
self.think=self.th_die;
self.nextthink=self.ltime+self.pausetime;
}
else
{
self.th_die();
return;
}
}
else
{
if(self.pausetime)
{
self.think=chunk_death;
self.nextthink=self.ltime+self.pausetime;
}
else
{
chunk_death();
return;
}
}
}
else if(self.wait==-1||self.wait==-3)
{
//dprint("Train wait of -1 or -3\n");
if(self.level)
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NORM);
else
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NORM);
self.nextthink=-1;
}
else if (self.wait)
{
if(self.level)
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NONE);
else
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NORM);
self.nextthink = self.ltime + self.wait;
//dprintf("Next think: %s\n",self.nextthink);
//dprintf("Time: %s\n",time);
}
else
{
self.nextthink = self.ltime + 0.1;
//dprint("Train no wait\n");
}
}
else
{
if(self.level)
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NONE);
else
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise, 1, ATTN_NORM);
}
if (self.decap == 0 || self.decap == 2)
if(!self.effects&EF_NODRAW)
self.effects = 0;
else
self.effects=EF_NODRAW;
};
void() train_rotate_mp =
{
entity targ;
vector dir;
targ = self.enemy;
if (targ.mangle_x != 0 || targ.mangle_y != 0 || targ.mangle_z != 0)
{
dir = self.angles;
dir += targ.mangle;
if(self.wait)
SUB_CalcAngleMove (dir, self.anglespeed, train_wait_mp);
else
SUB_CalcAngleMove (dir, self.anglespeed, train_next_mp);
}
else if(self.wait)
train_wait_mp();
else
train_next_mp();
};
void() train_next_mp =
{//NOTE!!! WHEN A TRAIN HAS A WAIT <= TIME, IT STOPS!!!
entity oldtarg,targ;
vector dir,end_spot;
vector slope_angles;
/* if(self.movechain)
{
dprint(self.movechain.model);
dprint(" moving\n");
}
*/
//float targ_aspeed;//,targ_speed;
/*
dprint("Next target: ");
dprint(self.target);
dprint("\n");
*/
targ = find (world, targetname, self.target);
self.target = targ.target;
if (!self.decap && self.spawnflags & TRAIN_RETURN)
if (self.noise3 == targ.targetname)
self.decap = 2;
if (!self.target)
objerror ("train_next: no next target");
// else
// dprint("Found next target\n");
if (targ.wait)
self.wait = targ.wait;
// if(self.wait)
// dprintf("My wait is: %s\n",self.wait);
// else
// self.wait = 0;
oldtarg=self.enemy;
self.enemy = targ;
if(self.level)
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise1, 1, ATTN_LOOP);
else
sound (self, CHAN_UPDATE+PHS_OVERRIDE_R, self.noise1, 1, ATTN_LOOP);
/*Used to not set self speed to targ speed
if(targ.speed)
targ_speed=targ.speed;
else
targ_speed = self.speed;
*/
if(targ.speed)
self.speed=targ.speed;
// dprintf("Train's speed now: %s\n",targ_speed);
if(self.spawnflags&SLOPE)
{
// dprint("Train auto-sloping\n");
//Make everything 0 - 359
while(self.angles_x>359)
self.angles_x -= 360;
while(self.angles_x<0)
self.angles_x += 360;
// while(self.angles_y>359)
// self.angles_y -= 360;
// while(self.angles_y<0)
// self.angles_y += 360;
slope_angles = vectoangles(normalize(targ.origin - self.origin));
while(slope_angles_x>359)
slope_angles_x -= 360;
while(slope_angles_x<0)
slope_angles_x += 360;
// while(slope_angles_y>359)
// slope_angles_y -= 360;
// while(slope_angles_y<0)
// slope_angles_y += 360;
targ.mangle_x = self.angles_x - slope_angles_x;
// targ.mangle_y = self.angles_y - slope_angles_y;
// if(targ.mangle_x<-180)
// targ.mangle_x+=360;
// else if(targ.mangle_x>180)
// targ.mangle_x-=360;
// if(targ.mangle_y<-180)
// targ.mangle_y+=360;
// else if(targ.mangle_y>180)
// targ.mangle_y-=360;
/*
Don't mod roll
if(targ.mangle_z>180)
targ.mangle_z= (180 - (targ.mangle_z - 180))*-1;
else if(targ.mangle_z<-180)
targ.mangle_z= 180 - (targ.mangle_z + 180);
*/
// dprintv("Target mangle: %s\n",targ.mangle);
}
if(self.spawnflags&USE_ORIGIN&&self.origin!='0 0 0')
end_spot = targ.origin;
else
end_spot = targ.origin - self.mins;
if (!self.spawnflags&ANGLE_WAIT&&(targ.mangle_x != 0 || targ.mangle_y != 0 || targ.mangle_z != 0))
{
dir = self.angles;
dir += targ.mangle;
// dprint ("move and rotate\n");
if(targ.anglespeed)
self.anglespeed=targ.anglespeed;
if(targ.spawnflags&SYNCH||self.spawnflags&SLOPE)
{
if(!self.wait)
SUB_CalcMoveAndAngleInit (end_spot, self.speed, dir, self.anglespeed, train_next_mp,TRUE);
else
SUB_CalcMoveAndAngleInit (end_spot, self.speed, dir, self.anglespeed, train_wait_mp,TRUE);
}
else
{
if(!self.wait)
SUB_CalcMoveAndAngleInit (end_spot, self.speed, dir, self.anglespeed, train_next_mp,FALSE);
else
SUB_CalcMoveAndAngleInit (end_spot, self.speed, dir, self.anglespeed, train_wait_mp,FALSE);
}
}
else
{
if(targ.mangle_x != 0 || targ.mangle_y != 0 || targ.mangle_z != 0)
{
// dprint ("move then rotate\n");
SUB_CalcMove (end_spot, self.speed, train_rotate_mp);
}
else
{
// dprintv("move- no rotate %s\n",targ.mangle);
if(!self.wait)
SUB_CalcMove (end_spot, self.speed, train_next_mp);
else
SUB_CalcMove (end_spot, self.speed, train_wait_mp);
}
}
if (self.spawnflags & TRAIN_WAITTRIG)
self.decap = 2;
};
void() func_train_find_mp =
{
entity targ;
targ = find (world, targetname, self.target);
self.enemy=targ;
self.target = targ.target;
if(self.spawnflags&USE_ORIGIN&&self.origin!='0 0 0')
setorigin (self, targ.origin);
else
setorigin (self, targ.origin - self.mins);
if(targ.mangle_x)
{
// dprint("taking path's x\n");
self.angles_x = targ.mangle_x;
}
if(targ.mangle_y)
{
// dprint("taking path's y\n");
self.angles_y = targ.mangle_y;
}
if(targ.mangle_z)
{
// dprint("taking path's z\n");
self.angles_z = targ.mangle_z;
}
if (!self.targetname)
{ // not triggered, so start immediately
self.decap = 1;
self.nextthink = self.ltime + 0.1;
self.think = train_next_mp;
}
};
/*QUAKED func_train_mp (0 .5 .8) ? invisible TOGGLE RETURN TRANSLUCENT SLOPE ANGLEMATCH USE_ORIGIN ANGLEWAIT
Hexen 2 MISSION PACK version Trains
Remember: angles and mangles are 'x y z' format where x = pitch, y = yaw and z = roll
Trains are moving platforms that players can ride.
The targets origin specifies the min point of the train at each corner.
The train spawns at the first target it is pointing at.
If the train is the target of a button or trigger, it will not begin moving until activated.
speed default 100
dmg default 2
soundtype
0) none
1) ratchet metal
2) pullies
3) sliding
4) normal?
5) medival?
6) guillotine?
7) chain?
8) Rolling boulder
9) Spinning prayer wheel
if train is only moving to one spot
"angle" - to tell it's direction
"distance" - in pixels, how far to move
"speed" - how fast it moves between spots (default=100)
"anglespeed" - how fast it rotates to a new angle (default = 100)
"wait" - -1 will make it stop forever, -2 will make it blow up (you can put the waits on the pathcorners and it will take the wait from there.
-3 will make the train stop and wait for the next trigger event (don't blame me!- Blame Josh!)
NOTE: If you give it a wait of -2, be sure to set the thingtype.
"pausetime" - How long to wait after getting to the end of it's path before blowing up, default is 0
"weaponmodel" - A model file to use instead of train visuals, but will have the blocking shape of the train you make
WARNING: use "directory/model.mdl" format- NOT a "\"!!!
NOTE: You should use a origin brush in the train and make sure you know where the origin of the model you're using is at.
if set to "models/null.spr", it will effectively make an invisible train.
thingtype - type of chunks and sprites it will generate
0 - glass
1 - grey stone (default for trains)
2 - wood
3 - metal
4 - flesh
5 - fire
6 - clay
7 - leaves
8 - hay
9 - brown stone
10 - cloth
11 - wood & leaf
12 - wood & metal
13 - wood stone
14 - metal stone
15 - metal cloth
16 - spider web
17 - stained glass
18 - ice
19 - clear glass
20 - red glass
The train will modify it's angles by whatever angles it's next path point has, so if it heads towards a path corner with an angle of '0 90 0', the train will rotate '0 90 0' on it's way to the pathpoint. If you make the anglespeed the same as the angle, the turn should finish right as the train gets to the new spot.
NOTE: A path_corner using spawnflag "SYNCH" will make the train automatically calculate a new anglespeed based on the distance it's going and will finish the turn at the same time the move is done.
As usual, any rotating brush needs an origin brush.
"abslight" - to set the absolute light level
"angles" - only used for models attached to trains.
"level" - if set to "1" sounds from train have no attenuation (can always be heard no matter how far player is away)
if "invisible" is checked, train will be invisible and not solid
SLOPE - Train will automatically find the pitch and yaw it needs to get from path_corner to path_corner
ANGLEMATCH - If it has an attached model, that model's angles will change with the train's
USE_ORIGIN - Use an origin brush as origin for moving along path, not south-west-bottom corner.
ANGLE_WAIT - Train will not change angles until it reached path_corner, and will not move again until that angle movement is done
*/
void() func_train_mp =
{
entity targ;
if(!world.spawnflags&MISSIONPACK)
{
func_train();
return;
}
if(self.dmg==666)
if(mapname=="tibet9")
self.dmg=50;
self.decap = 0;
if (self.spawnflags & TRAIN_GLOW)
{
self.solid=SOLID_NOT;
self.effects(+)EF_NODRAW;
}
else
{
self.solid = SOLID_BSP;
setmodel (self, self.model);
if(self.weaponmodel)
{
self.movechain=spawn();
self.movechain.model=self.weaponmodel;
self.movechain.movetype=MOVETYPE_NOCLIP;
self.movechain.solid=SOLID_NOT;
precache_model2(self.movechain.model);
setmodel (self.movechain, self.movechain.model);
setorigin(self.movechain,self.origin);
self.effects(+)EF_NODRAW;
self.weaponmodel="";
self.movechain.angles=self.angles;
self.angles='0 0 0';
if(self.abslight)
{
self.movechain.drawflags(+)MLS_ABSLIGHT;
self.movechain.abslight=self.abslight;
}
if(self.spawnflags&ANGLEMATCH)//Match angles
self.movechain.flags(+)FL_MOVECHAIN_ANGLE;
}
}
if (!self.speed)
self.speed = 100;
if (!self.anglespeed)
self.anglespeed = 100;
if (!self.target)
objerror ("func_train without a target");
if (!self.dmg)
self.dmg = 2;
if(self.health)
{
self.takedamage=DAMAGE_YES;
self.th_die=chunk_death;
if(!self.thingtype)
self.thingtype=1;
}
if(self.soundtype==1)
{
self.noise = "plats/train2.wav";
self.noise1 = "plats/train1.wav";
}
else if(self.soundtype==2)
{
self.noise = "plats/pulyplt2.wav";
self.noise1 = "plats/pulyplt1.wav";
}
else if(self.soundtype==3)
{
self.noise = "plats/platstp.wav";
precache_sound3("plats/platstp.wav");
self.noise1 = "plats/platslid.wav";
precache_sound3("plats/platslid.wav");
}
else if(self.soundtype==4)
{
self.noise = "plats/plat2.wav";
self.noise1 = "plats/plat1.wav";
}
else if(self.soundtype==5)
{
self.noise = "plats/medplat2.wav";
self.noise1 = "plats/medplat1.wav";
}
else if(self.soundtype==6)
{
self.noise = "plats/guiltin2.wav";
self.noise1 = "plats/guiltin1.wav";
}
else if(self.soundtype==7)
{
self.noise = "plats/chainplt2.wav";
self.noise1 = "plats/chainplt1.wav";
}
else if(self.soundtype==8)
{
self.noise = "plats/boldstop.wav"; //stop
precache_sound3("plats/boldstop.wav");
self.noise1 = "plats/boldroll.wav"; //moving
precache_sound3("plats/boldroll.wav");
}
else if(self.soundtype==9)
{
self.noise = "plats/pwheel2.wav";
precache_sound3("plats/pwheel2.wav");
self.noise1 = "plats/pwheel1.wav";
precache_sound3("plats/pwheel1.wav");
}
else
self.noise = self.noise1 = "misc/null.wav";
precache_sound (self.noise);
precache_sound (self.noise1);
if(self.wait==-2)
{
if(!self.thingtype)
self.thingtype=1;
if(!self.th_die)
self.th_die=chunk_death;
}
self.cnt = 1;
self.movetype = MOVETYPE_PUSH;
self.blocked = train_blocked_mp;
self.use = train_use_mp;
// self.classname = "train";
setsize (self, self.mins , self.maxs);
setorigin (self, self.origin);
targ = find(world, target, self.target);
self.noise3 = targ.target;
if(self.spawnflags&SLOPE)
self.spawnflags(+)SYNCH;
if (self.abslight)
self.drawflags(+)MLS_ABSLIGHT;
if (self.spawnflags & 8)
{
self.drawflags(+)DRF_TRANSLUCENT;
self.solid = SOLID_NOT;
}
// start trains on the second frame, to make sure their targets have had
// a chance to spawn
self.nextthink = self.ltime + 0.1;
self.think = func_train_find_mp;
};