From 81115d271db1aeaccae5bb994d33bd24e8c8ecbd Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 17 Jul 2022 21:56:45 +0200 Subject: [PATCH 1/2] Fix: Trains driving on railtypes only checked powerness of any engine, but ignored compatibility of all vehicles. --- src/rail_type.h | 1 + src/train_cmd.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/rail_type.h b/src/rail_type.h index 874a8ebbb6..ca40f84a53 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -49,6 +49,7 @@ enum RailTypes : uint64 { RAILTYPES_ELECTRIC = 1 << RAILTYPE_ELECTRIC, ///< Electrified rails RAILTYPES_MONO = 1 << RAILTYPE_MONO, ///< Monorail! RAILTYPES_MAGLEV = 1 << RAILTYPE_MAGLEV, ///< Ever fast maglev + RAILTYPES_ALL = UINT64_MAX, ///< All railtypes INVALID_RAILTYPES = UINT64_MAX, ///< Invalid railtypes }; DECLARE_ENUM_AS_BIT_SET(RailTypes) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 983b5ccd1c..15a1d27b6a 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -114,7 +114,8 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes) const RailVehicleInfo *rvi_v = RailVehInfo(this->engine_type); EngineID first_engine = this->IsFrontEngine() ? this->engine_type : INVALID_ENGINE; this->gcache.cached_total_length = 0; - this->compatible_railtypes = RAILTYPES_NONE; + RailTypes all_compatible = RAILTYPES_ALL; + RailTypes any_powered = RAILTYPES_NONE; bool train_can_tilt = true; int min_curve_speed_mod = INT_MAX; @@ -169,17 +170,20 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes) } if (!u->IsArticulatedPart()) { - /* Do not count powered wagons for the compatible railtypes, as wagons always - have railtype normal */ - if (rvi_u->power > 0) { - this->compatible_railtypes |= GetRailTypeInfo(u->railtype)->powered_railtypes; - } - /* Some electric engines can be allowed to run on normal rail. It happens to all * existing electric engines when elrails are disabled and then re-enabled */ if (HasBit(u->flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) { u->railtype = RAILTYPE_RAIL; - u->compatible_railtypes |= RAILTYPES_RAIL; + } + + /* collect railtypes compatible with every vehicle */ + all_compatible &= GetRailTypeInfo(u->railtype)->compatible_railtypes; + + /* Do not count powered wagons for the compatible railtypes, as wagons always + have railtype normal */ + if (rvi_u->power > 0) { + /* collect railtypes powering any engine */ + any_powered |= GetRailTypeInfo(u->railtype)->powered_railtypes; } /* max speed is the minimum of the speed limits of all vehicles in the consist */ @@ -230,6 +234,8 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes) u->InvalidateNewGRFCache(); } + this->compatible_railtypes = all_compatible & any_powered; + /* store consist weight/max speed in cache */ this->vcache.cached_max_speed = max_speed; this->tcache.cached_tilt = train_can_tilt; From 25c7e5de10fcb8ea7716f3558db056b286495372 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 17 Jul 2022 23:06:53 +0200 Subject: [PATCH 2/2] Change: If a train gets stranded on unpowered tracks, provide some minimum power to resolve the deadlock. This is meant in particular for trains with multiple engines, which are powered on different track types. If the train traversed from one track type to another, the first engine may lose power before the second engine gains it. The train needs some momentum/minimum-speed to cross this power gap. --- src/ground_vehicle.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp index f6e44c2e29..a29a220aaf 100644 --- a/src/ground_vehicle.cpp +++ b/src/ground_vehicle.cpp @@ -56,12 +56,14 @@ void GroundVehicle::PowerChanged() this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20; + if (total_power == 0) { + /* Ensure that vehicles are never completely stuck */ + total_power = 1; + } + max_te *= GROUND_ACCELERATION; // Tractive effort in (tonnes * 1000 * 9.8 =) N. max_te /= 256; // Tractive effort is a [0-255] coefficient. if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) { - /* Stop the vehicle if it has no power. */ - if (total_power == 0) this->vehstatus |= VS_STOPPED; - this->gcache.cached_power = total_power; this->gcache.cached_max_te = max_te; SetWindowDirty(WC_VEHICLE_DETAILS, this->index);