diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 2e8c827831..7b035fe07e 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -193,41 +193,6 @@ CargoArray GetCapacityOfArticulatedParts(EngineID engine) return capacity; } -/** - * Get the default cargoes and refits of an articulated vehicle. - * The refits are linked to a cargo rather than an articulated part to prevent a long list of parts. - * @param engine Model to investigate. - * @param[out] cargoes Total amount of units that can be transported, summed by cargo. - * @param[out] refits Whether a (possibly partial) refit for each cargo is possible. - * @param cargo_type Selected refitted cargo type - * @param cargo_capacity Capacity of selected refitted cargo type - */ -void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits, CargoID cargo_type, uint cargo_capacity) -{ - cargoes->Clear(); - *refits = 0; - - const Engine *e = Engine::Get(engine); - - if (cargo_type < NUM_CARGO && cargo_capacity > 0) { - (*cargoes)[cargo_type] += cargo_capacity; - if (IsEngineRefittable(engine)) SetBit(*refits, cargo_type); - } - - if (!e->IsGroundVehicle() || !HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return; - - for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) { - EngineID artic_engine = GetNextArticulatedPart(i, engine); - if (artic_engine == INVALID_ENGINE) break; - - cargo_capacity = GetVehicleDefaultCapacity(artic_engine, &cargo_type); - if (cargo_type < NUM_CARGO && cargo_capacity > 0) { - (*cargoes)[cargo_type] += cargo_capacity; - if (IsEngineRefittable(artic_engine)) SetBit(*refits, cargo_type); - } - } -} - /** * Checks whether any of the articulated parts is refittable * @param engine the first part diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index 8f6efd70d7..955c0ae102 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -479,8 +479,7 @@ public: const Engine *e = Engine::Get(this->sel_engine[side]); TestedEngineDetails ted; ted.cost = 0; - ted.cargo = e->GetDefaultCargoType(); - ted.capacity = e->GetDisplayDefaultCapacity(&ted.mail_capacity); + ted.FillDefaultCapacities(e); NWidgetBase *nwi = this->GetWidget(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS); int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index a827422308..50e40dd9ed 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -740,18 +740,23 @@ static GUIEngineList::FilterFunction * const _filter_funcs[] = { &CargoAndEngineFilter, }; -static int DrawCargoCapacityInfo(int left, int right, int y, EngineID engine, TestedEngineDetails &te) +static uint GetCargoWeight(const CargoArray &cap) { - CargoArray cap; - CargoTypes refits; - GetArticulatedVehicleCargoesAndRefits(engine, &cap, &refits, te.cargo, te.capacity); - + uint weight = 0; for (CargoID c = 0; c < NUM_CARGO; c++) { - if (cap[c] == 0) continue; + if (cap[c] != 0) weight += CargoSpec::Get(c)->weight * cap[c] / 16; + } + return weight; +} + +static int DrawCargoCapacityInfo(int left, int right, int y, TestedEngineDetails &te, bool refittable) +{ + for (CargoID c = 0; c < NUM_CARGO; c++) { + if (te.all_capacities[c] == 0) continue; SetDParam(0, c); - SetDParam(1, cap[c]); - SetDParam(2, HasBit(refits, c) ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY); + SetDParam(1, te.all_capacities[c]); + SetDParam(2, refittable ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY); DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY); y += FONT_HEIGHT_NORMAL; } @@ -778,8 +783,7 @@ static int DrawRailWagonPurchaseInfo(int left, int right, int y, EngineID engine /* Wagon weight - (including cargo) */ uint weight = e->GetDisplayWeight(); SetDParam(0, weight); - uint cargo_weight = ((e->CanCarryCargo() && te.cargo < NUM_CARGO) ? CargoSpec::Get(te.cargo)->weight * te.capacity / 16 : 0); - SetDParam(1, cargo_weight + weight); + SetDParam(1, GetCargoWeight(te.all_capacities) + weight); DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT); y += FONT_HEIGHT_NORMAL; @@ -872,8 +876,7 @@ static int DrawRoadVehPurchaseInfo(int left, int right, int y, EngineID engine_n /* Road vehicle weight - (including cargo) */ int16 weight = e->GetDisplayWeight(); SetDParam(0, weight); - uint cargo_weight = ((e->CanCarryCargo() && te.cargo < NUM_CARGO) ? CargoSpec::Get(te.cargo)->weight * te.capacity / 16 : 0); - SetDParam(1, cargo_weight + weight); + SetDParam(1, GetCargoWeight(te.all_capacities) + weight); DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT); y += FONT_HEIGHT_NORMAL; @@ -1055,6 +1058,20 @@ static uint ShowAdditionalText(int left, int right, int y, EngineID engine) return result; } +void TestedEngineDetails::FillDefaultCapacities(const Engine *e) +{ + this->cargo = e->GetDefaultCargoType(); + if (e->type == VEH_TRAIN || e->type == VEH_ROAD) { + this->all_capacities = GetCapacityOfArticulatedParts(e->index); + this->capacity = this->all_capacities[this->cargo]; + this->mail_capacity = 0; + } else { + this->capacity = e->GetDisplayDefaultCapacity(&this->mail_capacity); + this->all_capacities[this->cargo] = this->capacity; + this->all_capacities[CT_MAIL] = this->mail_capacity; + } +} + /** * Draw the purchase info details of a vehicle at a given location. * @param left,right,y location where to draw the info @@ -1096,7 +1113,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, if (articulated_cargo) { /* Cargo type + capacity, or N/A */ - int new_y = DrawCargoCapacityInfo(left, right, y, engine_number, te); + int new_y = DrawCargoCapacityInfo(left, right, y, te, refittable); if (new_y == y) { SetDParam(0, CT_INVALID); @@ -1463,6 +1480,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { this->te.capacity = _returned_refit_capacity; this->te.mail_capacity = _returned_mail_refit_capacity; this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo; + this->te.all_capacities = _returned_vehicle_capacities; delete t; RestoreRandomSeeds(saved_seeds); return; @@ -1478,14 +1496,14 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { this->te.capacity = _returned_refit_capacity; this->te.mail_capacity = _returned_mail_refit_capacity; this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo; + this->te.all_capacities = _returned_vehicle_capacities; return; } } /* Purchase test was not possible or failed, fill in the defaults instead. */ this->te.cost = 0; - this->te.capacity = e->GetDisplayDefaultCapacity(&this->te.mail_capacity); - this->te.cargo = e->GetDefaultCargoType(); + this->te.FillDefaultCapacities(e); } void OnInit() override @@ -2245,6 +2263,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { state.te.capacity = _returned_refit_capacity; state.te.mail_capacity = _returned_mail_refit_capacity; state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo; + state.te.all_capacities = _returned_vehicle_capacities; delete t; RestoreRandomSeeds(saved_seeds); return; @@ -2260,14 +2279,14 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { state.te.capacity = _returned_refit_capacity; state.te.mail_capacity = _returned_mail_refit_capacity; state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo; + state.te.all_capacities = _returned_vehicle_capacities; return; } } /* Purchase test was not possible or failed, fill in the defaults instead. */ state.te.cost = 0; - state.te.capacity = e->GetDisplayDefaultCapacity(&state.te.mail_capacity); - state.te.cargo = e->GetDefaultCargoType(); + state.te.FillDefaultCapacities(e); } void OnInit() override diff --git a/src/engine_func.h b/src/engine_func.h index b778956171..3cf11140f7 100644 --- a/src/engine_func.h +++ b/src/engine_func.h @@ -25,7 +25,6 @@ extern const uint8 _engine_offsets[4]; bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company); bool IsEngineRefittable(EngineID engine); -void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits, CargoID cargo_type, uint cargo_capacity); void SetYearEngineAgingStops(); void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 588e99bf87..efa674b1d7 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -95,6 +95,7 @@ static const uint GEN_HASHY_BUCKET_BITS = 6; VehicleID _new_vehicle_id; uint _returned_refit_capacity; ///< Stores the capacity after a refit operation. uint16 _returned_mail_refit_capacity; ///< Stores the mail capacity after a refit operation (Aircraft only). +CargoArray _returned_vehicle_capacities; ///< Stores the cargo capacities after a vehicle build operation /** The pool with all our precious vehicles. */ diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 13c413afd8..07a738be7e 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -167,7 +167,16 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint value.AddCost(CmdRefitVehicle(tile, flags, v->index, cargo | (1 << 16), nullptr)); } else { /* Fill in non-refitted capacities */ - _returned_refit_capacity = e->GetDisplayDefaultCapacity(&_returned_mail_refit_capacity); + if (e->type == VEH_TRAIN || e->type == VEH_ROAD) { + _returned_vehicle_capacities = GetCapacityOfArticulatedParts(eid); + _returned_refit_capacity = _returned_vehicle_capacities[default_cargo]; + _returned_mail_refit_capacity = 0; + } else { + _returned_refit_capacity = e->GetDisplayDefaultCapacity(&_returned_mail_refit_capacity); + _returned_vehicle_capacities.Clear(); + _returned_vehicle_capacities[default_cargo] = _returned_refit_capacity; + _returned_vehicle_capacities[CT_MAIL] = _returned_mail_refit_capacity; + } } if (flags & DC_EXEC) { @@ -370,6 +379,7 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, uint total_capacity = 0; uint total_mail_capacity = 0; num_vehicles = num_vehicles == 0 ? UINT8_MAX : num_vehicles; + _returned_vehicle_capacities.Clear(); VehicleSet vehicles_to_refit; if (!only_this) { @@ -394,7 +404,11 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, /* If the vehicle is not refittable, or does not allow automatic refitting, * count its capacity nevertheless if the cargo matches */ bool refittable = HasBit(e->info.refit_mask, new_cid) && (!auto_refit || HasBit(e->info.misc_flags, EF_AUTO_REFIT)); - if (!refittable && v->cargo_type != new_cid) continue; + if (!refittable && v->cargo_type != new_cid) { + uint amount = e->DetermineCapacity(v, nullptr); + if (amount > 0) _returned_vehicle_capacities[v->cargo_type] += amount; + continue; + } /* Determine best fitting subtype if requested */ if (actual_subtype == 0xFF) { @@ -415,6 +429,9 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, /* mail_capacity will always be zero if the vehicle is not an aircraft. */ total_mail_capacity += mail_capacity; + _returned_vehicle_capacities[new_cid] += amount; + _returned_vehicle_capacities[CT_MAIL] += mail_capacity; + if (!refittable) continue; /* Restore the original cargo type */ diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 7be1addcf0..22e80a28b3 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -19,6 +19,7 @@ #include "newgrf_config.h" #include "track_type.h" #include "livery.h" +#include "cargo_type.h" #define is_custom_sprite(x) (x >= 0xFD) #define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD) @@ -245,6 +246,7 @@ CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits); extern VehicleID _new_vehicle_id; extern uint _returned_refit_capacity; extern uint16 _returned_mail_refit_capacity; +extern CargoArray _returned_vehicle_capacities; bool CanVehicleUseStation(EngineID engine_type, const struct Station *st); bool CanVehicleUseStation(const Vehicle *v, const struct Station *st); diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h index 9ec0246c3a..477e29a06d 100644 --- a/src/vehicle_gui.h +++ b/src/vehicle_gui.h @@ -42,6 +42,9 @@ struct TestedEngineDetails { CargoID cargo; ///< Cargo type uint capacity; ///< Cargo capacity uint16 mail_capacity; ///< Mail capacity if available + CargoArray all_capacities; ///< Capacities for all cargoes + + void FillDefaultCapacities(const Engine *e); }; int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te);