/**
* Sets the new speed for an aircraft
* @param v The vehicle for which the speed should be obtained
* @param speed_limit The maximum speed the vehicle may have.
* @param hard_limit If true, the limit is directly enforced, otherwise the plane is slowed down gradually
* @return The number of position updates needed within the tick
*/
static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true)
{
/**
* 'acceleration' has the unit 3/8 mph/tick. This function is called twice per tick.
* So the speed amount we need to accelerate is:
* acceleration * 3 / 16 mph = acceleration * 3 / 16 * 16 / 10 km-ish/h
* = acceleration * 3 / 10 * 256 * (km-ish/h / 256)
* ~ acceleration * 77 (km-ish/h / 256)
*/
uint spd = v->acceleration * 77;
byte t;
/* Adjust speed limits by plane speed factor to prevent taxiing
* and take-off speeds being too low. */
speed_limit *= _settings_game.vehicle.plane_speed;
/* adjust speed for broken vehicles */
if (v->vehstatus & VS_AIRCRAFT_BROKEN) {
if (speed_limit > SPEED_LIMIT_BROKEN) hard_limit = false;
speed_limit = min(speed_limit, SPEED_LIMIT_BROKEN);
}
if (v->vcache.cached_max_speed < speed_limit) {
if (v->cur_speed < speed_limit) hard_limit = false;
speed_limit = v->vcache.cached_max_speed;
}
v->subspeed = (t = v->subspeed) + (byte)spd;
/* Aircraft's current speed is used twice so that very fast planes are
* forced to slow down rapidly in the short distance needed. The magic
* value 16384 was determined to give similar results to the old speed/48
* method at slower speeds. This also results in less reduction at slow
* speeds to that aircraft do not get to taxi speed straight after
* touchdown. */
if (!hard_limit && v->cur_speed > speed_limit) {
speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
}
spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
/* updates statusbar only if speed have changed to save CPU time */
if (spd != v->cur_speed) {
v->cur_speed = spd;
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
/* Adjust distance moved by plane speed setting */
if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
/* Convert direction-independent speed into direction-dependent speed. (old movement method) */
spd = v->GetOldAdvanceSpeed(spd);
spd += v->progress;
v->progress = (byte)spd;
return spd >> 8;
}