From 9742300a1eef68cc6b594e9ee03d3c741347e677 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 31 Jan 2016 15:22:46 +0000 Subject: [PATCH 1/4] Fix some more whitespace/formatting issues. --- src/ground_vehicle.cpp | 18 ++++++++---------- src/ground_vehicle.hpp | 7 ++++--- src/ship_cmd.cpp | 6 +++--- src/train_cmd.cpp | 2 +- src/vehicle.cpp | 2 +- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp index 502d186ea4..071913ac8f 100644 --- a/src/ground_vehicle.cpp +++ b/src/ground_vehicle.cpp @@ -171,8 +171,7 @@ int GroundVehicle::GetAcceleration() AccelStatus mode = v->GetAccelerationStatus(); /* handle breakdown power reduction */ - //TODO - if( Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { + if (Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { /* We'd like to cache this, but changing cached_power has too many unwanted side-effects */ uint32 power_temp; this->CalculatePower(power_temp, max_te, true); @@ -198,7 +197,7 @@ int GroundVehicle::GetAcceleration() } /* If power is 0 because of a breakdown, we make the force 0 if accelerating */ - if ( Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER) && power == 0) { + if (Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER) && power == 0) { force = 0; } @@ -214,7 +213,7 @@ int GroundVehicle::GetAcceleration() uint64 breakdown_factor = (uint64)abs(resistance) * (uint64)(this->cur_speed << 16); breakdown_factor /= (max(force, (int64)100) * this->gcache.cached_max_track_speed); breakdown_factor = min((64 << 16) + (breakdown_factor * 128), 255 << 16); - if ( Type == VEH_TRAIN && Train::From(this)->tcache.cached_num_engines > 1) { + if (Type == VEH_TRAIN && Train::From(this)->tcache.cached_num_engines > 1) { /* For multiengine trains, breakdown chance is multiplied by 3 / (num_engines + 2) */ breakdown_factor *= 3; breakdown_factor /= (Train::From(this)->tcache.cached_num_engines + 2); @@ -238,7 +237,7 @@ int GroundVehicle::GetAcceleration() accel = force < resistance ? min(-1, accel) : max(1, accel); if (this->type == VEH_TRAIN ) { if(_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL && - HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { + HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { /* We need to apply the power reducation for non-realistic acceleration here */ uint32 power; CalculatePower(power, max_te, true); @@ -246,11 +245,10 @@ int GroundVehicle::GetAcceleration() accel -= this->acceleration >> 1; } - - if ( this->IsFrontEngine() && !(this->current_order_time & 0x1FF) && - !(this->current_order.IsType(OT_LOADING)) && - !(Train::From(this)->flags & (VRF_IS_BROKEN | (1 << VRF_TRAIN_STUCK))) && - this->cur_speed < 3 && accel < 5) { + if (this->IsFrontEngine() && !(this->current_order_time & 0x1FF) && + !(this->current_order.IsType(OT_LOADING)) && + !(Train::From(this)->flags & (VRF_IS_BROKEN | (1 << VRF_TRAIN_STUCK))) && + this->cur_speed < 3 && accel < 5) { SetBit(Train::From(this)->flags, VRF_TOO_HEAVY); } } diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp index 00dcfca721..86f328fe1e 100644 --- a/src/ground_vehicle.hpp +++ b/src/ground_vehicle.hpp @@ -376,16 +376,17 @@ protected: if (this->breakdown_ctr == 1) { if (this->breakdown_type == BREAKDOWN_LOW_POWER) { - if((this->tick_counter & 0x7) == 0) { - if(this->cur_speed > (this->breakdown_severity * max_speed) >> 8) { + if ((this->tick_counter & 0x7) == 0) { + if (this->cur_speed > (this->breakdown_severity * max_speed) >> 8) { tempmax = this->cur_speed - (this->cur_speed / 10) - 1; } else { tempmax = (this->breakdown_severity * max_speed) >> 8; } } } - if(this->breakdown_type == BREAKDOWN_LOW_SPEED) + if (this->breakdown_type == BREAKDOWN_LOW_SPEED) { tempmax = min(max_speed, this->breakdown_severity); + } } if (this->cur_speed > max_speed) { diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index e7e2961bdd..9bd985c536 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -382,15 +382,15 @@ static bool ShipAccelerate(Vehicle *v) spd = min(v->cur_speed + 1, v->vcache.cached_max_speed); spd = min(spd, v->current_order.GetMaxSpeed() * 2); - if(v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_POWER && v->cur_speed > (v->breakdown_severity * ShipVehInfo(v->engine_type)->max_speed) >> 8) { - if((v->tick_counter & 0x7) == 0 && v->cur_speed > 0) { + if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_POWER && v->cur_speed > (v->breakdown_severity * ShipVehInfo(v->engine_type)->max_speed) >> 8) { + if ((v->tick_counter & 0x7) == 0 && v->cur_speed > 0) { spd = v->cur_speed - 1; } else { spd = v->cur_speed; } } - if(v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_SPEED) { + if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_SPEED) { spd = min(spd, v->breakdown_severity); } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 4c83477fd5..6cc941f562 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4079,7 +4079,7 @@ void Train::OnNewDay() SetWindowClassesDirty(WC_TRAINS_LIST); } } - if(IsEngine() || IsMultiheaded()) { + if (IsEngine() || IsMultiheaded()) { CheckVehicleBreakdown(this); } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 398c61bdae..d357d2c9f9 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1430,7 +1430,7 @@ bool Vehicle::HandleBreakdown() if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) { if (--this->breakdown_delay == 0) { this->breakdown_ctr = 0; - if(this->type == VEH_TRAIN) { + if (this->type == VEH_TRAIN) { CheckBreakdownFlags(Train::From(this->First())); this->First()->MarkDirty(); SetWindowDirty(WC_VEHICLE_VIEW, this->First()->index); From 5eed9865d65ece366e867bed3fff5fa5ed284850 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 31 Jan 2016 22:55:25 +0000 Subject: [PATCH 2/4] Improved breakdowns: Various changes and fixes. * Revert breakdown_chance to (mostly) its original behaviour. * Create a new breakdown_chance_factor to hold breakdown_chance from improved breakdowns logic. * Revert airport crash probabilities back to original behaviour, with modified behaviour only during emergency landings. * Low power breakdowns now only reduce the power of the engine which has broken down. * Low power breakdowns no longer reduce speed directly. * Add callback function to run whenever improved breakdowns setting is changed. Reset breakdown_chance_factor where required. * More whitespace/formatting... --- src/aircraft_cmd.cpp | 14 +++++++------- src/ground_vehicle.cpp | 17 ++++++++--------- src/ground_vehicle.hpp | 11 ++++++----- src/roadveh_cmd.cpp | 2 +- src/saveload/afterload.cpp | 7 ++++--- src/saveload/vehicle_sl.cpp | 1 + src/settings.cpp | 28 +++++++++++++++++++++++++++- src/ship_cmd.cpp | 2 +- src/table/settings.ini | 3 ++- src/train.h | 2 +- src/train_cmd.cpp | 7 ++----- src/vehicle.cpp | 27 +++++++++++++++++++-------- src/vehicle_base.h | 1 + src/vehicle_gui.cpp | 10 +++++++++- 14 files changed, 89 insertions(+), 43 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 76227e1430..87831dcd04 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -308,7 +308,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine * v->reliability_spd_dec = e->reliability_spd_dec; /* higher speed means higher breakdown chance */ /* to somewhat compensate for the fact that fast aircraft spend less time in the air */ - v->breakdown_chance = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255); + v->breakdown_chance_factor = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255); v->max_age = e->GetLifeLengthInDays(); _new_vehicle_id = v->index; @@ -1333,18 +1333,18 @@ static void MaybeCrashAirplane(Aircraft *v) Station *st = Station::Get(v->targetairport); /* FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports */ - uint32 prob = (_settings_game.vehicle.improved_breakdowns && _settings_game.difficulty.vehicle_breakdowns) ? - 0x10000 / 10000 : 0x4000 << _settings_game.vehicle.plane_crashes; + uint32 prob = (0x4000 << _settings_game.vehicle.plane_crashes); if ((st->airport.GetFTA()->flags & AirportFTAClass::SHORT_STRIP) && (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) { prob /= 20; - } else if (!_settings_game.vehicle.improved_breakdowns) { + } else { prob /= 1500; - } else if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) { - /* Airplanes that are attempting an emergency landing have a 2% chance to crash */ - prob = 0x10000 / 50; + } + if (_settings_game.vehicle.improved_breakdowns && v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) { + /* Airplanes that are attempting an emergency landing have a 2% chance to crash */ + prob = max(prob, 0x10000 / 50); } if (GB(Random(), 0, 22) > prob) return; diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp index 071913ac8f..91d1900558 100644 --- a/src/ground_vehicle.cpp +++ b/src/ground_vehicle.cpp @@ -78,14 +78,15 @@ void GroundVehicle::CalculatePower(uint32& total_power, uint32& max_te, for (const T *u = v; u != NULL; u = u->Next()) { uint32 current_power = u->GetPower() + u->GetPoweredPartPower(u); + + if (breakdowns && u->breakdown_ctr == 1 && u->breakdown_type == BREAKDOWN_LOW_POWER) { + current_power = current_power * u->breakdown_severity / 256; + } + total_power += current_power; /* Only powered parts add tractive effort. */ if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort(); - - if (breakdowns && u->breakdown_ctr == 1 && u->breakdown_type == BREAKDOWN_LOW_POWER) { - total_power = total_power * u->breakdown_severity / 256; - } } max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N. @@ -138,7 +139,6 @@ int GroundVehicle::GetAcceleration() * and km/h to m/s conversion below result in a maxium of * about 1.1E11, way more than 4.3E9 of int32. */ int64 power = this->gcache.cached_power * 746ll; - uint32 max_te = this->gcache.cached_max_te; // [N] /* This is constructed from: * - axle resistance: U16 power * 10 for 128 vehicles. @@ -171,6 +171,7 @@ int GroundVehicle::GetAcceleration() AccelStatus mode = v->GetAccelerationStatus(); /* handle breakdown power reduction */ + uint32 max_te = this->gcache.cached_max_te; // [N] if (Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { /* We'd like to cache this, but changing cached_power has too many unwanted side-effects */ uint32 power_temp; @@ -219,9 +220,7 @@ int GroundVehicle::GetAcceleration() breakdown_factor /= (Train::From(this)->tcache.cached_num_engines + 2); } /* breakdown_chance is at least 5 (5 / 128 = ~4% of the normal chance) */ - this->breakdown_chance = max(breakdown_factor >> 16, (uint64)5); - } else { - this->breakdown_chance = 128; + this->breakdown_chance_factor = max(breakdown_factor >> 16, (uint64)5); } if (mode == AS_ACCEL) { @@ -235,7 +234,7 @@ int GroundVehicle::GetAcceleration() * same (maximum) speed. */ int accel = ClampToI32((force - resistance) / (mass * 4)); accel = force < resistance ? min(-1, accel) : max(1, accel); - if (this->type == VEH_TRAIN ) { + if (this->type == VEH_TRAIN) { if(_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) { /* We need to apply the power reducation for non-realistic acceleration here */ diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp index 86f328fe1e..be1c36781e 100644 --- a/src/ground_vehicle.hpp +++ b/src/ground_vehicle.hpp @@ -370,22 +370,23 @@ protected: uint spd = this->subspeed + accel; this->subspeed = (byte)spd; + int tempmax = max_speed; + /* When we are going faster than the maximum speed, reduce the speed * somewhat gradually. But never lower than the maximum speed. */ - int tempmax = ((this->breakdown_ctr == 1) ? this->cur_speed : max_speed); - if (this->breakdown_ctr == 1) { if (this->breakdown_type == BREAKDOWN_LOW_POWER) { - if ((this->tick_counter & 0x7) == 0) { + if ((this->tick_counter & 0x7) == 0 && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) { if (this->cur_speed > (this->breakdown_severity * max_speed) >> 8) { tempmax = this->cur_speed - (this->cur_speed / 10) - 1; } else { tempmax = (this->breakdown_severity * max_speed) >> 8; } } - } - if (this->breakdown_type == BREAKDOWN_LOW_SPEED) { + } else if (this->breakdown_type == BREAKDOWN_LOW_SPEED) { tempmax = min(max_speed, this->breakdown_severity); + } else { + tempmax = this->cur_speed; } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 3747ad8854..68e020f124 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -298,7 +298,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; - v->breakdown_chance = 128; + v->breakdown_chance_factor = 128; v->max_age = e->GetLifeLengthInDays(); _new_vehicle_id = v->index; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index ac8fa33455..4208c3cdb6 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2835,14 +2835,15 @@ bool AfterLoadGame() v->reliability = min(v->First()->reliability, e->reliability); } } + /* FALL THROUGH */ case VEH_ROAD: - v->breakdown_chance = 128; + v->breakdown_chance_factor = 128; break; case VEH_SHIP: - v->breakdown_chance = 64; + v->breakdown_chance_factor = 64; break; case VEH_AIRCRAFT: - v->breakdown_chance = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255); + v->breakdown_chance_factor = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255); v->breakdown_severity = 40; break; default: break; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index def7ada99d..6612292c4d 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -671,6 +671,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_VAR(Vehicle, breakdown_delay, SLE_UINT8), SLE_VAR(Vehicle, breakdowns_since_last_service, SLE_UINT8), SLE_VAR(Vehicle, breakdown_chance, SLE_UINT8), + SLE_CONDVAR(Vehicle, breakdown_chance_factor, SLE_UINT8, SL_IB, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, breakdown_type, SLE_UINT8, SL_IB, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, breakdown_severity, SLE_UINT8, SL_IB, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, build_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), diff --git a/src/settings.cpp b/src/settings.cpp index 41a7491067..fce350e8b3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1020,7 +1020,7 @@ static bool RoadVehAccelerationModelChanged(int32 p1) RoadVehicle *rv; FOR_ALL_ROADVEHICLES(rv) { if (rv->IsFrontEngine()) { - rv->breakdown_chance = 128; + rv->breakdown_chance_factor = 128; } } } @@ -1319,6 +1319,32 @@ static bool MaxVehiclesChanged(int32 p1) return true; } +static bool ImprovedBreakdownsSettingChanged(int32 p1) +{ + if (!_settings_game.vehicle.improved_breakdowns) return true; + + Vehicle *v; + FOR_ALL_VEHICLES(v) { + switch(v->type) { + case VEH_TRAIN: + if (v->IsFrontEngine()) { + v->breakdown_chance_factor = 128; + Train::From(v)->UpdateAcceleration(); + } + break; + + case VEH_ROAD: + if (v->IsFrontEngine()) { + v->breakdown_chance_factor = 128; + } + break; + + default: + break; + } + } + return true; +} #ifdef ENABLE_NETWORK diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 9bd985c536..6f8ba28cc0 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -714,7 +714,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, u v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; - v->breakdown_chance = 64; // ships have a 50% lower breakdown chance than normal + v->breakdown_chance_factor = 64; // ships have a 50% lower breakdown chance than normal v->max_age = e->GetLifeLengthInDays(); _new_vehicle_id = v->index; diff --git a/src/table/settings.ini b/src/table/settings.ini index ec407c15db..e9c8d31b37 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -42,6 +42,7 @@ static bool InvalidateCompanyInfrastructureWindow(int32 p1); static bool InvalidateCompanyWindow(int32 p1); static bool ZoomMinMaxChanged(int32 p1); static bool MaxVehiclesChanged(int32 p1); +static bool ImprovedBreakdownsSettingChanged(int32 p1); #ifdef ENABLE_NETWORK static bool UpdateClientName(int32 p1); @@ -1143,7 +1144,7 @@ from = SL_IB guiflags = SGF_NO_NETWORK def = false str = STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS - +proc = ImprovedBreakdownsSettingChanged ; station.join_stations [SDT_NULL] diff --git a/src/train.h b/src/train.h index e6acea7981..e41ca63c34 100644 --- a/src/train.h +++ b/src/train.h @@ -292,7 +292,7 @@ protected: // These functions should not be called outside acceleration code. */ inline AccelStatus GetAccelerationStatus() const { - return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK ) || HasBit(this->flags, VRF_BREAKDOWN_BRAKING) ? AS_BRAKE : AS_ACCEL; + return ((this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) || HasBit(this->flags, VRF_BREAKDOWN_BRAKING)) ? AS_BRAKE : AS_ACCEL; } /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 6cc941f562..a8261f22d3 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -129,7 +129,7 @@ void CheckTrainsLengths() void CheckBreakdownFlags(Train *v) { assert(v->IsFrontEngine()); - /* clear the flags we're gonna check first, we'll set them again later (if applicable ) */ + /* clear the flags we're gonna check first, we'll set them again later (if applicable) */ CLRBITS(v->flags, (1 << VRF_BREAKDOWN_BRAKING) | VRF_IS_BROKEN); for (const Train *w = v; w != NULL; w = w->Next()) { @@ -492,10 +492,8 @@ void Train::UpdateAcceleration() if (_settings_game.vehicle.improved_breakdowns) { if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) { - this->breakdown_chance = max(128 * 3 / (this->tcache.cached_num_engines + 2), 5); + this->breakdown_chance_factor = max(128 * 3 / (this->tcache.cached_num_engines + 2), 5); } - } else { - this->breakdown_chance = 128; } } @@ -4055,7 +4053,6 @@ void Train::OnNewDay() if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); if (this->IsFrontEngine()) { - CheckIfTrainNeedsService(this); CheckOrders(this); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index d357d2c9f9..854ccd6458 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -123,6 +123,8 @@ void VehicleServiceInDepot(Vehicle *v) v->date_of_last_service = _date; v->breakdowns_since_last_service = 0; v->reliability = v->GetEngine()->reliability; + /* Prevent vehicles from breaking down directly after exiting the depot. */ + v->breakdown_chance = 0; v = v->Next(); } while (v != NULL && v->HasEngineType()); } @@ -144,7 +146,7 @@ bool Vehicle::NeedsServicing() const if ((this->ServiceIntervalIsPercent() ? (this->reliability >= this->GetEngine()->reliability * (100 - this->service_interval) / 100) : (this->date_of_last_service + this->service_interval >= _date)) - && !(this->type == VEH_TRAIN && HasBit(Train::From(this)->flags ,VRF_NEED_REPAIR))) { + && !(this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_NEED_REPAIR))) { return false; } @@ -1277,15 +1279,21 @@ void CheckVehicleBreakdown(Vehicle *v) return; } - uint32 r1 = Random(); - uint32 r2 = Random(); + uint32 r = Random(); + + /* increase chance of failure */ + int chance = v->breakdown_chance + 1; + if (Chance16I(1, 25, r)) chance += 25; + chance = min(255, chance); + v->breakdown_chance = chance; - byte chance = 128; if (_settings_game.vehicle.improved_breakdowns) { - /* Dual engines have their breakdown chances reduced to 70% of the normal value */ - chance = (v->type == VEH_TRAIN && Train::From(v)->IsMultiheaded()) ? v->First()->breakdown_chance * 7 / 10 : v->First()->breakdown_chance; - } else if(v->type == VEH_SHIP) { - chance = 64; + if (v->type == VEH_TRAIN && Train::From(v)->IsMultiheaded()) { + /* Dual engines have their breakdown chances reduced to 70% of the normal value */ + chance = chance * 7 / 10; + } + chance *= v->First()->breakdown_chance_factor; + chance >>= 7; } /** * Chance is (1 - reliability) * breakdown_setting * breakdown_chance / 10. @@ -1295,9 +1303,12 @@ void CheckVehicleBreakdown(Vehicle *v) * However, because breakdowns are no longer by definition a complete stop, * their impact will be significantly less. */ + uint32 r1 = Random(); if ((uint32) (0xffff - v->reliability) * _settings_game.difficulty.vehicle_breakdowns * chance > GB(r1, 0, 24) * 10) { + uint32 r2 = Random(); v->breakdown_ctr = GB(r1, 24, 6) + 0xF; v->breakdown_delay = GB(r2, 0, 7) + 0x80; + v->breakdown_chance = 0; DetermineBreakdownType(v, r2); } } diff --git a/src/vehicle_base.h b/src/vehicle_base.h index ddf162b944..19d9b4a58f 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -195,6 +195,7 @@ public: byte breakdown_severity; ///< severity of the breakdown. Note that lower means more severe byte breakdown_type; ///< Type of breakdown + byte breakdown_chance_factor; ///< Improved breakdowns: current multiplier for breakdown_chance * 128, used for head vehicle only SpriteID colourmap; ///< NOSAVE: cached colour mapping /* Related to age and service time */ diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 9df4badc16..f1f057f78b 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2632,7 +2632,15 @@ public: if (w->breakdown_type == BREAKDOWN_LOW_SPEED) { SetDParam(1, min( w->First()->GetDisplayMaxSpeed(), w->breakdown_severity >> ((v->type == VEH_TRAIN) ? 0 : 1))); } else if (w->breakdown_type == BREAKDOWN_LOW_POWER) { - SetDParam(1, w->breakdown_severity * 100 / 256); + int percent; + if (v->type == VEH_TRAIN) { + uint32 power, te; + Train::From(v)->CalculatePower(power, te, true); + percent = (100 * power) / Train::From(v)->gcache.cached_power; + } else { + percent = w->breakdown_severity * 100 / 256; + } + SetDParam(1, percent); } } } else if (v->vehstatus & VS_STOPPED) { From e03d97eab60b2ee6fbcf3b985dc4ba5292e753cd Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 31 Jan 2016 23:24:17 +0000 Subject: [PATCH 3/4] Improved breakdowns: Fix string parameter count issues. Fix whitespace. --- src/lang/english.txt | 5 +++-- src/train_gui.cpp | 8 ++++---- src/vehicle_gui.cpp | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index cf08b94031..0b726f36e6 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3622,7 +3622,8 @@ STR_VEHICLE_STATUS_LEAVING :{LTBLUE}Leaving STR_VEHICLE_STATUS_CRASHED :{RED}Crashed! STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Broken down STR_VEHICLE_STATUS_STOPPED :{RED}Stopped -STR_VEHICLE_STATUS_BROKEN_DOWN_VEL :{RED}Broken down - {STRING1}, {LTBLUE} {VELOCITY} +STR_VEHICLE_STATUS_BROKEN_DOWN_VEL :{RED}Broken down - {STRING2}, {LTBLUE} {VELOCITY} +STR_VEHICLE_STATUS_BROKEN_DOWN_VEL_SHORT :{RED}Broken down - {STRING2} STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL :{RED}Stopping, {VELOCITY} STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}No power STR_VEHICLE_STATUS_TRAIN_STUCK :{ORANGE}Waiting for free path @@ -3661,7 +3662,7 @@ STR_VEHICLE_INFO_AGE_RUNNING_COST_YR :{BLACK}Age: {LT STR_RUNNING :{LTBLUE}Running STR_NEED_REPAIR :{ORANGE}Train needs repair - max speed reduced to {VELOCITY} -STR_CURRENT_STATUS :{BLACK}Current status: {STRING2} +STR_CURRENT_STATUS :{BLACK}Current status: {STRING3} # The next two need to stay in this order STR_VEHICLE_INFO_AGE :{COMMA} year{P "" s} ({COMMA}) diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 139dae8293..f4e78f971c 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -254,15 +254,15 @@ static void TrainDetailsInfoTab(const Train *v, int left, int right, int y, byte case 2: if (v->breakdown_ctr == 1) { if (_settings_game.vehicle.improved_breakdowns) { - SetDParam(0, STR_VEHICLE_STATUS_BROKEN_DOWN_VEL); + SetDParam(0, STR_VEHICLE_STATUS_BROKEN_DOWN_VEL_SHORT); SetDParam(1, STR_BREAKDOWN_TYPE_CRITICAL + v->breakdown_type); if (v->breakdown_type == BREAKDOWN_LOW_SPEED) { - SetDParam(2, min( v->First()->GetCurrentMaxSpeed(), v->breakdown_severity)); + SetDParam(2, min(v->First()->GetCurrentMaxSpeed(), v->breakdown_severity)); } else if (v->breakdown_type == BREAKDOWN_LOW_POWER) { - SetDParam(2, v->breakdown_severity * 100 / 256 ); + SetDParam(2, v->breakdown_severity * 100 / 256); } } else { - SetDParam( 0, STR_VEHICLE_STATUS_BROKEN_DOWN ); + SetDParam(0, STR_VEHICLE_STATUS_BROKEN_DOWN); } } else { if (HasBit(v->flags, VRF_NEED_REPAIR)) { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index f1f057f78b..4d27751710 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2613,7 +2613,7 @@ public: } else if (v->breakdown_ctr == 1 || (v->type == VEH_TRAIN && Train::From(v)->flags & VRF_IS_BROKEN)) { if (_settings_game.vehicle.improved_breakdowns) { str = STR_VEHICLE_STATUS_BROKEN_DOWN_VEL; - SetDParam(2, v->GetDisplaySpeed()); + SetDParam(3, v->GetDisplaySpeed()); } else { str = STR_VEHICLE_STATUS_BROKEN_DOWN; } @@ -2630,7 +2630,7 @@ public: SetDParam(0, STR_BREAKDOWN_TYPE_CRITICAL + w->breakdown_type); if (w->breakdown_type == BREAKDOWN_LOW_SPEED) { - SetDParam(1, min( w->First()->GetDisplayMaxSpeed(), w->breakdown_severity >> ((v->type == VEH_TRAIN) ? 0 : 1))); + SetDParam(1, min(w->First()->GetDisplayMaxSpeed(), w->breakdown_severity >> ((v->type == VEH_TRAIN) ? 0 : 1))); } else if (w->breakdown_type == BREAKDOWN_LOW_POWER) { int percent; if (v->type == VEH_TRAIN) { From 5b2dc8bcd8b69df8a0a99d4b424b0f93d048ee63 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 1 Feb 2016 00:21:51 +0000 Subject: [PATCH 4/4] Fix vehicle needs repair speed limits being incorrect in vehicle details. --- src/train_cmd.cpp | 18 ++++++++++++------ src/train_gui.cpp | 4 +++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index a8261f22d3..22885c8233 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -148,6 +148,17 @@ void CheckBreakdownFlags(Train *v) } } +uint16 GetTrainVehicleMaxSpeed(const Train *u, const RailVehicleInfo *rvi_u, const Train *front) +{ + uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed); + if (HasBit(u->flags, VRF_NEED_REPAIR) && front->IsFrontEngine()) { + for (uint i = 0; i < u->critical_breakdown_count; i++) { + speed = min(speed - (speed / (front->tcache.cached_num_engines + 2)) + 1, speed); + } + } + return speed; +} + /** * Recalculates the cached stuff of a train. Should be called each time a vehicle is added * to/removed from the chain, and when the game is loaded. @@ -238,12 +249,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes) /* max speed is the minimum of the speed limits of all vehicles in the consist */ if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings_game.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) { - uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed); - if (HasBit(u->flags, VRF_NEED_REPAIR) && this->IsFrontEngine()) { - for (uint i = 0; i < u->critical_breakdown_count; i++) { - speed = min(speed - (speed / (this->tcache.cached_num_engines + 2)) + 1, speed); - } - } + uint16 speed = GetTrainVehicleMaxSpeed(u, rvi_u, this); if (speed != 0) max_speed = min(speed, max_speed); } } diff --git a/src/train_gui.cpp b/src/train_gui.cpp index f4e78f971c..55b26defa3 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -21,6 +21,8 @@ #include "safeguards.h" +uint16 GetTrainVehicleMaxSpeed(const Train *u, const RailVehicleInfo *rvi_u, const Train *front); + /** * Callback for building wagons. * @param result The result of the command. @@ -267,7 +269,7 @@ static void TrainDetailsInfoTab(const Train *v, int left, int right, int y, byte } else { if (HasBit(v->flags, VRF_NEED_REPAIR)) { SetDParam(0, STR_NEED_REPAIR); - SetDParam(1, v->vcache.cached_max_speed); + SetDParam(1, GetTrainVehicleMaxSpeed(v, &(v->GetEngine()->u.rail), v->First())); } else { SetDParam(0, STR_RUNNING); }