diff --git a/src/lang/english.txt b/src/lang/english.txt index fa4331c86a..076b1b459d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4605,6 +4605,7 @@ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: STR_VEHICLE_INFO_TRAIN_LENGTH :{BLACK}Train length {LTBLUE}{DECIMAL} tile{P "" s} {STRING4} STR_VEHICLE_INFO_WEIGHT_RATIOS :{BLACK}Power / weight: {LTBLUE}{POWER_WEIGHT_RATIO} {BLACK} Max. T.E / weight: {LTBLUE}{FORCE_WEIGHT_RATIO} +STR_VEHICLE_INFO_FULL_WEIGHT_WITH_RATIOS :{BLACK}Full weight: {LTBLUE}{WEIGHT_SHORT} {STRING2} STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY_LONG} (last year: {CURRENCY_LONG}) STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_LIFETIME :{STRING2} (lifetime: {CURRENCY_LONG}) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index cd9a208ec6..c13f5ab6ed 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3800,6 +3800,9 @@ bool AfterLoadGame() AfterLoadTraceRestrict(); AfterLoadTemplateVehiclesUpdateImage(); + if (SlXvIsFeaturePresent(XSLFI_TEMPLATE_REPLACEMENT, 1, 5)) { + AfterLoadTemplateVehiclesUpdateProperties(); + } InvalidateVehicleTickCaches(); ClearVehicleTickCaches(); @@ -3892,4 +3895,5 @@ void ReloadNewGRFData() MarkWholeScreenDirty(); CheckTrainsLengths(); AfterLoadTemplateVehiclesUpdateImage(); + AfterLoadTemplateVehiclesUpdateProperties(); } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 6978fd2041..a174bd7abe 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -91,7 +91,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_REVERSE_AT_WAYPOINT, XSCF_NULL, 1, 1, "reverse_at_waypoint", nullptr, nullptr, nullptr }, { XSLFI_VEH_LIFETIME_PROFIT, XSCF_NULL, 1, 1, "veh_lifetime_profit", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_DAY_SCALE, XSCF_NULL, 1, 1, "linkgraph_day_scale", nullptr, nullptr, nullptr }, - { XSLFI_TEMPLATE_REPLACEMENT, XSCF_NULL, 5, 5, "template_replacement", nullptr, nullptr, "TRPL,TMPL" }, + { XSLFI_TEMPLATE_REPLACEMENT, XSCF_NULL, 6, 6, "template_replacement", nullptr, nullptr, "TRPL,TMPL" }, { XSLFI_MORE_RAIL_TYPES, XSCF_NULL, 0, 1, "more_rail_types", nullptr, nullptr, nullptr }, { XSLFI_CARGO_TYPE_ORDERS, XSCF_NULL, 3, 3, "cargo_type_orders", nullptr, nullptr, "ORDX,VEOX" }, { XSLFI_EXTENDED_GAMELOG, XSCF_NULL, 1, 1, "extended_gamelog", nullptr, nullptr, nullptr }, diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index aac89c9ac2..88cd1017a1 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -51,6 +51,7 @@ Engine *GetTempDataEngine(EngineID index); void CopyTempEngineData(); void AfterLoadTemplateVehiclesUpdateImage(); +void AfterLoadTemplateVehiclesUpdateProperties(); extern int32 _saved_scrollpos_x; extern int32 _saved_scrollpos_y; diff --git a/src/saveload/tbtr_template_veh_sl.cpp b/src/saveload/tbtr_template_veh_sl.cpp index 6cc3ab2f97..a058980fb0 100644 --- a/src/saveload/tbtr_template_veh_sl.cpp +++ b/src/saveload/tbtr_template_veh_sl.cpp @@ -37,7 +37,8 @@ const SaveLoad* GTD() { SLE_VAR(TemplateVehicle, max_speed, SLE_UINT16), SLE_VAR(TemplateVehicle, power, SLE_UINT32), - SLE_VAR(TemplateVehicle, weight, SLE_UINT32), + SLE_VAR(TemplateVehicle, empty_weight, SLE_UINT32), + SLE_CONDVAR_X(TemplateVehicle, full_weight, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TEMPLATE_REPLACEMENT, 6)), SLE_VAR(TemplateVehicle, max_te, SLE_UINT32), SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TEMPLATE_REPLACEMENT, 0, 3)), @@ -144,6 +145,36 @@ void AfterLoadTemplateVehiclesUpdateImage() RestoreRandomSeeds(saved_seeds); } +void AfterLoadTemplateVehiclesUpdateProperties() +{ + SavedRandomSeeds saved_seeds; + SaveRandomSeeds(&saved_seeds); + + for (TemplateVehicle *tv : TemplateVehicle::Iterate()) { + if (tv->Prev() == nullptr) { + Backup cur_company(_current_company, tv->owner, FILE_LINE); + StringID err; + Train* t = VirtualTrainFromTemplateVehicle(tv, err); + if (t != nullptr) { + uint32 full_cargo_weight = 0; + for (Train *u = t; u != nullptr; u = u->Next()) { + full_cargo_weight += u->GetCargoWeight(u->cargo_cap); + } + const GroundVehicleCache *gcache = t->GetGroundVehicleCache(); + tv->max_speed = t->GetDisplayMaxSpeed(); + tv->power = gcache->cached_power; + tv->empty_weight = gcache->cached_weight; + tv->full_weight = gcache->cached_weight + full_cargo_weight; + tv->max_te = gcache->cached_max_te; + delete t; + } + cur_company.Restore(); + } + } + + RestoreRandomSeeds(saved_seeds); +} + extern const ChunkHandler _template_vehicle_chunk_handlers[] = { {'TMPL', Save_TMPLS, Load_TMPLS, Ptrs_TMPLS, nullptr, CH_ARRAY | CH_LAST}, }; diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index f4868410d9..57c2113c1d 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -314,12 +314,31 @@ public: y += FONT_HEIGHT_NORMAL; } /* Draw vehicle performance info */ + const bool original_acceleration = (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL || + GetRailTypeInfo(this->virtual_train->railtype)->acceleration_type == 2); const GroundVehicleCache *gcache = this->virtual_train->GetGroundVehicleCache(); SetDParam(2, this->virtual_train->GetDisplayMaxSpeed()); SetDParam(1, gcache->cached_power); SetDParam(0, gcache->cached_weight); SetDParam(3, gcache->cached_max_te / 1000); - DrawString(8, r.right, y, STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + DrawString(8, r.right, y, original_acceleration ? STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED : STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + uint32 full_cargo_weight = 0; + for (Train *train = this->virtual_train; train != nullptr; train = train->Next()) { + full_cargo_weight += train->GetCargoWeight(train->cargo_cap); + } + if (full_cargo_weight > 0 || _settings_client.gui.show_train_weight_ratios_in_details) { + y += FONT_HEIGHT_NORMAL; + uint full_weight = gcache->cached_weight + full_cargo_weight; + SetDParam(0, full_weight); + if (_settings_client.gui.show_train_weight_ratios_in_details) { + SetDParam(1, STR_VEHICLE_INFO_WEIGHT_RATIOS); + SetDParam(2, (100 * this->virtual_train->gcache.cached_power) / max(1, full_weight)); + SetDParam(3, (this->virtual_train->gcache.cached_max_te / 10) / max(1, full_weight)); + } else { + SetDParam(1, STR_EMPTY); + } + DrawString(8, r.right, y, STR_VEHICLE_INFO_FULL_WEIGHT_WITH_RATIOS); + } /* Draw cargo summary */ CargoArray cargo_caps; for (const Train *tmp = this->virtual_train; tmp != nullptr; tmp = tmp->Next()) { diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index ac3d3c32c0..7cc168cd59 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -729,16 +729,33 @@ public: const TemplateVehicle *tmp = this->templates[this->selected_template_index]; + short top = ScaleGUITrad(4) - this->vscroll[2]->GetPosition(); + short left = ScaleGUITrad(8); + /* Draw vehicle performance info */ + const bool original_acceleration = (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL || + GetRailTypeInfo(tmp->railtype)->acceleration_type == 2); SetDParam(2, tmp->max_speed); SetDParam(1, tmp->power); - SetDParam(0, tmp->weight); - SetDParam(3, tmp->max_te); - DrawString(8, r.right, ScaleGUITrad(4) - this->vscroll[2]->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + SetDParam(0, tmp->empty_weight); + SetDParam(3, tmp->max_te / 1000); + DrawString(left, r.right, top, original_acceleration ? STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED : STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + + if (tmp->full_weight > tmp->empty_weight || _settings_client.gui.show_train_weight_ratios_in_details) { + top += FONT_HEIGHT_NORMAL; + SetDParam(0, tmp->full_weight); + if (_settings_client.gui.show_train_weight_ratios_in_details) { + SetDParam(1, STR_VEHICLE_INFO_WEIGHT_RATIOS); + SetDParam(2, (100 * tmp->power) / max(1, tmp->full_weight)); + SetDParam(3, (tmp->max_te / 10) / max(1, tmp->full_weight)); + } else { + SetDParam(1, STR_EMPTY); + } + DrawString(8, r.right, top, STR_VEHICLE_INFO_FULL_WEIGHT_WITH_RATIOS); + } /* Draw cargo summary */ - short top = ScaleGUITrad(30) - this->vscroll[2]->GetPosition(); - short left = ScaleGUITrad(8); + top += ScaleGUITrad(26); short count_columns = 0; short max_columns = 2; diff --git a/src/tbtr_template_vehicle.h b/src/tbtr_template_vehicle.h index c245cd2533..b1b3353d2c 100644 --- a/src/tbtr_template_vehicle.h +++ b/src/tbtr_template_vehicle.h @@ -101,7 +101,8 @@ public: uint16 max_speed; uint32 power; - uint32 weight; + uint32 empty_weight; + uint32 full_weight; uint32 max_te; VehicleSpriteSeq sprite_seq; ///< NOSAVE: Vehicle appearance. diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index ec46805550..618fbf46b7 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -152,11 +152,20 @@ void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev tmp->cargo_subtype = virt->cargo_subtype; tmp->cargo_cap = virt->cargo_cap; - const GroundVehicleCache *gcache = virt->GetGroundVehicleCache(); - tmp->max_speed = virt->GetDisplayMaxSpeed(); - tmp->power = gcache->cached_power; - tmp->weight = gcache->cached_weight; - tmp->max_te = gcache->cached_max_te / 1000; + if (!virt->Previous()) { + uint cargo_weight = 0; + uint full_cargo_weight = 0; + for (const Train *u = virt; u != nullptr; u = u->Next()) { + cargo_weight += u->GetCargoWeight(u->cargo.StoredCount()); + full_cargo_weight += u->GetCargoWeight(u->cargo_cap); + } + const GroundVehicleCache *gcache = virt->GetGroundVehicleCache(); + tmp->max_speed = virt->GetDisplayMaxSpeed(); + tmp->power = gcache->cached_power; + tmp->empty_weight = max(gcache->cached_weight - cargo_weight, 1); + tmp->full_weight = max(gcache->cached_weight + full_cargo_weight - cargo_weight, 1); + tmp->max_te = gcache->cached_max_te; + } virt->GetImage(DIR_W, EIT_IN_DEPOT, &tmp->sprite_seq); tmp->image_dimensions.SetFromTrain(virt); diff --git a/src/train.h b/src/train.h index 4e081a06a8..716e86323a 100644 --- a/src/train.h +++ b/src/train.h @@ -221,6 +221,15 @@ struct Train FINAL : public GroundVehicle { return const_cast(const_cast(this)->GetStationLoadingVehicle()); } + inline uint16 GetCargoWeight(uint cargo_amount) const + { + if (cargo_amount > 0) { + return (CargoSpec::Get(this->cargo_type)->weight * cargo_amount * FreightWagonMult(this->cargo_type)) / 16; + } else { + return 0; + } + } + protected: // These functions should not be called outside acceleration code. /** * Gets the speed a broken down train (low speed breakdown) is limited to. @@ -272,13 +281,9 @@ protected: // These functions should not be called outside acceleration code. return 0; } - /** - * Allows to know the weight value that this vehicle will use. - * @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() * FreightWagonMult(this->cargo_type)) / 16; + uint16 weight = 0; /* Vehicle weight is not added for articulated parts. */ if (!this->IsArticulatedPart()) { @@ -293,6 +298,15 @@ protected: // These functions should not be called outside acceleration code. return weight; } + /** + * 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()); + } + /** * Allows to know the tractive effort value that this vehicle will use. * @return Tractive effort value from the engine.