- 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);
+ 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);