20 template <
class T, VehicleType Type>
23 assert(this->First() ==
this);
24 const T *v = T::From(
this);
26 uint32_t total_power = 0;
28 uint32_t number_of_parts = 0;
29 uint16_t max_track_speed = this->vcache.cached_max_speed;
31 for (
const T *u = v; u !=
nullptr; u = u->Next()) {
32 uint32_t current_power = u->GetPower() + u->GetPoweredPartPower(u);
33 total_power += current_power;
36 if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort();
40 uint16_t track_speed = u->GetMaxTrackSpeed();
41 if (track_speed > 0) max_track_speed = std::min(max_track_speed, track_speed);
45 uint8_t air_drag_value = v->GetAirDrag();
48 if (air_drag_value == 0) {
49 uint16_t max_speed = v->GetDisplayMaxSpeed();
51 air_drag = (max_speed <= 10) ? 192 : std::max(2048 / max_speed, 1);
54 air_drag = (air_drag_value == 1) ? 0 : air_drag_value;
57 this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20;
61 if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) {
63 if (total_power == 0) this->vehstatus |=
VS_STOPPED;
65 this->gcache.cached_power = total_power;
66 this->gcache.cached_max_te = max_te;
71 this->gcache.cached_max_track_speed = max_track_speed;
78 template <
class T, VehicleType Type>
81 assert(this->First() ==
this);
84 for (T *u = T::From(
this); u !=
nullptr; u = u->Next()) {
85 uint32_t current_weight = u->GetWeight();
86 weight += current_weight;
88 u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
92 this->gcache.cached_weight = std::max(1u, weight);
94 this->gcache.cached_axle_resistance = 10 * weight;
104 template <
class T, VehicleType Type>
108 const T *v = T::From(
this);
110 int64_t speed = v->GetCurrentSpeed();
113 int32_t mass = this->gcache.cached_weight;
119 int64_t power = this->gcache.cached_power * 746ll;
132 int64_t resistance = 0;
134 bool maglev = v->GetAccelerationType() == 2;
136 const int area = v->GetAirDragArea();
139 resistance = this->gcache.cached_axle_resistance;
140 resistance += mass * v->GetRollingFriction();
144 resistance +=
static_cast<int64_t
>(area) * this->gcache.cached_air_drag * speed * speed / 1000;
146 resistance += this->GetSlopeResistance();
151 const int max_te = this->gcache.cached_max_te;
158 force = power * 18 / (speed * 5);
159 if (mode ==
AS_ACCEL && force > max_te) force = max_te;
165 force = (mode ==
AS_ACCEL && !maglev) ? std::min<int>(max_te, power) : power;
166 force = std::max(force, (mass * 8) + resistance);
171 if (force == resistance)
return 0;
178 int accel = ClampTo<int32_t>((force - resistance) / (mass * 4));
179 return force < resistance ? std::min(-1, accel) : std::max(1, accel);
181 return ClampTo<int32_t>(std::min<int64_t>(-force - resistance, -10000) / mass);
189 template <
class T, VehicleType Type>
192 const T *v = this->First();
199 for (; v !=
nullptr; v = v->Next()) {
200 if (!v->T::IsInDepot() || v->tile != this->tile)
return false;
Map related accessors for depots.
bool IsDepotTypeTile(Tile tile, TransportType type)
Check if a tile is a depot and it is a depot of the given type.
AccelStatus
What is the status of our acceleration?
@ AS_ACCEL
We want to go faster, if possible of course.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
bool IsChainInDepot() const override
Check whether the whole vehicle chain is in the depot.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
void PowerChanged()
Recalculates the cached total power of a vehicle.
int GetAcceleration() const
Calculates the acceleration of the vehicle under its current conditions.
Base for the train class.
TransportType
Available types of transport.
@ TRANSPORT_RAIL
Transport by train.
@ TRANSPORT_ROAD
Transport by road vehicle.
@ VS_STOPPED
Vehicle is stopped by the player.
@ VEH_ROAD
Road vehicle type.
@ VEH_TRAIN
Train vehicle type.
static const int GROUND_ACCELERATION
Acceleration due to gravity, 9.8 m/s^2.
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers: