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;
+
/*
=============
PlayerJump
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(!doublejump && self.multijump_ready && self.multijump_count < cvar("g_multijump") && self.velocity_z > cvar("g_multijump_speed"))
+ {
+ // doublejump = FALSE; // checked above in the if
+ if (cvar("g_multijump") > 0)
+ {
+ if (cvar("g_multijump_add") == 0) // in this case we make the z velocity == jumpvelocity
+ {
+ if (self.velocity_z < mjumpheight)
+ {
+ doublejump = TRUE;
+ self.velocity_z = 0;
+ }
+ }
+ else
+ doublejump = TRUE;
+
+ if(doublejump)
+ {
+ if(self.movement_x != 0 || self.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
+ {
+ float curspeed;
+ vector wishvel, wishdir;
+
+ curspeed = max(
+ vlen(vec2(self.velocity)), // current xy speed
+ vlen(vec2(antilag_takebackavgvelocity(self, max(self.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
+ );
+ makevectors(self.v_angle_y * '0 1 0');
+ wishvel = v_forward * self.movement_x + v_right * self.movement_y;
+ wishdir = normalize(wishvel);
+
+ self.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
+ self.velocity_y = wishdir_y * curspeed;
+ // keep velocity_z unchanged!
+ }
+ self.multijump_count += 1;
+ }
+ }
+ self.multijump_ready = FALSE; // require releasing and pressing the jump button again for the next jump
+ }
+
if (!doublejump)
- if (!(self.flags & FL_ONGROUND))
- return;
+ if (!(self.flags & FL_ONGROUND))
+ return;
if(!sv_pogostick)
if (!(self.flags & FL_JUMPRELEASED))
if(self.health <= g_bloodloss)
return;
- if(g_runematch)
- {
- if(self.runes & RUNE_SPEED)
- {
- if(self.runes & CURSE_SLOW)
- mjumpheight = mjumpheight * cvar("g_balance_rune_speed_combo_jumpheight");
- else
- mjumpheight = mjumpheight * cvar("g_balance_rune_speed_jumpheight");
- }
- else if(self.runes & CURSE_SLOW)
- {
- mjumpheight = mjumpheight * cvar("g_balance_curse_slow_jumpheight");
- }
- }
-
- if(g_minstagib && (self.items & IT_INVINCIBLE))
- {
- mjumpheight = mjumpheight * cvar("g_minstagib_speed_jumpheight");
- }
-
// sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
// velocity bounds. Final velocity is bound between (jumpheight *
// min + jumpheight) and (jumpheight * max + jumpheight);
// using this move type for "big rigs"
// the engine does not push the entity!
- float accel, steer, f;
+ float accel, steer, f, myspeed, steerfactor;
vector angles_save, rigvel;
angles_save = self.angles;
- accel = bound(-1, self.movement_x / sv_maxspeed, 1);
- steer = bound(-1, self.movement_y / sv_maxspeed, 1);
+ accel = bound(-1, self.movement_x / self.stat_sv_maxspeed, 1);
+ steer = bound(-1, self.movement_y / self.stat_sv_maxspeed, 1);
if(g_bugrigs_reverse_speeding)
{
if(self.flags & FL_ONGROUND || g_bugrigs_air_steering)
{
- float myspeed, upspeed, steerfactor, accelfactor;
+ float upspeed, accelfactor;
myspeed = self.velocity * v_forward;
upspeed = self.velocity * v_up;
float mt;
rigvel_z -= frametime * sv_gravity; // 4x gravity plays better
- rigvel_xy = rigvel;
- rigvel_xy_z = 0;
+ rigvel_xy = vec2(rigvel);
if(g_bugrigs_planar_movement_car_jumping && !g_touchexplode) // touchexplode is a better way to handle collisions
mt = MOVE_NORMAL;
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);
}
vel_straight = self.velocity * wishdir;
vel_z = self.velocity_z;
- vel_xy = self.velocity - vel_z * '0 0 1';
+ vel_xy = vec2(self.velocity);
vel_perpend = vel_xy - vel_straight * wishdir;
step = accel * frametime * wishspeed0;
if(wishspeed > curspeed * 1.01)
{
- wishspeed = min(wishspeed, curspeed + sv_warsowbunny_airforwardaccel * sv_maxspeed * frametime);
+ wishspeed = min(wishspeed, curspeed + sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime);
}
else
{
- f = max(0, (sv_warsowbunny_topspeed - curspeed) / (sv_warsowbunny_topspeed - sv_maxspeed));
- wishspeed = max(curspeed, sv_maxspeed) + sv_warsowbunny_accel * f * sv_maxspeed * frametime;
+ f = max(0, (sv_warsowbunny_topspeed - curspeed) / (sv_warsowbunny_topspeed - self.stat_sv_maxspeed));
+ wishspeed = max(curspeed, self.stat_sv_maxspeed) + sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime;
}
wishvel = wishdir * wishspeed;
acceldir = wishvel - curvel;
addspeed = vlen(acceldir);
acceldir = normalize(acceldir);
- accelspeed = min(addspeed, sv_warsowbunny_turnaccel * sv_maxspeed * frametime);
+ accelspeed = min(addspeed, sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime);
if(sv_warsowbunny_backtosideratio < 1)
{
float speedaward_speed;
string speedaward_holder;
+string speedaward_uid;
void race_send_speedaward(float msg)
{
// send the best speed of the round
float speedaward_alltimebest;
string speedaward_alltimebest_holder;
+string speedaward_alltimebest_uid;
void race_send_speedaward_alltimebest(float msg)
{
// send the best speed
float buttons_prev;
float not_allowed_to_move;
string c;
+
+ maxspd_mod = 1;
+ if(g_minstagib && (self.items & IT_INVINCIBLE))
+ maxspd_mod *= cvar("g_minstagib_speed_highspeed");
+ if(g_nexball && self.ballcarried)
+ maxspd_mod *= cvar("g_nexball_basketball_carrier_highspeed");
+ if(g_runematch)
+ {
+ if(self.runes & RUNE_SPEED)
+ {
+ if(self.runes & CURSE_SLOW)
+ maxspd_mod *= cvar("g_balance_rune_speed_combo_highspeed");
+ else
+ maxspd_mod *= cvar("g_balance_rune_speed_highspeed");
+ }
+ else if(self.runes & CURSE_SLOW)
+ {
+ maxspd_mod *= cvar("g_balance_curse_slow_highspeed");
+ }
+ }
+ maxspd_mod *= autocvar_g_movement_highspeed;
// fix physics stats for g_movement_highspeed
- self.stat_sv_airaccel_qw = AdjustAirAccelQW(sv_airaccel_qw, autocvar_g_movement_highspeed);
+ self.stat_sv_airaccel_qw = AdjustAirAccelQW(sv_airaccel_qw, maxspd_mod);
if(sv_airstrafeaccel_qw)
- self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(sv_airstrafeaccel_qw, autocvar_g_movement_highspeed);
+ self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(sv_airstrafeaccel_qw, maxspd_mod);
else
self.stat_sv_airstrafeaccel_qw = 0;
- self.stat_sv_airspeedlimit_nonqw = sv_airspeedlimit_nonqw * autocvar_g_movement_highspeed;
+ self.stat_sv_airspeedlimit_nonqw = sv_airspeedlimit_nonqw * maxspd_mod;
+ self.stat_sv_maxspeed = sv_maxspeed * maxspd_mod; // also slow walking
if(self.PlayerPhysplug)
if(self.PlayerPhysplug())
maxspd_mod = 1;
- if(g_runematch)
- {
- if(self.runes & RUNE_SPEED)
- {
- if(self.runes & CURSE_SLOW)
- maxspd_mod = maxspd_mod * cvar("g_balance_rune_speed_combo_moverate");
- else
- maxspd_mod = maxspd_mod * cvar("g_balance_rune_speed_moverate");
- }
- else if(self.runes & CURSE_SLOW)
- {
- maxspd_mod = maxspd_mod * cvar("g_balance_curse_slow_moverate");
- }
- }
-
- if(g_minstagib && (self.items & IT_INVINCIBLE))
- {
- maxspd_mod = cvar("g_minstagib_speed_moverate");
- }
-
- if(g_nexball && self.ballcarried)
- {
- maxspd_mod = cvar("g_nexball_basketball_carrier_speed");
- }
-
swampspd_mod = 1;
if(self.in_swamp) {
swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
maxspd_mod = self.spectatorspeed;
}
- spd = max(sv_maxspeed, sv_maxairspeed) * maxspd_mod * swampspd_mod;
+ spd = max(self.stat_sv_maxspeed, sv_maxairspeed) * maxspd_mod * swampspd_mod;
if(self.speed != spd)
{
self.speed = spd;
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 (self.BUTTON_JUMP)
PlayerJump ();
else
if (self.waterlevel == WATERLEVEL_SWIMMING)
CheckWaterJump ();
+ self.prevjumpbutton = self.BUTTON_JUMP;
}
if (self.flags & FL_WATERJUMP )
// acceleration
wishdir = normalize(wishvel);
wishspeed = vlen(wishvel);
- if (wishspeed > sv_maxspeed*maxspd_mod)
- wishspeed = sv_maxspeed*maxspd_mod;
+ if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
+ wishspeed = self.stat_sv_maxspeed*maxspd_mod;
if (time >= self.teleport_time)
PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0, 0);
}
wishdir = normalize(wishvel);
wishspeed = vlen(wishvel);
- if (wishspeed > sv_maxspeed*maxspd_mod)
- wishspeed = sv_maxspeed*maxspd_mod;
+ if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
+ wishspeed = self.stat_sv_maxspeed*maxspd_mod;
wishspeed = wishspeed * 0.7;
// water friction
// acceleration
wishdir = normalize(wishvel);
wishspeed = vlen(wishvel);
- if (wishspeed > sv_maxspeed*maxspd_mod)
- wishspeed = sv_maxspeed*maxspd_mod;
+ if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
+ wishspeed = self.stat_sv_maxspeed*maxspd_mod;
if (time >= self.teleport_time)
{
// water acceleration
// acceleration
wishdir = normalize(wishvel);
wishspeed = vlen(wishvel);
- if (wishspeed > sv_maxspeed*maxspd_mod)
- wishspeed = sv_maxspeed*maxspd_mod;
+ if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
+ wishspeed = self.stat_sv_maxspeed*maxspd_mod;
if (self.crouch)
wishspeed = wishspeed * 0.5;
if (time >= self.teleport_time)
// acceleration
wishdir = normalize(wishvel);
wishspeed = wishspeed0 = vlen(wishvel);
- if (wishspeed0 > sv_maxspeed*maxspd_mod)
- wishspeed0 = sv_maxspeed*maxspd_mod;
+ if (wishspeed0 > self.stat_sv_maxspeed*maxspd_mod)
+ wishspeed0 = self.stat_sv_maxspeed*maxspd_mod;
if (wishspeed > maxairspd)
wishspeed = maxairspd;
if (self.crouch)
// 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);
if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed) {
speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1');
speedaward_holder = self.netname;
+ speedaward_uid = self.crypto_idfp;
speedaward_lastupdate = time;
}
if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1) {
rr = RACE_RECORD;
race_send_speedaward(MSG_ALL);
speedaward_lastsent = speedaward_speed;
- if (speedaward_speed > speedaward_alltimebest) {
+ if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "") {
speedaward_alltimebest = speedaward_speed;
speedaward_alltimebest_holder = speedaward_holder;
+ speedaward_alltimebest_uid = speedaward_uid;
db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest));
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/netname"), speedaward_alltimebest_holder);
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid);
race_send_speedaward_alltimebest(MSG_ALL);
}
}
}
+
+ float xyspeed;
+ xyspeed = vlen('1 0 0' * self.velocity_x + '0 1 0' * self.velocity_y);
+ if(self.weapon == WEP_NEX && cvar("g_balance_nex_charge") && cvar("g_balance_nex_charge_velocity_rate") && xyspeed > cvar("g_balance_nex_charge_minspeed"))
+ {
+ // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+ xyspeed = min(xyspeed, cvar("g_balance_nex_charge_maxspeed"));
+ f = (xyspeed - cvar("g_balance_nex_charge_minspeed")) / (cvar("g_balance_nex_charge_maxspeed") - cvar("g_balance_nex_charge_minspeed"));
+ // add the extra charge
+ self.nex_charge = min(1, self.nex_charge + cvar("g_balance_nex_charge_velocity_rate") * f * frametime);
+ }
:end
if(self.flags & FL_ONGROUND)
self.lastground = time;