| 103 | */ |
| 104 | template <class T, VehicleType Type> |
| 105 | int GroundVehicle<T, Type>::GetAcceleration() const |
| 106 | { |
| 107 | /* Templated class used for function calls for performance reasons. */ |
| 108 | const T *v = T::From(this); |
| 109 | /* Speed is used squared later on, so U16 * U16, and then multiplied by other values. */ |
| 110 | int64_t speed = v->GetCurrentSpeed(); // [km/h-ish] |
| 111 | |
| 112 | /* Weight is stored in tonnes. */ |
| 113 | int64_t mass = this->gcache.cached_weight; |
| 114 | |
| 115 | /* Power is stored in HP, we need it in watts. |
| 116 | * Each vehicle can have U16 power, 128 vehicles, HP -> watt |
| 117 | * and km/h to m/s conversion below result in a maximum of |
| 118 | * about 1.1E11, way more than 4.3E9 of int32. */ |
| 119 | int64_t power = this->gcache.cached_power * 746ll; |
| 120 | |
| 121 | /* This is constructed from: |
| 122 | * - axle resistance: U16 power * 10 for 128 vehicles. |
| 123 | * * 8.3E7 |
| 124 | * - rolling friction: U16 power * 144 for 128 vehicles. |
| 125 | * * 1.2E9 |
| 126 | * - slope resistance: U16 weight * 100 * 10 (steepness) for 128 vehicles. |
| 127 | * * 8.4E9 |
| 128 | * - air drag: 28 * (U8 drag + 3 * U8 drag * 128 vehicles / 20) * U16 speed * U16 speed |
| 129 | * * 6.2E14 before dividing by 1000 |
| 130 | * Sum is 6.3E11, more than 4.3E9 of int32_t, so int64_t is needed. |
| 131 | */ |
| 132 | int64_t resistance = 0; |
| 133 | |
| 134 | bool maglev = v->GetAccelerationType() == VehicleAccelerationModel::Maglev; |
| 135 | |
| 136 | const int area = v->GetAirDragArea(); |
| 137 | if (!maglev) { |
| 138 | /* Static resistance plus rolling friction. */ |
| 139 | resistance = this->gcache.cached_axle_resistance; |
| 140 | resistance += mass * v->GetRollingFriction(); |
| 141 | } |
| 142 | /* Air drag; the air drag coefficient is in an arbitrary NewGRF-unit, |
| 143 | * so we need some magic conversion factor. */ |
| 144 | resistance += static_cast<int64_t>(area) * this->gcache.cached_air_drag * speed * speed / 1000; |
| 145 | |
| 146 | resistance += this->GetSlopeResistance(); |
| 147 | |
| 148 | /* This value allows to know if the vehicle is accelerating or braking. */ |
| 149 | AccelStatus mode = v->GetAccelerationStatus(); |
| 150 | |
| 151 | const int max_te = this->gcache.cached_max_te; // [N] |
| 152 | /* Constructed from power, with need to multiply by 18 and assuming |
| 153 | * low speed, it needs to be a 64 bit integer too. */ |
| 154 | int64_t force; |
| 155 | if (speed > 0) { |
| 156 | if (!maglev) { |
| 157 | /* Conversion factor from km/h to m/s is 5/18 to get [N] in the end. */ |
| 158 | force = power * 18 / (speed * 5); |
| 159 | if (mode == AS_ACCEL && force > max_te) force = max_te; |
| 160 | } else { |
| 161 | force = power / 25; |
| 162 | } |
no test coverage detected