From beda7ebb39c78b9822018b05565b4d9b56a9506a Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 4 Jan 2018 19:05:18 +0000 Subject: [PATCH 1/2] Set minimum speed for train critical breakdown reduction. --- src/train_cmd.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5e90db53b2..4cf2952cbf 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -151,12 +151,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); + const uint16 base_speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed); + uint16 speed = base_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); } } + + /* clamp speed to be no less than lower of 5mph and 1/8 of base speed */ + speed = max(speed, min(5, (base_speed + 7) >> 3)); + if (HasBit(u->flags, VRF_HAS_HIT_RV) && front->IsFrontEngine()) { speed = min(speed, 30); } From 0a80aec6345f9e0cfb16f76e746b8045b2e19b17 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 4 Jan 2018 19:18:24 +0000 Subject: [PATCH 2/2] Implement critical breakdown speed reduction for road vehicles --- src/lang/english.txt | 2 +- src/roadveh.h | 4 ++++ src/roadveh_cmd.cpp | 18 +++++++++++++++++- src/roadveh_gui.cpp | 5 +++++ src/saveload/extended_ver_sl.cpp | 2 +- src/saveload/vehicle_sl.cpp | 1 + src/vehicle.cpp | 12 +++++++++++- src/vehicle_gui.cpp | 4 ++-- 8 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 2857e87b20..117474994d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3675,7 +3675,7 @@ STR_VEHICLE_DETAILS_AIRCRAFT_RENAME :{BLACK}Name air STR_VEHICLE_INFO_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING2}{BLACK} Running Cost: {LTBLUE}{CURRENCY_LONG}/yr STR_RUNNING :{LTBLUE}Running -STR_NEED_REPAIR :{ORANGE}Train needs repair - max speed reduced to {VELOCITY} +STR_NEED_REPAIR :{ORANGE}Vehicle needs repair - max speed reduced to {VELOCITY} STR_CURRENT_STATUS :{BLACK}Current status: {STRING3} # The next two need to stay in this order diff --git a/src/roadveh.h b/src/roadveh.h index 8a48c19837..1be48878ea 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -97,6 +97,8 @@ struct RoadVehicle FINAL : public GroundVehicle { RoadType roadtype; RoadTypes compatible_roadtypes; + byte critical_breakdown_count; ///< Counter for the number of critical breakdowns since last service + /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ RoadVehicle() : GroundVehicleBase() {} /** We want to 'destruct' the right class. */ @@ -124,6 +126,8 @@ struct RoadVehicle FINAL : public GroundVehicle { bool IsBus() const; int GetCurrentMaxSpeed() const; + int GetEffectiveMaxSpeed() const; + int GetDisplayEffectiveMaxSpeed() const { return this->GetEffectiveMaxSpeed() / 2; } int UpdateSpeed(); protected: // These functions should not be called outside acceleration code. diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index ab10c43922..f2f705a15f 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -430,13 +430,29 @@ void RoadVehicle::UpdateDeltaXY(Direction direction) this->z_extent = 6; } +/** + * Calculates the maximum speed of the vehicle, taking into account speed reductions following critical breakdowns + * @return Maximum speed of the vehicle. + */ +int RoadVehicle::GetEffectiveMaxSpeed() const +{ + int max_speed = this->vcache.cached_max_speed; + + for (uint i = 0; i < this->critical_breakdown_count; i++) { + max_speed = min(max_speed - (max_speed / 3) + 1, max_speed); + } + + /* clamp speed to be no less than lower of 5mph and 1/8 of base speed */ + return max(max_speed, min(10, (this->vcache.cached_max_speed + 7) >> 3)); +} + /** * Calculates the maximum speed of the vehicle under its current conditions. * @return Maximum speed of the vehicle. */ inline int RoadVehicle::GetCurrentMaxSpeed() const { - int max_speed = this->vcache.cached_max_speed; + int max_speed = this->GetEffectiveMaxSpeed(); /* Limit speed to 50% while reversing, 75% in curves. */ for (const RoadVehicle *u = this; u != NULL; u = u->Next()) { diff --git a/src/roadveh_gui.cpp b/src/roadveh_gui.cpp index 63e0549582..9e23654b20 100644 --- a/src/roadveh_gui.cpp +++ b/src/roadveh_gui.cpp @@ -117,6 +117,11 @@ void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y) /* Draw Transfer credits text */ SetDParam(0, feeder_share); DrawString(left, right, y + 3 * FONT_HEIGHT_NORMAL + 3 + y_offset, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE); + + if (RoadVehicle::From(v)->critical_breakdown_count > 0) { + SetDParam(0, RoadVehicle::From(v)->GetDisplayEffectiveMaxSpeed()); + DrawString(left, right, y + 4 * FONT_HEIGHT_NORMAL + 4 + y_offset, STR_NEED_REPAIR); + } } /** diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index cd9d4ee47c..216bee3e08 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 5, 5, "improved_breakdowns", NULL, NULL, NULL }, + { XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 6, 6, "improved_breakdowns", NULL, NULL, NULL }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 4ffe29772b..7c68e64bc2 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -750,6 +750,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt) SLE_CONDNULL(4, 69, 130), SLE_CONDNULL(2, 6, 130), SLE_CONDNULL(16, 2, 143), // old reserved space + SLE_CONDVAR_X(RoadVehicle, critical_breakdown_count, SLE_UINT8, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_IMPROVED_BREAKDOWNS, 6)), SLE_END() }; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 6dcd1af960..4ddcfab2af 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -153,6 +153,8 @@ void VehicleServiceInDepot(Vehicle *v) Train::From(v)->ConsistChanged(CCF_REFIT); CLRBITS(Train::From(v)->flags, (1 << VRF_BREAKDOWN_BRAKING) | VRF_IS_BROKEN ); } + } else if (v->type == VEH_ROAD) { + RoadVehicle::From(v)->critical_breakdown_count = 0; } v->vehstatus &= ~VS_AIRCRAFT_BROKEN; SetWindowDirty(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated @@ -185,7 +187,8 @@ 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)) + && !(this->type == VEH_ROAD && RoadVehicle::From(this)->critical_breakdown_count > 0)) { return false; } @@ -1458,6 +1461,13 @@ bool Vehicle::HandleBreakdown() EffectVehicle *u = CreateEffectVehicleRel(this, 4, 4, 5, EV_BREAKDOWN_SMOKE); if (u != NULL) u->animation_state = this->breakdown_delay * 2; } + if (_settings_game.vehicle.improved_breakdowns) { + if (this->type == VEH_ROAD) { + if (RoadVehicle::From(this)->critical_breakdown_count != 255) { + RoadVehicle::From(this)->critical_breakdown_count++; + } + } + } /* FALL THROUGH */ case BREAKDOWN_EM_STOP: this->cur_speed = 0; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index bb972a7b1b..af10eefbcf 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1942,13 +1942,13 @@ struct VehicleDetailsWindow : Window { uint desired_height; if (v->HasArticulatedPart()) { /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */ - desired_height = WD_FRAMERECT_TOP + ScaleGUITrad(15) + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM; + desired_height = WD_FRAMERECT_TOP + ScaleGUITrad(15) + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM; /* Add space for the cargo amount for each part. */ for (const Vehicle *u = v; u != NULL; u = u->Next()) { if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1; } } else { - desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM; + desired_height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + 4 + WD_FRAMERECT_BOTTOM; } return desired_height; }