diff --git a/src/train.h b/src/train.h index 66386b5c6a..dd2b2734f4 100644 --- a/src/train.h +++ b/src/train.h @@ -493,4 +493,6 @@ inline int GetTrainStopLocation(StationID station_id, TileIndex tile, Train *v, return GetTrainStopLocation(station_id, tile, v, update_train_state, station_ahead, station_length, v->x_pos, v->y_pos); } +int GetTrainEstimatedMaxAchievableSpeed(const Train *train, const int mass, const int speed_cap); + #endif /* TRAIN_H */ diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index a208e32851..6cf27b064b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -6919,3 +6919,62 @@ void TrainBrakesOverheatedBreakdown(Vehicle *v) t->breakdown_type = BREAKDOWN_BRAKE_OVERHEAT; t->breakdown_severity = 0; } + +static int GetTrainRealisticAccelerationAtSpeed(const Train *train, const int speed, const int mass) +{ + const int64 power = train->gcache.cached_power * 746ll; + int64 resistance = 0; + + const bool maglev = (GetRailTypeInfo(train->railtype)->acceleration_type == 2); + + if (!maglev) { + /* Static resistance plus rolling friction. */ + resistance = 10 * mass; + resistance += mass * (15 * (512 + speed) / 512); + } + + const int area = 14; + + resistance += (area * train->gcache.cached_air_drag * speed * speed) / 1000; + + uint32 max_te = train->gcache.cached_max_te; // [N] + int64 force; + + if (speed > 0) { + if (!maglev) { + /* Conversion factor from km/h to m/s is 5/18 to get [N] in the end. */ + force = power * 18 / (speed * 5); + + if (force > static_cast(max_te)) { + force = max_te; + } + } else { + force = power / 25; + } + } else { + force = (!maglev) ? std::min(max_te, power) : power; + force = std::max(force, (mass * 8) + resistance); + } + + /* Easy way out when there is no acceleration. */ + if (force == resistance) return 0; + + int acceleration = ClampToI32((force - resistance) / (mass * 4)); + acceleration = force < resistance ? std::min(-1, acceleration) : std::max(1, acceleration); + + return acceleration; +} + +int GetTrainEstimatedMaxAchievableSpeed(const Train *train, const int mass, const int speed_cap) +{ + int max_speed = 0; + int acceleration; + + do + { + max_speed++; + acceleration = GetTrainRealisticAccelerationAtSpeed(train, max_speed, mass); + } while (acceleration > 0 && max_speed < speed_cap); + + return max_speed; +} diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 6985c01d5b..4b19e1effd 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -410,65 +410,6 @@ int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab) return num; } -int GetAcceleration(const Train *train, const int speed, const int mass) -{ - const int64 power = train->gcache.cached_power * 746ll; - int64 resistance = 0; - - const bool maglev = (GetRailTypeInfo(train->railtype)->acceleration_type == 2); - - if (!maglev) { - /* Static resistance plus rolling friction. */ - resistance = 10 * mass; - resistance += mass * (15 * (512 + speed) / 512); - } - - const int area = 14; - - resistance += (area * train->gcache.cached_air_drag * speed * speed) / 1000; - - uint32 max_te = train->gcache.cached_max_te; // [N] - int64 force; - - if (speed > 0) { - if (!maglev) { - /* Conversion factor from km/h to m/s is 5/18 to get [N] in the end. */ - force = power * 18 / (speed * 5); - - if (force > static_cast(max_te)) { - force = max_te; - } - } else { - force = power / 25; - } - } else { - force = (!maglev) ? std::min(max_te, power) : power; - force = std::max(force, (mass * 8) + resistance); - } - - /* Easy way out when there is no acceleration. */ - if (force == resistance) return 0; - - int acceleration = ClampToI32((force - resistance) / (mass * 4)); - acceleration = force < resistance ? std::min(-1, acceleration) : std::max(1, acceleration); - - return acceleration; -} - -int GetMaxSpeed(const Train *train, const int mass, const int speed_cap) -{ - int max_speed = 0; - int acceleration; - - do - { - max_speed++; - acceleration = GetAcceleration(train, max_speed, mass); - } while (acceleration > 0 && max_speed < speed_cap); - - return max_speed; -} - /** * Draw the details for the given vehicle at the given position * @@ -590,8 +531,8 @@ void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_po } if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) { - const int empty_max_speed = GetMaxSpeed(v, empty_weight, v->GetDisplayMaxSpeed()); - const int loaded_max_speed = GetMaxSpeed(v, loaded_weight, v->GetDisplayMaxSpeed()); + const int empty_max_speed = GetTrainEstimatedMaxAchievableSpeed(v, empty_weight, v->GetDisplayMaxSpeed()); + const int loaded_max_speed = GetTrainEstimatedMaxAchievableSpeed(v, loaded_weight, v->GetDisplayMaxSpeed()); if (--vscroll_pos < 0 && vscroll_pos >= -vscroll_cap) { SetDParam(0, empty_weight);