/** * 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; }