22 template <
class T, VehicleType Type>
25 assert(this->First() ==
this);
26 const T *v = T::From(
this);
28 uint32 total_power = 0;
30 uint32 number_of_parts = 0;
31 uint16 max_track_speed = v->GetDisplayMaxSpeed();
33 for (
const T *u = v; u != NULL; u = u->Next()) {
34 uint32 current_power = u->GetPower() + u->GetPoweredPartPower(u);
35 total_power += current_power;
38 if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort();
42 uint16 track_speed = u->GetMaxTrackSpeed();
43 if (track_speed > 0) max_track_speed =
min(max_track_speed, track_speed);
47 byte air_drag_value = v->GetAirDrag();
50 if (air_drag_value == 0) {
51 uint16 max_speed = v->GetDisplayMaxSpeed();
53 air_drag = (max_speed <= 10) ? 192 :
max(2048 / max_speed, 1);
56 air_drag = (air_drag_value == 1) ? 0 : air_drag_value;
59 this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20;
63 if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) {
65 if (total_power == 0) this->vehstatus |=
VS_STOPPED;
67 this->gcache.cached_power = total_power;
68 this->gcache.cached_max_te = max_te;
73 this->gcache.cached_max_track_speed = max_track_speed;
80 template <
class T, VehicleType Type>
83 assert(this->First() ==
this);
86 for (T *u = T::From(
this); u != NULL; u = u->Next()) {
87 uint32 current_weight = u->GetWeight();
88 weight += current_weight;
90 u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
94 this->gcache.cached_weight = max<uint32>(1, weight);
96 this->gcache.cached_axle_resistance = 10 * weight;
106 template <
class T, VehicleType Type>
110 const T *v = T::From(
this);
112 int64 speed = v->GetCurrentSpeed();
115 int32 mass = this->gcache.cached_weight;
121 int64 power = this->gcache.cached_power * 746ll;
134 int64 resistance = 0;
136 bool maglev = v->GetAccelerationType() == 2;
138 const int area = v->GetAirDragArea();
141 resistance = this->gcache.cached_axle_resistance;
142 resistance += mass * v->GetRollingFriction();
146 resistance += (area * this->gcache.cached_air_drag * speed * speed) / 1000;
148 resistance += this->GetSlopeResistance();
153 const int max_te = this->gcache.cached_max_te;
160 force = power * 18 / (speed * 5);
161 if (mode ==
AS_ACCEL && force > max_te) force = max_te;
167 force = (mode ==
AS_ACCEL && !maglev) ?
min(max_te, power) : power;
168 force =
max(force, (mass * 8) + resistance);
173 if (force == resistance)
return 0;
180 int accel =
ClampToI32((force - resistance) / (mass * 4));
181 return force < resistance ?
min(-1, accel) :
max(1, accel);
191 template <
class T, VehicleType Type>
194 const T *v = this->First();
201 for (; v != NULL; v = v->Next()) {
202 if (!v->T::IsInDepot() || v->tile != this->tile)
return false;