float sv_airstrafeaccel_qw;
float sv_aircontrol;
float sv_aircontrol_power;
+float sv_aircontrol_penalty;
float sv_warsowbunny_airforwardaccel;
float sv_warsowbunny_accel;
float sv_warsowbunny_topspeed;
.float wasFlying;
.float spectatorspeed;
+.float multijump_count;
+.float multijump_ready;
+.float prevjumpbutton;
+
+.float prevtopspeed; // store the top speed during the last 0.25 seconds to make dodging at full speeds easier
+.float prevtopspeed_time;
+
/*
=============
PlayerJump
return;
}
- if (!doublejump)
- if (!(self.flags & FL_ONGROUND))
- return;
+ if (cvar("g_multijump"))
+ {
+ if (self.prevjumpbutton == FALSE && !(self.flags & FL_ONGROUND)) // jump button pressed this frame and we are in midair
+ self.multijump_ready = TRUE; // this is necessary to check that we released the jump button and pressed it again
+ else
+ self.multijump_ready = FALSE;
+ }
+
+ if(self.multijump_ready && self.multijump_count < cvar("g_multijump") && self.velocity_z > cvar("g_multijump_speed"))
+ {
+ if (cvar("g_multijump") > 0)
+ {
+ if (cvar("g_multijump_add") == 0) // in this case we make the z velocity == jumpvelocity
+ self.velocity_z = 0;
+
+ float curspeed;
+ curspeed = vlen(self.velocity);
+ local vector wishvel, wishdir;
+ makevectors(self.v_angle);
+ wishvel = v_forward * self.movement_x + v_right * self.movement_y;
+ wishdir = normalize(wishvel);
+ if(wishdir_x != 0 && wishdir_y != 0) // don't remove all speed if player isnt pressing any movement keys
+ {
+ self.velocity_x = wishdir_x * max(curspeed, self.prevtopspeed); // allow "dodging" at a multijump
+ self.velocity_y = wishdir_y * max(curspeed, self.prevtopspeed);
+ }
+ self.multijump_count += 1;
+ }
+ self.multijump_ready = FALSE; // require releasing and pressing the jump button again for the next jump
+ }
+ else if (!doublejump)
+ if (!(self.flags & FL_ONGROUND))
+ return;
if(!sv_pogostick)
if (!(self.flags & FL_JUMPRELEASED))
if(dot > 0) // we can't change direction while slowing down
{
- k *= fabs(sv_aircontrol)*pow(dot, sv_aircontrol_power)*frametime;
+ k *= pow(dot, sv_aircontrol_power)*frametime;
+ xyspeed = max(0, xyspeed - sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32);
+ k *= sv_aircontrol;
self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
}
string GetMapname(void);
float speedaward_lastupdate;
float speedaward_lastsent;
-var float autocvar_g_movement_highspeed = 1;
void SV_PlayerPhysics()
{
local vector wishvel, wishdir, v;
float buttons_prev;
float not_allowed_to_move;
string c;
-
+
// fix physics stats for g_movement_highspeed
self.stat_sv_airaccel_qw = AdjustAirAccelQW(sv_airaccel_qw, autocvar_g_movement_highspeed);
if(sv_airstrafeaccel_qw)
if(self.classname == "player")
{
+ if(self.flags & FL_ONGROUND)
+ {
+ if (cvar("g_multijump") > 0)
+ self.multijump_count = 0;
+ else
+ self.multijump_count = -2; // the cvar value for infinite jumps is -1, so this needs to be smaller
+ }
+
+ if(vlen(self.velocity) >= self.prevtopspeed || time - self.prevtopspeed_time > 0.25)
+ {
+ self.prevtopspeed_time = time;
+ self.prevtopspeed = vlen('1 0 0' * self.velocity_x + '0 1 0' * self.velocity_y);
+ }
+
if (self.BUTTON_JUMP)
PlayerJump ();
else
if (self.waterlevel == WATERLEVEL_SWIMMING)
CheckWaterJump ();
+ self.prevjumpbutton = self.BUTTON_JUMP;
}
if (self.flags & FL_WATERJUMP )
// CPM
if(sv_airstopaccelerate)
- if(self.velocity * wishdir < 0)
- airaccel = sv_airstopaccelerate*maxspd_mod;
+ {
+ vector curdir;
+ curdir = self.velocity;
+ curdir_z = 0;
+ curdir = normalize(curdir);
+ airaccel = airaccel + (sv_airstopaccelerate*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
+ }
// note that for straight forward jumping:
// step = accel * frametime * wishspeed0;
// accel = bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);