Fix displayed capacities/weights of articulated vehicles in build window
Simplify handling of multi-part capacities and refits See: https://github.com/OpenTTD/OpenTTD/issues/9954 See: https://github.com/OpenTTD/OpenTTD/issues/10032
This commit is contained in:
@@ -193,41 +193,6 @@ CargoArray GetCapacityOfArticulatedParts(EngineID engine)
|
|||||||
return capacity;
|
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
|
* Checks whether any of the articulated parts is refittable
|
||||||
* @param engine the first part
|
* @param engine the first part
|
||||||
|
@@ -479,8 +479,7 @@ public:
|
|||||||
const Engine *e = Engine::Get(this->sel_engine[side]);
|
const Engine *e = Engine::Get(this->sel_engine[side]);
|
||||||
TestedEngineDetails ted;
|
TestedEngineDetails ted;
|
||||||
ted.cost = 0;
|
ted.cost = 0;
|
||||||
ted.cargo = e->GetDefaultCargoType();
|
ted.FillDefaultCapacities(e);
|
||||||
ted.capacity = e->GetDisplayDefaultCapacity(&ted.mail_capacity);
|
|
||||||
|
|
||||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS);
|
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(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,
|
int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT,
|
||||||
|
@@ -740,18 +740,23 @@ static GUIEngineList::FilterFunction * const _filter_funcs[] = {
|
|||||||
&CargoAndEngineFilter,
|
&CargoAndEngineFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int DrawCargoCapacityInfo(int left, int right, int y, EngineID engine, TestedEngineDetails &te)
|
static uint GetCargoWeight(const CargoArray &cap)
|
||||||
{
|
{
|
||||||
CargoArray cap;
|
uint weight = 0;
|
||||||
CargoTypes refits;
|
|
||||||
GetArticulatedVehicleCargoesAndRefits(engine, &cap, &refits, te.cargo, te.capacity);
|
|
||||||
|
|
||||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
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(0, c);
|
||||||
SetDParam(1, cap[c]);
|
SetDParam(1, te.all_capacities[c]);
|
||||||
SetDParam(2, HasBit(refits, c) ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
|
SetDParam(2, refittable ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
|
||||||
DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
|
DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
|
||||||
y += FONT_HEIGHT_NORMAL;
|
y += FONT_HEIGHT_NORMAL;
|
||||||
}
|
}
|
||||||
@@ -778,8 +783,7 @@ static int DrawRailWagonPurchaseInfo(int left, int right, int y, EngineID engine
|
|||||||
/* Wagon weight - (including cargo) */
|
/* Wagon weight - (including cargo) */
|
||||||
uint weight = e->GetDisplayWeight();
|
uint weight = e->GetDisplayWeight();
|
||||||
SetDParam(0, weight);
|
SetDParam(0, weight);
|
||||||
uint cargo_weight = ((e->CanCarryCargo() && te.cargo < NUM_CARGO) ? CargoSpec::Get(te.cargo)->weight * te.capacity / 16 : 0);
|
SetDParam(1, GetCargoWeight(te.all_capacities) + weight);
|
||||||
SetDParam(1, cargo_weight + weight);
|
|
||||||
DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
|
DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
|
||||||
y += FONT_HEIGHT_NORMAL;
|
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) */
|
/* Road vehicle weight - (including cargo) */
|
||||||
int16 weight = e->GetDisplayWeight();
|
int16 weight = e->GetDisplayWeight();
|
||||||
SetDParam(0, weight);
|
SetDParam(0, weight);
|
||||||
uint cargo_weight = ((e->CanCarryCargo() && te.cargo < NUM_CARGO) ? CargoSpec::Get(te.cargo)->weight * te.capacity / 16 : 0);
|
SetDParam(1, GetCargoWeight(te.all_capacities) + weight);
|
||||||
SetDParam(1, cargo_weight + weight);
|
|
||||||
DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
|
DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
|
||||||
y += FONT_HEIGHT_NORMAL;
|
y += FONT_HEIGHT_NORMAL;
|
||||||
|
|
||||||
@@ -1055,6 +1058,20 @@ static uint ShowAdditionalText(int left, int right, int y, EngineID engine)
|
|||||||
return result;
|
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.
|
* Draw the purchase info details of a vehicle at a given location.
|
||||||
* @param left,right,y location where to draw the info
|
* @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) {
|
if (articulated_cargo) {
|
||||||
/* Cargo type + capacity, or N/A */
|
/* 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) {
|
if (new_y == y) {
|
||||||
SetDParam(0, CT_INVALID);
|
SetDParam(0, CT_INVALID);
|
||||||
@@ -1463,6 +1480,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase {
|
|||||||
this->te.capacity = _returned_refit_capacity;
|
this->te.capacity = _returned_refit_capacity;
|
||||||
this->te.mail_capacity = _returned_mail_refit_capacity;
|
this->te.mail_capacity = _returned_mail_refit_capacity;
|
||||||
this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
||||||
|
this->te.all_capacities = _returned_vehicle_capacities;
|
||||||
delete t;
|
delete t;
|
||||||
RestoreRandomSeeds(saved_seeds);
|
RestoreRandomSeeds(saved_seeds);
|
||||||
return;
|
return;
|
||||||
@@ -1478,14 +1496,14 @@ struct BuildVehicleWindow : BuildVehicleWindowBase {
|
|||||||
this->te.capacity = _returned_refit_capacity;
|
this->te.capacity = _returned_refit_capacity;
|
||||||
this->te.mail_capacity = _returned_mail_refit_capacity;
|
this->te.mail_capacity = _returned_mail_refit_capacity;
|
||||||
this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
this->te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
||||||
|
this->te.all_capacities = _returned_vehicle_capacities;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Purchase test was not possible or failed, fill in the defaults instead. */
|
/* Purchase test was not possible or failed, fill in the defaults instead. */
|
||||||
this->te.cost = 0;
|
this->te.cost = 0;
|
||||||
this->te.capacity = e->GetDisplayDefaultCapacity(&this->te.mail_capacity);
|
this->te.FillDefaultCapacities(e);
|
||||||
this->te.cargo = e->GetDefaultCargoType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnInit() override
|
void OnInit() override
|
||||||
@@ -2245,6 +2263,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase {
|
|||||||
state.te.capacity = _returned_refit_capacity;
|
state.te.capacity = _returned_refit_capacity;
|
||||||
state.te.mail_capacity = _returned_mail_refit_capacity;
|
state.te.mail_capacity = _returned_mail_refit_capacity;
|
||||||
state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
||||||
|
state.te.all_capacities = _returned_vehicle_capacities;
|
||||||
delete t;
|
delete t;
|
||||||
RestoreRandomSeeds(saved_seeds);
|
RestoreRandomSeeds(saved_seeds);
|
||||||
return;
|
return;
|
||||||
@@ -2260,14 +2279,14 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase {
|
|||||||
state.te.capacity = _returned_refit_capacity;
|
state.te.capacity = _returned_refit_capacity;
|
||||||
state.te.mail_capacity = _returned_mail_refit_capacity;
|
state.te.mail_capacity = _returned_mail_refit_capacity;
|
||||||
state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
state.te.cargo = (cargo == CT_INVALID) ? e->GetDefaultCargoType() : cargo;
|
||||||
|
state.te.all_capacities = _returned_vehicle_capacities;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Purchase test was not possible or failed, fill in the defaults instead. */
|
/* Purchase test was not possible or failed, fill in the defaults instead. */
|
||||||
state.te.cost = 0;
|
state.te.cost = 0;
|
||||||
state.te.capacity = e->GetDisplayDefaultCapacity(&state.te.mail_capacity);
|
state.te.FillDefaultCapacities(e);
|
||||||
state.te.cargo = e->GetDefaultCargoType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnInit() override
|
void OnInit() override
|
||||||
|
@@ -25,7 +25,6 @@ extern const uint8 _engine_offsets[4];
|
|||||||
|
|
||||||
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
|
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
|
||||||
bool IsEngineRefittable(EngineID engine);
|
bool IsEngineRefittable(EngineID engine);
|
||||||
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits, CargoID cargo_type, uint cargo_capacity);
|
|
||||||
void SetYearEngineAgingStops();
|
void SetYearEngineAgingStops();
|
||||||
void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date);
|
void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date);
|
||||||
|
|
||||||
|
@@ -95,6 +95,7 @@ static const uint GEN_HASHY_BUCKET_BITS = 6;
|
|||||||
VehicleID _new_vehicle_id;
|
VehicleID _new_vehicle_id;
|
||||||
uint _returned_refit_capacity; ///< Stores the capacity after a refit operation.
|
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).
|
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. */
|
/** The pool with all our precious vehicles. */
|
||||||
|
@@ -167,7 +167,16 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
|||||||
value.AddCost(CmdRefitVehicle(tile, flags, v->index, cargo | (1 << 16), nullptr));
|
value.AddCost(CmdRefitVehicle(tile, flags, v->index, cargo | (1 << 16), nullptr));
|
||||||
} else {
|
} else {
|
||||||
/* Fill in non-refitted capacities */
|
/* 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) {
|
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_capacity = 0;
|
||||||
uint total_mail_capacity = 0;
|
uint total_mail_capacity = 0;
|
||||||
num_vehicles = num_vehicles == 0 ? UINT8_MAX : num_vehicles;
|
num_vehicles = num_vehicles == 0 ? UINT8_MAX : num_vehicles;
|
||||||
|
_returned_vehicle_capacities.Clear();
|
||||||
|
|
||||||
VehicleSet vehicles_to_refit;
|
VehicleSet vehicles_to_refit;
|
||||||
if (!only_this) {
|
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,
|
/* If the vehicle is not refittable, or does not allow automatic refitting,
|
||||||
* count its capacity nevertheless if the cargo matches */
|
* 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));
|
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 */
|
/* Determine best fitting subtype if requested */
|
||||||
if (actual_subtype == 0xFF) {
|
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. */
|
/* mail_capacity will always be zero if the vehicle is not an aircraft. */
|
||||||
total_mail_capacity += mail_capacity;
|
total_mail_capacity += mail_capacity;
|
||||||
|
|
||||||
|
_returned_vehicle_capacities[new_cid] += amount;
|
||||||
|
_returned_vehicle_capacities[CT_MAIL] += mail_capacity;
|
||||||
|
|
||||||
if (!refittable) continue;
|
if (!refittable) continue;
|
||||||
|
|
||||||
/* Restore the original cargo type */
|
/* Restore the original cargo type */
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "newgrf_config.h"
|
#include "newgrf_config.h"
|
||||||
#include "track_type.h"
|
#include "track_type.h"
|
||||||
#include "livery.h"
|
#include "livery.h"
|
||||||
|
#include "cargo_type.h"
|
||||||
|
|
||||||
#define is_custom_sprite(x) (x >= 0xFD)
|
#define is_custom_sprite(x) (x >= 0xFD)
|
||||||
#define IS_CUSTOM_FIRSTHEAD_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 VehicleID _new_vehicle_id;
|
||||||
extern uint _returned_refit_capacity;
|
extern uint _returned_refit_capacity;
|
||||||
extern uint16 _returned_mail_refit_capacity;
|
extern uint16 _returned_mail_refit_capacity;
|
||||||
|
extern CargoArray _returned_vehicle_capacities;
|
||||||
|
|
||||||
bool CanVehicleUseStation(EngineID engine_type, const struct Station *st);
|
bool CanVehicleUseStation(EngineID engine_type, const struct Station *st);
|
||||||
bool CanVehicleUseStation(const Vehicle *v, const struct Station *st);
|
bool CanVehicleUseStation(const Vehicle *v, const struct Station *st);
|
||||||
|
@@ -42,6 +42,9 @@ struct TestedEngineDetails {
|
|||||||
CargoID cargo; ///< Cargo type
|
CargoID cargo; ///< Cargo type
|
||||||
uint capacity; ///< Cargo capacity
|
uint capacity; ///< Cargo capacity
|
||||||
uint16 mail_capacity; ///< Mail capacity if available
|
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);
|
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te);
|
||||||
|
Reference in New Issue
Block a user