From 95fb2228523054d2f5f85437acd344b5a0987aa0 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 3 Apr 2021 22:04:37 +0100 Subject: [PATCH] Distribute articulated vehicle weight evenly between articulated parts Instead of allocating it all to the first part This improves realistic braking behaviour for long articulated consists --- src/ground_vehicle.cpp | 11 ++++++++++- src/ground_vehicle.hpp | 2 ++ src/roadveh.h | 25 ++++++++++++++++++++++--- src/train.h | 15 ++++++++++++++- src/vehicle_base.h | 11 +++++++++++ 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp index fd61e51b51..d2092a0927 100644 --- a/src/ground_vehicle.cpp +++ b/src/ground_vehicle.cpp @@ -104,9 +104,18 @@ void GroundVehicle::CargoChanged() uint32 weight = 0; uint64 mass_offset = 0; uint32 veh_offset = 0; + uint16 articulated_weight = 0; for (T *u = T::From(this); u != nullptr; u = u->Next()) { - uint32 current_weight = u->GetWeight(); + uint32 current_weight = u->GetCargoWeight(); + if (u->IsArticulatedPart()) { + current_weight += articulated_weight; + } else { + uint16 engine_weight = u->GetWeightWithoutCargo(); + uint part_count = u->GetEnginePartsCount(); + articulated_weight = engine_weight / part_count; + current_weight += articulated_weight + (engine_weight % part_count); + } if (Type == VEH_TRAIN) { Train::From(u)->tcache.cached_veh_weight = current_weight; mass_offset += current_weight * (veh_offset + (Train::From(u)->gcache.cached_veh_length / 2)); diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp index c09daf10f8..bd27eae11d 100644 --- a/src/ground_vehicle.hpp +++ b/src/ground_vehicle.hpp @@ -69,6 +69,8 @@ struct GroundVehicleAcceleration { * * virtual uint16 GetPower() const = 0; * virtual uint16 GetPoweredPartPower(const T *head) const = 0; + * virtual uint16 GetWeightWithoutCargo() const = 0; + * virtual uint16 GetCargoWeight() const = 0; * virtual uint16 GetWeight() const = 0; * virtual byte GetTractiveEffort() const = 0; * virtual byte GetAirDrag() const = 0; diff --git a/src/roadveh.h b/src/roadveh.h index 06f202f0f4..50d57d052a 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -199,12 +199,12 @@ protected: // These functions should not be called outside acceleration code. } /** - * Allows to know the weight value that this vehicle will use. + * Allows to know the weight value that this vehicle will use (excluding cargo). * @return Weight value from the engine in tonnes. */ - inline uint16 GetWeight() const + inline uint16 GetWeightWithoutCargo() const { - uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.StoredCount()) / 16; + uint16 weight = 0; /* Vehicle weight is not added for articulated parts. */ if (!this->IsArticulatedPart()) { @@ -220,6 +220,25 @@ protected: // These functions should not be called outside acceleration code. return weight; } + /** + * Allows to know the weight value that this vehicle will use (cargo only). + * @return Weight value from the engine in tonnes. + */ + inline uint16 GetCargoWeight() const + { + return (CargoSpec::Get(this->cargo_type)->weight * this->cargo.StoredCount()) / 16; + } + + /** + * Allows to know the weight value that this vehicle will use. + * @return Weight value from the engine in tonnes. + */ + inline uint16 GetWeight() const + { + return this->GetWeightWithoutCargo() + this->GetCargoWeight(); + } + + /** * Allows to know the tractive effort value that this vehicle will use. * @return Tractive effort value from the engine. diff --git a/src/train.h b/src/train.h index 85be4c7287..5eeed76d58 100644 --- a/src/train.h +++ b/src/train.h @@ -312,6 +312,10 @@ protected: // These functions should not be called outside acceleration code. return 0; } + /** + * Allows to know the weight value that this vehicle will use (excluding cargo). + * @return Weight value from the engine in tonnes. + */ inline uint16 GetWeightWithoutCargo() const { uint16 weight = 0; @@ -329,13 +333,22 @@ protected: // These functions should not be called outside acceleration code. return weight; } + /** + * Allows to know the weight value that this vehicle will use (cargo only). + * @return Weight value from the engine in tonnes. + */ + inline uint16 GetCargoWeight() const + { + return this->GetCargoWeight(this->cargo.StoredCount()); + } + /** * Allows to know the weight value that this vehicle will use. * @return Weight value from the engine in tonnes. */ inline uint16 GetWeight() const { - return this->GetWeightWithoutCargo() + this->GetCargoWeight(this->cargo.StoredCount()); + return this->GetWeightWithoutCargo() + this->GetCargoWeight(); } /** diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 656c45dc3f..375a86a879 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -1052,6 +1052,17 @@ public: return this->Next(); } + inline uint GetEnginePartsCount() const + { + uint count = 1; + const Vehicle *v = this->Next(); + while (v != nullptr && v->IsArticulatedPart()) { + count++; + v = v->Next(); + } + return count; + } + /** * Get the first part of an articulated engine. * @return First part of the engine.