- addspeed = wishspeed - vel_straight;
- if(addspeed > 0)
- vel_straight = vel_straight + min(addspeed, accel * s->cmd.frametime * wishspeed) * accelqw;
- if(wishspeed > 0)
- vel_straight = vel_straight + min(wishspeed, accel * s->cmd.frametime * wishspeed) * (1 - accelqw);
-
- VectorScale(vel_perpend, 1 - s->cmd.frametime * wishspeed * sidefric, vel_perpend);
+ step = accel * s->cmd.frametime * wishspeed0;
+
+ vel_xy_current = VectorLength(vel_xy);
+ if(speedlimit > 0)
+ accelqw = CL_ClientMovement_Physics_AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
+ vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
+ vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
+ if(vel_xy_backward < 0)
+ vel_xy_backward = 0; // not that it REALLY occurs that this would cause wrong behaviour afterwards
+
+ vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
+
+ if(sidefric < 0 && VectorLength2(vel_perpend))
+ // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
+ {
+ vec_t f, fmin;
+ f = max(0, 1 + s->cmd.frametime * wishspeed * sidefric);
+ fmin = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / VectorLength2(vel_perpend);
+ // assume: fmin > 1
+ // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
+ // vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
+ // vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
+ // obviously, this cannot be
+ if(fmin <= 0)
+ VectorScale(vel_perpend, f, vel_perpend);
+ else
+ {
+ fmin = sqrt(fmin);
+ VectorScale(vel_perpend, max(fmin, f), vel_perpend);
+ }
+ }
+ else
+ VectorScale(vel_perpend, max(0, 1 - s->cmd.frametime * wishspeed * sidefric), vel_perpend);