nuclide/Source/Server/PhysicsMove.c
Marco Hladik bf1adc491a Support for more muzzleflashes
Fixes and cleanups regarding effects, networking
All sorts of other cool things
2017-01-14 16:00:31 +01:00

257 lines
6.1 KiB
C

#define movevars_stepheight 22
#define movevars_friction 4
#define movevars_gravity 800
#define movevars_accelerate 10
#define movevars_stopspeed 100
#define movevars_maxspeed 320
#define movevars_jumpheight 270
.float pmove_flags;
.float gravity;
enumflags {
PMF_JUMP_HELD,
PMF_RESERVED,
PMF_ONGROUND
};
static void dotouch( entity tother ) {
entity oself;
if (tother.touch == __NULL__)
return;
oself = self;
other = self;
self = tother;
self.touch();
self = oself;
}
void PhysicsMove_Rebound(vector surfnorm) {
float v;
v = self.velocity*surfnorm;
self.velocity = self.velocity - surfnorm*(v);
}
//move forwards (preferably on the level) (does step ups)
void PhysicsMove_Move(void) {
vector dest;
vector saved_plane_normal;
float stepped;
float movetime;
float attempts;
//we need to bounce off surfaces (in order to slide along them), so we need at 2 attempts
for (attempts = 3, movetime = input_timelength; movetime>0 && attempts; attempts--)
{
dest = self.origin + self.velocity*movetime;
tracebox(self.origin, self.mins, self.maxs, dest, FALSE, self); //try going straight there
self.origin = trace_endpos;
if (trace_fraction < 1)
{
saved_plane_normal = trace_plane_normal;
movetime -= movetime * trace_fraction;
if (movetime)
{
//step up if we can
trace_endpos = self.origin;
trace_endpos_z += movevars_stepheight;
tracebox( self.origin, self.mins, self.maxs, trace_endpos, FALSE, self );
stepped = trace_endpos_z - self.origin_z;
dest = trace_endpos + self.velocity*movetime;
dest_z = trace_endpos_z;
//move forwards
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
//if we got anywhere, make this raised-step move count
if (trace_fraction != 0)
{
if (trace_fraction < 1)
PhysicsMove_Rebound(trace_plane_normal);
//move down
dest = trace_endpos;
dest_z -= stepped+1;
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
if (trace_fraction < 1)
PhysicsMove_Rebound(trace_plane_normal);
self.origin = trace_endpos;
movetime -= movetime * input_timelength;
continue;
}
}
//stepping failed, just bounce off
PhysicsMove_Rebound(saved_plane_normal);
dotouch(trace_ent);
}
else
break;
}
}
/*
void(vector dest) PhysicsMove_StepMove =
{
//we hit something...
//step up
src = trace_endpos;
trace_endpos_z += movevars_stepheight;
tracebox(src, self.mins, self.maxs, dest, FALSE, self);
stepped = trace_endpos_z - src_z;
dest_z += stepped;
//move forwards
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
//move down
dest_z -= stepped;
tracebox(trace_endpos, self.mins, self.maxs, dest, FALSE, self);
}
*/
void PhysicsMove_ApplyFriction( void ) {
float newspeed, oldspeed;
oldspeed = vlen(self.velocity);
if (oldspeed < 1)
{
self.velocity = '0 0 0';
return;
}
//calculate what their new speed should be
newspeed = oldspeed - oldspeed*movevars_friction*input_timelength;
//and slow them
if (newspeed < 0)
newspeed = 0;
self.velocity = self.velocity * (newspeed/oldspeed);
}
void PhysicsMove_Accelerate(vector wishdir, float wishspeed, float accel) {
float addspeed, accelspeed;
float d;
d = self.velocity*wishdir;
addspeed = wishspeed - (d);
if (addspeed <= 0)
return;
accelspeed = accel*input_timelength*wishspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
self.velocity = self.velocity + accelspeed*wishdir;
}
void PhysicsMove_InAirAccelerate( void ) {
vector hforward;
vector hright;
vector desireddir;
float desiredspeed;
hforward = v_forward;
hforward_z = 0;
hforward = normalize(hforward);
hright = v_right;
hright_z = 0;
hright = normalize(hright);
desireddir = hforward*input_movevalues_x + hright*input_movevalues_y;
desiredspeed = vlen(desireddir);
desireddir = normalize(desireddir);
if (desiredspeed > movevars_maxspeed)
desiredspeed = movevars_maxspeed;
if (self.pmove_flags & PMF_ONGROUND)
{
if (input_buttons & 2)
{
if (!(self.pmove_flags & PMF_JUMP_HELD))
{
self.velocity_z += movevars_jumpheight;
self.pmove_flags (+) PMF_ONGROUND;
}
}
}
if (self.pmove_flags & PMF_ONGROUND)
{
PhysicsMove_ApplyFriction();
PhysicsMove_Accelerate(desireddir, desiredspeed, movevars_accelerate);
}
else
{
//there's no friction in air...
if (desiredspeed > 30)
desiredspeed = 30;
PhysicsMove_Accelerate(desireddir, desiredspeed, movevars_accelerate);
if (self.gravity)
self.velocity_z -= self.gravity * movevars_gravity * input_timelength;
else
self.velocity_z -= movevars_gravity * input_timelength;
}
}
void PhysicsMove_NoclipAccelerate( void ) {
vector desireddir;
float desiredspeed;
desireddir = v_forward*input_movevalues_x + v_right*input_movevalues_y+v_up*input_movevalues_z;
desiredspeed = vlen(desireddir);
desireddir = normalize(desireddir);
PhysicsMove_ApplyFriction();
PhysicsMove_Accelerate(desireddir, desiredspeed, movevars_accelerate);
}
void PhysicsMove_Categorise( void ) {
//if we're moving up, we're not on the ground
if (self.velocity_z > 0)
self.pmove_flags (-) PMF_ONGROUND;
else
{
//don't know, maybe we are, maybe we're not
tracebox(self.origin, self.mins, self.maxs, self.origin-'0 0 1', FALSE, self);
if (trace_fraction == 1 || trace_plane_normal_z < 0.7) {
self.pmove_flags (-) PMF_ONGROUND;
// self.groundentity = trace_ent;
}
else
self.pmove_flags (+) PMF_ONGROUND;
}
}
void PhysicsMove( entity eEnt ) {
self = eEnt;
makevectors(input_angles);
if (!(input_buttons & PMF_JUMP_HELD))
self.pmove_flags (-) PMF_JUMP_HELD;
PhysicsMove_Categorise();
switch ( self.movetype ) {
case MOVETYPE_WALK:
PhysicsMove_InAirAccelerate();
PhysicsMove_Move();
break;
case MOVETYPE_FLY:
PhysicsMove_NoclipAccelerate();
PhysicsMove_Move();
break;
case MOVETYPE_NOCLIP:
PhysicsMove_NoclipAccelerate();
self.origin += self.velocity*input_timelength;
break;
case MOVETYPE_NONE:
break;
}
}