From e97213e7e25e7d72ffba1892954e8b6520c5412c Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Thu, 8 Jan 2026 15:34:50 -0500 Subject: [PATCH] Change: Vehicles loading at stations don't lose reliability (#14841) --- src/settings_type.h | 7 +++ src/table/settings/difficulty_settings.ini | 6 +-- src/vehicle.cpp | 51 ++++++++++++++-------- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/settings_type.h b/src/settings_type.h index 68b6da1d90..997b010544 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -117,6 +117,13 @@ enum PlaceHouses : uint8_t { PH_ALLOWED_CONSTRUCTED, }; +/** Possible values for "vehicle_breakdowns" setting. */ +enum VehicleBreakdowns : uint8_t { + VB_NONE = 0, + VB_REDUCED, + VB_NORMAL, +}; + /** Settings related to the difficulty of the game */ struct DifficultySettings { uint8_t competitor_start_time; ///< Unused value, used to load old savegames. diff --git a/src/table/settings/difficulty_settings.ini b/src/table/settings/difficulty_settings.ini index a4148b2d73..eae5bb6a15 100644 --- a/src/table/settings/difficulty_settings.ini +++ b/src/table/settings/difficulty_settings.ini @@ -176,9 +176,9 @@ var = difficulty.vehicle_breakdowns type = SLE_UINT8 from = SLV_97 flags = SettingFlag::GuiDropdown -def = 1 -min = 0 -max = 2 +def = VB_REDUCED +min = VB_NONE +max = VB_NORMAL interval = 1 str = STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS strhelp = STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 2b70a2a6a1..a73c838a39 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -187,7 +187,7 @@ void VehicleServiceInDepot(Vehicle *v) v->reliability = v->GetEngine()->reliability; /* Prevent vehicles from breaking down directly after exiting the depot. */ v->breakdown_chance /= 4; - if (_settings_game.difficulty.vehicle_breakdowns == 1) v->breakdown_chance = 0; // on reduced breakdown + if (_settings_game.difficulty.vehicle_breakdowns == VB_REDUCED) v->breakdown_chance = 0; // on reduced breakdown v = v->Next(); } while (v != nullptr && v->HasEngineType()); } @@ -222,7 +222,7 @@ bool Vehicle::NeedsServicing() const /* If we're servicing anyway, because we have not disabled servicing when * there are no breakdowns or we are playing with breakdowns, bail out. */ if (!_settings_game.order.no_servicing_if_no_breakdowns || - _settings_game.difficulty.vehicle_breakdowns != 0) { + _settings_game.difficulty.vehicle_breakdowns != VB_NONE) { return true; } @@ -1285,38 +1285,53 @@ static const uint8_t _breakdown_chance[64] = { 150, 170, 190, 210, 230, 250, 250, 250, }; +/** + * Periodic check for a vehicle to maybe break down. + * @param v The vehicle to consider breaking. + */ void CheckVehicleBreakdown(Vehicle *v) { + /* Vehicles in the menu don't break down. */ + if (_game_mode == GM_MENU) return; + + /* If both breakdowns and automatic servicing are disabled, we don't decrease reliability or break down. */ + if (_settings_game.difficulty.vehicle_breakdowns == VB_NONE && _settings_game.order.no_servicing_if_no_breakdowns) return; + + /* With Reduced breakdowns, vehicles (un)loading at stations don't lose reliability. */ + if (_settings_game.difficulty.vehicle_breakdowns == VB_REDUCED && v->current_order.IsType(OT_LOADING)) return; + + /* Decrease reliability. */ int rel, rel_old; + v->reliability = rel = std::max((rel_old = v->reliability) - v->reliability_spd_dec, 0); + if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index); - /* decrease reliability */ - if (!_settings_game.order.no_servicing_if_no_breakdowns || - _settings_game.difficulty.vehicle_breakdowns != 0) { - v->reliability = rel = std::max((rel_old = v->reliability) - v->reliability_spd_dec, 0); - if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index); - } + /* Some vehicles lose reliability but won't break down. */ + /* Breakdowns are disabled. */ + if (_settings_game.difficulty.vehicle_breakdowns == VB_NONE) return; + /* The vehicle is already broken down. */ + if (v->breakdown_ctr != 0) return; + /* The vehicle is stopped or going very slow. */ + if (v->cur_speed < 5) return; + /* The vehicle has been manually stopped. */ + if (v->vehstatus.Test(VehState::Stopped)) return; - if (v->breakdown_ctr != 0 || v->vehstatus.Test(VehState::Stopped) || - _settings_game.difficulty.vehicle_breakdowns < 1 || - v->cur_speed < 5 || _game_mode == GM_MENU) { - return; - } + /* Time to consider breaking down. */ uint32_t r = Random(); - /* increase chance of failure */ + /* Increase chance of failure. */ int chance = v->breakdown_chance + 1; if (Chance16I(1, 25, r)) chance += 25; v->breakdown_chance = ClampTo(chance); - /* calculate reliability value to use in comparison */ + /* Calculate reliability value to use in comparison. */ rel = v->reliability; if (v->type == VEH_SHIP) rel += 0x6666; - /* reduced breakdowns? */ - if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666; + /* Reduce the chance if the player has chosen the Reduced setting. */ + if (_settings_game.difficulty.vehicle_breakdowns == VB_REDUCED) rel += 0x6666; - /* check if to break down */ + /* Check the random chance and inform the vehicle of the result. */ if (_breakdown_chance[ClampTo(rel) >> 10] <= v->breakdown_chance) { v->breakdown_ctr = GB(r, 16, 6) + 0x3F; v->breakdown_delay = GB(r, 24, 7) + 0x80;