* Computes train speed limit caused by curves * @return imposed speed limit */
| 305 | * @return imposed speed limit |
| 306 | */ |
| 307 | uint16_t Train::GetCurveSpeedLimit() const |
| 308 | { |
| 309 | assert(this->First() == this); |
| 310 | |
| 311 | static const int absolute_max_speed = UINT16_MAX; |
| 312 | int max_speed = absolute_max_speed; |
| 313 | |
| 314 | if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) return max_speed; |
| 315 | |
| 316 | int curvecount[2] = {0, 0}; |
| 317 | |
| 318 | /* first find the curve speed limit */ |
| 319 | int numcurve = 0; |
| 320 | int sum = 0; |
| 321 | int pos = 0; |
| 322 | int lastpos = -1; |
| 323 | for (const Train *u = this; u->Next() != nullptr; u = u->Next(), pos += u->gcache.cached_veh_length) { |
| 324 | Direction this_dir = u->direction; |
| 325 | Direction next_dir = u->Next()->direction; |
| 326 | |
| 327 | DirDiff dirdiff = DirDifference(this_dir, next_dir); |
| 328 | if (dirdiff == DIRDIFF_SAME) continue; |
| 329 | |
| 330 | if (dirdiff == DIRDIFF_45LEFT) curvecount[0]++; |
| 331 | if (dirdiff == DIRDIFF_45RIGHT) curvecount[1]++; |
| 332 | if (dirdiff == DIRDIFF_45LEFT || dirdiff == DIRDIFF_45RIGHT) { |
| 333 | if (lastpos != -1) { |
| 334 | numcurve++; |
| 335 | sum += pos - lastpos; |
| 336 | if (pos - lastpos <= static_cast<int>(VEHICLE_LENGTH) && max_speed > 88) { |
| 337 | max_speed = 88; |
| 338 | } |
| 339 | } |
| 340 | lastpos = pos; |
| 341 | } |
| 342 | |
| 343 | /* if we have a 90 degree turn, fix the speed limit to 60 */ |
| 344 | if (dirdiff == DIRDIFF_90LEFT || dirdiff == DIRDIFF_90RIGHT) { |
| 345 | max_speed = 61; |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | if (numcurve > 0 && max_speed > 88) { |
| 350 | if (curvecount[0] == 1 && curvecount[1] == 1) { |
| 351 | max_speed = absolute_max_speed; |
| 352 | } else { |
| 353 | sum = CeilDiv(sum, VEHICLE_LENGTH); |
| 354 | sum /= numcurve; |
| 355 | max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12)); |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | if (max_speed != absolute_max_speed) { |
| 360 | /* Apply the current railtype's curve speed advantage */ |
| 361 | const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(this->tile)); |
| 362 | max_speed += (max_speed / 2) * rti->curve_speed; |
| 363 | |
| 364 | if (this->tcache.cached_tilt) { |
no test coverage detected