20template <
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;
78template <
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;
104template <
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);
189template <
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.
Base class for all vehicles that move through ground.
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: