Rename and move train max speed estimation functions
This commit is contained in:
@@ -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);
|
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 */
|
#endif /* TRAIN_H */
|
||||||
|
@@ -6919,3 +6919,62 @@ void TrainBrakesOverheatedBreakdown(Vehicle *v)
|
|||||||
t->breakdown_type = BREAKDOWN_BRAKE_OVERHEAT;
|
t->breakdown_type = BREAKDOWN_BRAKE_OVERHEAT;
|
||||||
t->breakdown_severity = 0;
|
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<int>(max_te)) {
|
||||||
|
force = max_te;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
force = power / 25;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
force = (!maglev) ? std::min<uint64>(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;
|
||||||
|
}
|
||||||
|
@@ -410,65 +410,6 @@ int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab)
|
|||||||
return num;
|
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<int>(max_te)) {
|
|
||||||
force = max_te;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
force = power / 25;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
force = (!maglev) ? std::min<uint64>(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
|
* 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) {
|
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) {
|
||||||
const int empty_max_speed = GetMaxSpeed(v, empty_weight, v->GetDisplayMaxSpeed());
|
const int empty_max_speed = GetTrainEstimatedMaxAchievableSpeed(v, empty_weight, v->GetDisplayMaxSpeed());
|
||||||
const int loaded_max_speed = GetMaxSpeed(v, loaded_weight, v->GetDisplayMaxSpeed());
|
const int loaded_max_speed = GetTrainEstimatedMaxAchievableSpeed(v, loaded_weight, v->GetDisplayMaxSpeed());
|
||||||
|
|
||||||
if (--vscroll_pos < 0 && vscroll_pos >= -vscroll_cap) {
|
if (--vscroll_pos < 0 && vscroll_pos >= -vscroll_cap) {
|
||||||
SetDParam(0, empty_weight);
|
SetDParam(0, empty_weight);
|
||||||
|
Reference in New Issue
Block a user