Change: Decouple and remove landscape-dependent cargo types. (#11719)

Cargo types of default engines, industries and houses are now specified in terms of label.
This commit is contained in:
Peter Nelson 2024-02-04 10:16:08 +00:00 committed by GitHub
parent 83d63464db
commit 2fd9096070
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 378 additions and 275 deletions

View File

@ -306,11 +306,16 @@ CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *
v->cargo_cap = avi->passenger_capacity;
v->refit_cap = 0;
u->cargo_cap = avi->mail_capacity;
u->refit_cap = 0;
v->cargo_type = e->GetDefaultCargoType();
u->cargo_type = CT_MAIL;
assert(IsValidCargoID(v->cargo_type));
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) {
u->cargo_type = mail;
u->cargo_cap = avi->mail_capacity;
}
v->name.clear();
v->last_station_visited = INVALID_STATION;

View File

@ -398,6 +398,7 @@ void AddArticulatedParts(Vehicle *first)
rv->spritenum = e_artic->u.road.image_index;
if (e_artic->CanCarryCargo()) {
rv->cargo_type = e_artic->GetDefaultCargoType();
assert(IsValidCargoID(rv->cargo_type));
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
} else {
rv->cargo_type = front->cargo_type; // Needed for livery selection

View File

@ -820,7 +820,7 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
if (te.mail_capacity > 0) {
SetDParam(0, te.cargo);
SetDParam(1, te.capacity);
SetDParam(2, CT_MAIL);
SetDParam(2, GetCargoIDByLabel(CT_MAIL));
SetDParam(3, te.mail_capacity);
DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY);
} else {
@ -902,7 +902,11 @@ void TestedEngineDetails::FillDefaultCapacities(const Engine *e)
} else {
this->capacity = e->GetDisplayDefaultCapacity(&this->mail_capacity);
this->all_capacities[this->cargo] = this->capacity;
this->all_capacities[CT_MAIL] = this->mail_capacity;
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
this->all_capacities[GetCargoIDByLabel(CT_MAIL)] = this->mail_capacity;
} else {
this->mail_capacity = 0;
}
}
if (this->all_capacities.GetCount() == 0) this->cargo = INVALID_CARGO;
}

View File

@ -11,58 +11,64 @@
#define CARGO_TYPE_H
#include "core/enum_type.hpp"
#include "core/strong_typedef_type.hpp"
/** Globally unique label of a cargo type. */
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongType::Compare>;
/**
* Cargo slots to indicate a cargo type within a game.
* Numbers are re-used between different climates.
* @see CargoTypes
*/
typedef byte CargoID;
using CargoID = byte;
/** Available types of cargo */
enum CargoType {
/* Temperate */
CT_PASSENGERS = 0,
CT_COAL = 1,
CT_MAIL = 2,
CT_OIL = 3,
CT_LIVESTOCK = 4,
CT_GOODS = 5,
CT_GRAIN = 6,
CT_WOOD = 7,
CT_IRON_ORE = 8,
CT_STEEL = 9,
CT_VALUABLES = 10,
/**
* Available types of cargo
* Labels may be re-used between different climates.
*/
/* Arctic */
CT_WHEAT = 6,
CT_HILLY_UNUSED = 8,
CT_PAPER = 9,
CT_GOLD = 10,
CT_FOOD = 11,
/* Temperate */
static constexpr CargoLabel CT_PASSENGERS = CargoLabel{'PASS'};
static constexpr CargoLabel CT_COAL = CargoLabel{'COAL'};
static constexpr CargoLabel CT_MAIL = CargoLabel{'MAIL'};
static constexpr CargoLabel CT_OIL = CargoLabel{'OIL_'};
static constexpr CargoLabel CT_LIVESTOCK = CargoLabel{'LVST'};
static constexpr CargoLabel CT_GOODS = CargoLabel{'GOOD'};
static constexpr CargoLabel CT_GRAIN = CargoLabel{'GRAI'};
static constexpr CargoLabel CT_WOOD = CargoLabel{'WOOD'};
static constexpr CargoLabel CT_IRON_ORE = CargoLabel{'IORE'};
static constexpr CargoLabel CT_STEEL = CargoLabel{'STEL'};
static constexpr CargoLabel CT_VALUABLES = CargoLabel{'VALU'};
/* Tropic */
CT_RUBBER = 1,
CT_FRUIT = 4,
CT_MAIZE = 6,
CT_COPPER_ORE = 8,
CT_WATER = 9,
CT_DIAMONDS = 10,
/* Arctic */
static constexpr CargoLabel CT_WHEAT = CargoLabel{'WHEA'};
static constexpr CargoLabel CT_PAPER = CargoLabel{'PAPR'};
static constexpr CargoLabel CT_GOLD = CargoLabel{'GOLD'};
static constexpr CargoLabel CT_FOOD = CargoLabel{'FOOD'};
/* Toyland */
CT_SUGAR = 1,
CT_TOYS = 3,
CT_BATTERIES = 4,
CT_CANDY = 5,
CT_TOFFEE = 6,
CT_COLA = 7,
CT_COTTON_CANDY = 8,
CT_BUBBLES = 9,
CT_PLASTIC = 10,
CT_FIZZY_DRINKS = 11,
/* Tropic */
static constexpr CargoLabel CT_RUBBER = CargoLabel{'RUBR'};
static constexpr CargoLabel CT_FRUIT = CargoLabel{'FRUI'};
static constexpr CargoLabel CT_MAIZE = CargoLabel{'MAIZ'};
static constexpr CargoLabel CT_COPPER_ORE = CargoLabel{'CORE'};
static constexpr CargoLabel CT_WATER = CargoLabel{'WATR'};
static constexpr CargoLabel CT_DIAMONDS = CargoLabel{'DIAM'};
CT_INVALID = 0xFF, ///< Invalid cargo type.
};
/* Toyland */
static constexpr CargoLabel CT_SUGAR = CargoLabel{'SUGR'};
static constexpr CargoLabel CT_TOYS = CargoLabel{'TOYS'};
static constexpr CargoLabel CT_BATTERIES = CargoLabel{'BATT'};
static constexpr CargoLabel CT_CANDY = CargoLabel{'SWET'};
static constexpr CargoLabel CT_TOFFEE = CargoLabel{'TOFF'};
static constexpr CargoLabel CT_COLA = CargoLabel{'COLA'};
static constexpr CargoLabel CT_COTTON_CANDY = CargoLabel{'CTCD'};
static constexpr CargoLabel CT_BUBBLES = CargoLabel{'BUBL'};
static constexpr CargoLabel CT_PLASTIC = CargoLabel{'PLST'};
static constexpr CargoLabel CT_FIZZY_DRINKS = CargoLabel{'FZDR'};
/** Dummy label for engines that carry no cargo; they actually carry 0 passengers. */
static constexpr CargoLabel CT_NONE = CT_PASSENGERS;
static constexpr CargoLabel CT_INVALID = CargoLabel{UINT32_MAX}; ///< Invalid cargo type.
static const CargoID NUM_ORIGINAL_CARGO = 12; ///< Original number of cargo types.
static const CargoID NUM_CARGO = 64; ///< Maximum number of cargo types in a game.
@ -85,7 +91,7 @@ namespace CargoFilterCriteria {
};
/** Test whether cargo type is not CT_INVALID */
inline bool IsValidCargoType(CargoType t) { return t != CT_INVALID; }
inline bool IsValidCargoType(CargoLabel t) { return t != CT_INVALID; }
/** Test whether cargo type is not INVALID_CARGO */
inline bool IsValidCargoID(CargoID t) { return t != INVALID_CARGO; }

View File

@ -35,6 +35,12 @@ CargoTypes _cargo_mask;
*/
CargoTypes _standard_cargo_mask;
/**
* List of default cargo labels, used when setting up cargo types for default vehicles.
* This is done by label so that a cargo label can be redefined in a different slot.
*/
static std::vector<CargoLabel> _default_cargo_labels;
/**
* Set up the default cargo types for the given landscape type.
* @param l Landscape
@ -44,18 +50,20 @@ void SetupCargoForClimate(LandscapeID l)
assert(l < lengthof(_default_climate_cargo));
_cargo_mask = 0;
_default_cargo_labels.clear();
/* Copy from default cargo by label or index. */
auto insert = std::begin(CargoSpec::array);
for (const CargoLabel &cl : _default_climate_cargo[l]) {
for (const auto &cl : _default_climate_cargo[l]) {
/* Check if value is an index into the cargo table */
if (cl < lengthof(_default_cargo)) {
if (std::holds_alternative<int>(cl)) {
/* Copy the default cargo by index. */
*insert = _default_cargo[cl];
*insert = _default_cargo[std::get<int>(cl)];
} else {
/* Search for label in default cargo types and copy if found. */
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&cl](const CargoSpec &cs) { return cs.label == cl; });
CargoLabel label = std::get<CargoLabel>(cl);
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&label](const CargoSpec &cs) { return cs.label == label; });
if (found != std::end(_default_cargo)) {
*insert = *found;
} else {
@ -64,12 +72,49 @@ void SetupCargoForClimate(LandscapeID l)
}
}
if (insert->IsValid()) SetBit(_cargo_mask, insert->Index());
if (insert->IsValid()) {
SetBit(_cargo_mask, insert->Index());
_default_cargo_labels.push_back(insert->label);
}
++insert;
}
/* Reset and disable remaining cargo types. */
std::fill(insert, std::end(CargoSpec::array), CargoSpec{});
BuildCargoLabelMap();
}
/**
* Build cargo label map.
* This is called multiple times during NewGRF initialization as cargos are defined, so that TranslateRefitMask() and
* GetCargoTranslation(), also used during initialization, get the correct information.
*/
void BuildCargoLabelMap()
{
CargoSpec::label_map.clear();
for (const CargoSpec &cs : CargoSpec::array) {
/* During initialization, CargoSpec can be marked valid before the label has been set. */
if (!cs.IsValid() || cs.label == CargoLabel{0}) continue;
/* Label already exists, don't addd again. */
if (CargoSpec::label_map.count(cs.label) != 0) continue;
CargoSpec::label_map.insert(std::make_pair(cs.label, cs.Index()));
}
}
/**
* Test if a cargo is a default cargo type.
* @param cid Cargo ID.
* @returns true iff the cargo type is a default cargo type.
*/
bool IsDefaultCargo(CargoID cid)
{
auto cs = CargoSpec::Get(cid);
if (!cs->IsValid()) return false;
CargoLabel label = cs->label;
return std::any_of(std::begin(_default_cargo_labels), std::end(_default_cargo_labels), [&label](const CargoLabel &cl) { return cl == label; });
}
/**
@ -85,44 +130,6 @@ Dimension GetLargestCargoIconSize()
return size;
}
/**
* Get the cargo ID of a default cargo, if present.
* @param l Landscape
* @param ct Default cargo type.
* @return ID number if the cargo exists, else #INVALID_CARGO
*/
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct)
{
assert(l < lengthof(_default_climate_cargo));
if (!IsValidCargoType(ct)) return INVALID_CARGO;
assert(ct < lengthof(_default_climate_cargo[0]));
CargoLabel cl = _default_climate_cargo[l][ct];
/* Bzzt: check if cl is just an index into the cargo table */
if (cl < lengthof(_default_cargo)) {
cl = _default_cargo[cl].label;
}
return GetCargoIDByLabel(cl);
}
/**
* Get the cargo ID by cargo label.
* @param cl Cargo type to get.
* @return ID number if the cargo exists, else #INVALID_CARGO
*/
CargoID GetCargoIDByLabel(CargoLabel cl)
{
for (const CargoSpec *cs : CargoSpec::Iterate()) {
if (cs->label == cl) return cs->Index();
}
/* No matching label was found, so it is invalid */
return INVALID_CARGO;
}
/**
* Find the CargoID of a 'bitnum' value.
* @param bitnum 'bitnum' to find.

View File

@ -17,9 +17,6 @@
#include "landscape_type.h"
#include "core/bitmath_func.hpp"
/** Globally unique label of a cargo type. */
typedef uint32_t CargoLabel;
/** Town growth effect when delivering cargo. */
enum TownAcceptanceEffect : byte {
TAE_BEGIN = 0,
@ -194,8 +191,11 @@ struct CargoSpec {
private:
static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
static inline std::map<CargoLabel, CargoID> label_map{}; ///< Translation map from CargoLabel to Cargo ID.
friend void SetupCargoForClimate(LandscapeID l);
friend void BuildCargoLabelMap();
friend inline CargoID GetCargoIDByLabel(CargoLabel ct);
friend void FinaliseCargoArray();
};
@ -203,9 +203,17 @@ extern CargoTypes _cargo_mask;
extern CargoTypes _standard_cargo_mask;
void SetupCargoForClimate(LandscapeID l);
CargoID GetCargoIDByLabel(CargoLabel cl);
bool IsDefaultCargo(CargoID cid);
void BuildCargoLabelMap();
CargoID GetCargoIDByBitnum(uint8_t bitnum);
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct);
inline CargoID GetCargoIDByLabel(CargoLabel label)
{
auto found = CargoSpec::label_map.find(label);
if (found != std::end(CargoSpec::label_map)) return found->second;
return INVALID_CARGO;
}
Dimension GetLargestCargoIconSize();
void InitializeSortedCargoSpecs();

View File

@ -2541,7 +2541,7 @@ static void ConDumpCargoTypes()
IConsolePrint(CC_DEFAULT, " {:02d} Bit: {:2d}, Label: {:c}{:c}{:c}{:c}, Callback mask: 0x{:02X}, Cargo class: {}{}{}{}{}{}{}{}{}{}{}, GRF: {:08X}, {}",
spec->Index(),
spec->bitnum,
spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label,
spec->label.base() >> 24, spec->label.base() >> 16, spec->label.base() >> 8, spec->label.base(),
spec->callback_mask,
(spec->classes & CC_PASSENGERS) != 0 ? 'p' : '-',
(spec->classes & CC_MAIL) != 0 ? 'm' : '-',

View File

@ -244,8 +244,10 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
if (!IsCargoInClass(cargo_type, CC_PASSENGERS)) {
extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v);
}
if (!new_multipliers && cargo_type == CT_MAIL) return capacity + extra_mail_cap;
default_cargo = CT_PASSENGERS; // Always use 'passengers' wrt. cargo multipliers
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
if (!new_multipliers && cargo_type == GetCargoIDByLabel(CT_MAIL)) return capacity + extra_mail_cap;
}
default_cargo = GetCargoIDByLabel(CT_PASSENGERS); // Always use 'passengers' wrt. cargo multipliers
break;
default: NOT_REACHED();
@ -262,8 +264,8 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
uint16_t default_multiplier = new_multipliers ? 0x100 : CargoSpec::Get(default_cargo)->multiplier;
uint16_t cargo_multiplier = CargoSpec::Get(cargo_type)->multiplier;
capacity *= cargo_multiplier;
if (extra_mail_cap > 0) {
uint mail_multiplier = CargoSpec::Get(CT_MAIL)->multiplier;
if (extra_mail_cap > 0 && IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
uint mail_multiplier = CargoSpec::Get(GetCargoIDByLabel(CT_MAIL))->multiplier;
capacity += (default_multiplier * extra_mail_cap * cargo_multiplier + mail_multiplier / 2) / mail_multiplier;
}
capacity = (capacity + default_multiplier / 2) / default_multiplier;

View File

@ -211,7 +211,7 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
SetDParam(9, mail_capacity > 0 ? STR_ENGINE_PREVIEW_CAPACITY_2 : STR_ENGINE_PREVIEW_CAPACITY);
SetDParam(10, cargo);
SetDParam(11, capacity);
SetDParam(12, CT_MAIL);
SetDParam(12, GetCargoIDByLabel(CT_MAIL));
SetDParam(13, mail_capacity);
return STR_ENGINE_PREVIEW_TEXT4;

View File

@ -149,6 +149,7 @@ struct EngineInfo {
byte load_amount;
byte climates; ///< Climates supported by the engine.
CargoID cargo_type;
CargoLabel cargo_label;
CargoTypes refit_mask;
byte refit_cost;
byte misc_flags; ///< Miscellaneous flags. @see EngineMiscFlags

View File

@ -106,6 +106,7 @@ struct HouseSpec {
byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below)
byte cargo_acceptance[HOUSE_NUM_ACCEPTS]; ///< acceptance level for the cargo slots
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]; ///< input cargo slots
CargoLabel accepts_cargo_label[HOUSE_NUM_ACCEPTS]; ///< input landscape cargo slots
BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...)
HouseZones building_availability; ///< where can it be built (climates, zones)
bool enabled; ///< the house is available to build (true by default, but can be disabled by newgrf)

View File

@ -982,7 +982,7 @@ bool IsTileForestIndustry(TileIndex tile)
if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
/* Check for wood production */
return std::any_of(std::begin(ind->produced), std::end(ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo) && CargoSpec::Get(p.cargo)->label == 'WOOD'; });
return std::any_of(std::begin(ind->produced), std::end(ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo) && CargoSpec::Get(p.cargo)->label == CT_WOOD; });
}
static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
@ -1869,7 +1869,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->accepted.size()) : 3;
for (uint j = 0; j < maxcargoes; j++) {
uint16_t res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
break;
@ -1901,7 +1901,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->produced.size()) : 2;
for (uint j = 0; j < maxcargoes; j++) {
uint16_t res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
break;
@ -2877,7 +2877,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
/* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
new_prod = Clamp(new_prod, 1, 255);
if (p.cargo == CT_PASSENGERS && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
if (IsValidCargoID(p.cargo) && p.cargo == GetCargoIDByLabel(CT_PASSENGERS) && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
new_prod = Clamp(new_prod, 0, 16);
}

View File

@ -110,6 +110,7 @@ struct IndustrySpec {
IndustryType conflicting[3]; ///< Industries this industry cannot be close to
byte check_proc; ///< Index to a procedure to check for conflicting circumstances
CargoID produced_cargo[INDUSTRY_NUM_OUTPUTS];
CargoLabel produced_cargo_label[INDUSTRY_NUM_OUTPUTS];
byte production_rate[INDUSTRY_NUM_OUTPUTS];
/**
* minimum amount of cargo transported to the stations.
@ -117,6 +118,7 @@ struct IndustrySpec {
*/
byte minimal_cargo;
CargoID accepts_cargo[INDUSTRY_NUM_INPUTS]; ///< 16 accepted cargoes.
CargoLabel accepts_cargo_label[INDUSTRY_NUM_INPUTS];
uint16_t input_cargo_multiplier[INDUSTRY_NUM_INPUTS][INDUSTRY_NUM_OUTPUTS]; ///< Input cargo multipliers (multiply amount of incoming cargo for the produced cargoes)
IndustryLifeType life_type; ///< This is also known as Industry production flag, in newgrf specs
byte climate_availability; ///< Bitmask, giving landscape enums as bit position
@ -153,6 +155,7 @@ struct IndustrySpec {
*/
struct IndustryTileSpec {
std::array<CargoID, INDUSTRY_NUM_INPUTS> accepts_cargo; ///< Cargo accepted by this tile
std::array<CargoLabel, INDUSTRY_NUM_INPUTS> accepts_cargo_label;
std::array<int8_t, INDUSTRY_NUM_INPUTS> acceptance; ///< Level of acceptance per cargo type (signed, may be negative!)
Slope slopes_refused; ///< slope pattern on which this tile cannot be built
byte anim_production; ///< Animation frame to start when goods are produced

View File

@ -1151,6 +1151,7 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop
ei->cargo_type = INVALID_CARGO;
GrfMsg(2, "RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
}
ei->cargo_label = CT_INVALID;
break;
}
@ -1412,6 +1413,7 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
ei->cargo_type = INVALID_CARGO;
GrfMsg(2, "RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
}
ei->cargo_label = CT_INVALID;
break;
}
@ -1607,6 +1609,7 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop
ei->cargo_type = INVALID_CARGO;
GrfMsg(2, "ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
}
ei->cargo_label = CT_INVALID;
break;
}
@ -2426,7 +2429,9 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt
* climate. This can cause problems when copying the properties
* of a house that accepts food, where the new house is valid
* in the temperate climate. */
if (!CargoSpec::Get(housespec->accepts_cargo[2])->IsValid()) {
CargoID cid = housespec->accepts_cargo[2];
if (!IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
if (!IsValidCargoID(cid) || !CargoSpec::Get(cid)->IsValid()) {
housespec->cargo_acceptance[2] = 0;
}
}
@ -2462,13 +2467,14 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt
/* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
* Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_CANDY) : GetCargoIDByLabel(CT_GOODS)) :
((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_FIZZY_DRINKS) : GetCargoIDByLabel(CT_FOOD));
/* Make sure the cargo type is valid in this climate. */
if (!CargoSpec::Get(cid)->IsValid()) goods = 0;
housespec->accepts_cargo[2] = cid;
housespec->accepts_cargo_label[2] = CT_INVALID;
housespec->cargo_acceptance[2] = abs(goods); // but we do need positive value here
break;
}
@ -2636,7 +2642,7 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt
* @return ChangeInfoResult.
*/
template <typename T>
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader *buf, T &translation_table, const char *name)
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader *buf, std::vector<T> &translation_table, const char *name)
{
if (gvid != 0) {
GrfMsg(1, "LoadTranslationTable: {} translation table must start at zero", name);
@ -2645,8 +2651,7 @@ static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader
translation_table.clear();
for (int i = 0; i < numinfo; i++) {
uint32_t item = buf->ReadDWord();
translation_table.push_back(BSWAP32(item));
translation_table.push_back(T(BSWAP32(buf->ReadDWord())));
}
return CIR_SUCCESS;
@ -2991,6 +2996,7 @@ static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteRea
} else {
ClrBit(_cargo_mask, cid + i);
}
BuildCargoLabelMap();
break;
case 0x09: // String ID for cargo type name
@ -3058,8 +3064,8 @@ static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteRea
break;
case 0x17: // Cargo label
cs->label = buf->ReadDWord();
cs->label = BSWAP32(cs->label);
cs->label = CargoLabel{BSWAP32(buf->ReadDWord())};
BuildCargoLabelMap();
break;
case 0x18: { // Town growth substitute type
@ -3666,12 +3672,14 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
case 0x10: // Production cargo types
for (byte j = 0; j < 2; j++) {
indsp->produced_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
indsp->produced_cargo_label[j] = CT_INVALID;
}
break;
case 0x11: // Acceptance cargo types
for (byte j = 0; j < 3; j++) {
indsp->accepts_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
indsp->accepts_cargo_label[j] = CT_INVALID;
}
buf->ReadByte(); // Unnused, eat it up
break;
@ -5564,18 +5572,18 @@ static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
/* Look up the cargo label from the translation table */
CargoLabel cl = _cur.grffile->cargo_list[ctype];
if (cl == 0) {
if (cl == CT_INVALID) {
GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
return INVALID_CARGO;
}
CargoID cid = GetCargoIDByLabel(cl);
if (!IsValidCargoID(cid)) {
GrfMsg(5, "TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' unsupported, skipping.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8));
GrfMsg(5, "TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' unsupported, skipping.", GB(cl.base(), 24, 8), GB(cl.base(), 16, 8), GB(cl.base(), 8, 8), GB(cl.base(), 0, 8));
return INVALID_CARGO;
}
GrfMsg(6, "TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' mapped to cargo type {}.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8), cid);
GrfMsg(6, "TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' mapped to cargo type {}.", GB(cl.base(), 24, 8), GB(cl.base(), 16, 8), GB(cl.base(), 8, 8), GB(cl.base(), 0, 8), cid);
return cid;
}
@ -6864,9 +6872,9 @@ static void SkipIf(ByteReader *buf)
if (condtype >= 0x0B) {
/* Tests that ignore 'param' */
switch (condtype) {
case 0x0B: result = !IsValidCargoID(GetCargoIDByLabel(BSWAP32(cond_val)));
case 0x0B: result = !IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
break;
case 0x0C: result = IsValidCargoID(GetCargoIDByLabel(BSWAP32(cond_val)));
case 0x0C: result = IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
break;
case 0x0D: result = GetRailTypeByLabel(BSWAP32(cond_val)) == INVALID_RAILTYPE;
break;
@ -8961,9 +8969,8 @@ GRFFile::~GRFFile()
static void CalculateRefitMasks()
{
CargoTypes original_known_cargoes = 0;
for (int ct = 0; ct != NUM_ORIGINAL_CARGO; ++ct) {
CargoID cid = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ct));
if (IsValidCargoID(cid)) SetBit(original_known_cargoes, cid);
for (CargoID cid = 0; cid != NUM_CARGO; ++cid) {
if (IsDefaultCargo(cid)) SetBit(original_known_cargoes, cid);
}
for (Engine *e : Engine::Iterate()) {
@ -8971,6 +8978,11 @@ static void CalculateRefitMasks()
EngineInfo *ei = &e->info;
bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo
/* Apply default cargo translation map if cargo type hasn't been set, either explicitly or by aircraft cargo handling. */
if (!IsValidCargoID(e->info.cargo_type)) {
e->info.cargo_type = GetCargoIDByLabel(e->info.cargo_label);
}
/* If the NewGRF did not set any cargo properties, we apply default values. */
if (_gted[engine].defaultcargo_grf == nullptr) {
/* If the vehicle has any capacity, apply the default refit masks */
@ -8981,7 +8993,7 @@ static void CalculateRefitMasks()
static constexpr byte Y = 1 << LT_TOYLAND;
static const struct DefaultRefitMasks {
byte climate;
CargoType cargo_type;
CargoLabel cargo_label;
CargoTypes cargo_allowed;
CargoTypes cargo_disallowed;
} _default_refit_masks[] = {
@ -9005,13 +9017,13 @@ static void CalculateRefitMasks()
_gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS;
_gted[engine].cargo_disallowed = CC_LIQUID;
} else if (e->type == VEH_SHIP) {
switch (ei->cargo_type) {
case CT_PASSENGERS:
switch (ei->cargo_label.base()) {
case CT_PASSENGERS.base():
/* Ferries */
_gted[engine].cargo_allowed = CC_PASSENGERS;
_gted[engine].cargo_disallowed = 0;
break;
case CT_OIL:
case CT_OIL.base():
/* Tankers */
_gted[engine].cargo_allowed = CC_LIQUID;
_gted[engine].cargo_disallowed = 0;
@ -9038,7 +9050,7 @@ static void CalculateRefitMasks()
/* Train wagons and road vehicles are classified by their default cargo type */
for (const auto &drm : _default_refit_masks) {
if (!HasBit(drm.climate, _settings_game.game_creation.landscape)) continue;
if (drm.cargo_type != ei->cargo_type) continue;
if (drm.cargo_label != ei->cargo_label) continue;
_gted[engine].cargo_allowed = drm.cargo_allowed;
_gted[engine].cargo_disallowed = drm.cargo_disallowed;
@ -9051,8 +9063,6 @@ static void CalculateRefitMasks()
}
_gted[engine].UpdateRefittability(_gted[engine].cargo_allowed != 0);
/* Translate cargo_type using the original climate-specific cargo table. */
ei->cargo_type = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ei->cargo_type));
if (IsValidCargoID(ei->cargo_type)) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
}
@ -9206,10 +9216,10 @@ void FinaliseCargoArray()
for (CargoSpec &cs : CargoSpec::array) {
if (cs.town_production_effect == INVALID_TPE) {
/* Set default town production effect by cargo label. */
switch (cs.label) {
case 'PASS': cs.town_production_effect = TPE_PASSENGERS; break;
case 'MAIL': cs.town_production_effect = TPE_MAIL; break;
default: cs.town_production_effect = TPE_NONE; break;
switch (cs.label.base()) {
case CT_PASSENGERS.base(): cs.town_production_effect = TPE_PASSENGERS; break;
case CT_MAIL.base(): cs.town_production_effect = TPE_MAIL; break;
default: cs.town_production_effect = TPE_NONE; break;
}
}
if (!cs.IsValid()) {
@ -9352,6 +9362,13 @@ static void FinaliseHouseArray()
* this one in the pool is properly handled as 1x1 house. */
hs->building_flags = TILE_NO_FLAG;
}
/* Apply default cargo translation map for unset cargo slots */
for (uint i = 0; i < lengthof(hs->accepts_cargo); ++i) {
if (!IsValidCargoID(hs->accepts_cargo[i])) hs->accepts_cargo[i] = GetCargoIDByLabel(hs->accepts_cargo_label[i]);
/* Disable acceptance if cargo type is invalid. */
if (!IsValidCargoID(hs->accepts_cargo[i])) hs->cargo_acceptance[i] = 0;
}
}
HouseZones climate_mask = (HouseZones)(1 << (_settings_game.game_creation.landscape + 12));
@ -9426,6 +9443,21 @@ static void FinaliseIndustriesArray()
if (!indsp.enabled) {
indsp.name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
}
/* Apply default cargo translation map for unset cargo slots */
for (uint i = 0; i < lengthof(indsp.produced_cargo); ++i) {
if (!IsValidCargoID(indsp.produced_cargo[i])) indsp.produced_cargo[i] = GetCargoIDByLabel(indsp.produced_cargo_label[i]);
}
for (uint i = 0; i < lengthof(indsp.accepts_cargo); ++i) {
if (!IsValidCargoID(indsp.accepts_cargo[i])) indsp.accepts_cargo[i] = GetCargoIDByLabel(indsp.accepts_cargo_label[i]);
}
}
for (auto &indtsp : _industry_tile_specs) {
/* Apply default cargo translation map for unset cargo slots */
for (uint i = 0; i < lengthof(indtsp.accepts_cargo); ++i) {
if (!IsValidCargoID(indtsp.accepts_cargo[i])) indtsp.accepts_cargo[i] = GetCargoIDByLabel(indtsp.accepts_cargo_label[i]);
}
}
}

View File

@ -30,7 +30,7 @@ GrfSpecFeature CargoResolverObject::GetFeature() const
uint32_t CargoResolverObject::GetDebugID() const
{
return this->cargospec->label;
return this->cargospec->label.base();
}
/**

View File

@ -17,6 +17,7 @@
/* virtual */ uint32_t TownScopeResolver::GetVariable(byte variable, [[maybe_unused]] uint32_t parameter, bool *available) const
{
CargoID cid;
switch (variable) {
/* Larger towns */
case 0x40:
@ -81,24 +82,24 @@
case 0xB2: return this->t->statues;
case 0xB6: return ClampTo<uint16_t>(this->t->cache.num_houses);
case 0xB9: return this->t->growth_rate / Ticks::TOWN_GROWTH_TICKS;
case 0xBA: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_max);
case 0xBB: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_max), 8, 8);
case 0xBC: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_max);
case 0xBD: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_max), 8, 8);
case 0xBE: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_act);
case 0xBF: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_act), 8, 8);
case 0xC0: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_act);
case 0xC1: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_act), 8, 8);
case 0xC2: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_max);
case 0xC3: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_max), 8, 8);
case 0xC4: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_max);
case 0xC5: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_max), 8, 8);
case 0xC6: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_act);
case 0xC7: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_act), 8, 8);
case 0xC8: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_act);
case 0xC9: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_act), 8, 8);
case 0xCA: return this->t->GetPercentTransported(CT_PASSENGERS);
case 0xCB: return this->t->GetPercentTransported(CT_MAIL);
case 0xBA: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_max) : 0;
case 0xBB: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_max), 8, 8) : 0;
case 0xBC: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_max) : 0;
case 0xBD: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_max), 8, 8) : 0;
case 0xBE: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_act) : 0;
case 0xBF: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_act), 8, 8) : 0;
case 0xC0: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_act) : 0;
case 0xC1: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_act), 8, 8) : 0;
case 0xC2: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_max) : 0;
case 0xC3: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_max), 8, 8) : 0;
case 0xC4: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_max) : 0;
case 0xC5: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_max), 8, 8) : 0;
case 0xC6: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_act) : 0;
case 0xC7: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_act), 8, 8) : 0;
case 0xC8: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_act) : 0;
case 0xC9: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_act), 8, 8) : 0;
case 0xCA: return this->t->GetPercentTransported(GetCargoIDByLabel(CT_PASSENGERS));
case 0xCB: return this->t->GetPercentTransported(GetCargoIDByLabel(CT_MAIL));
case 0xCC: return this->t->received[TAE_FOOD].new_act;
case 0xCD: return GB(this->t->received[TAE_FOOD].new_act, 8, 8);
case 0xCE: return this->t->received[TAE_WATER].new_act;

View File

@ -630,23 +630,31 @@ static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, Carg
/* Top town building generates 10, so to make HQ interesting, the top
* type makes 20. */
acceptance[CT_PASSENGERS] += std::max(1U, level);
SetBit(*always_accepted, CT_PASSENGERS);
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
if (IsValidCargoID(pass)) {
acceptance[pass] += std::max(1U, level);
SetBit(*always_accepted, pass);
}
/* Top town building generates 4, HQ can make up to 8. The
* proportion passengers:mail is different because such a huge
* commercial building generates unusually high amount of mail
* correspondence per physical visitor. */
acceptance[CT_MAIL] += std::max(1U, level / 2);
SetBit(*always_accepted, CT_MAIL);
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) {
acceptance[mail] += std::max(1U, level / 2);
SetBit(*always_accepted, mail);
}
}
static void AddProducedCargo_Object(TileIndex tile, CargoArray &produced)
{
if (!IsObjectType(tile, OBJECT_HQ)) return;
produced[CT_PASSENGERS]++;
produced[CT_MAIL]++;
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
if (IsValidCargoID(pass)) produced[pass]++;
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) produced[mail]++;
}
@ -686,7 +694,8 @@ static void TileLoop_Object(TileIndex tile)
uint r = Random();
/* Top town buildings generate 250, so the top HQ type makes 256. */
if (GB(r, 0, 8) < (256 / 4 / (6 - level))) {
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
if (IsValidCargoID(pass) && GB(r, 0, 8) < (256 / 4 / (6 - level))) {
uint amt = GB(r, 0, 8) / 8 / 4 + 1;
/* Production is halved during recessions. */
@ -695,13 +704,14 @@ static void TileLoop_Object(TileIndex tile)
/* Scale by cargo scale setting. */
amt = ScaleByCargoScale(amt, true);
MoveGoodsToStation(CT_PASSENGERS, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
MoveGoodsToStation(pass, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
}
/* Top town building generates 90, HQ can make up to 196. The
* proportion passengers:mail is about the same as in the acceptance
* equations. */
if (GB(r, 8, 8) < (196 / 4 / (6 - level))) {
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail) && GB(r, 8, 8) < (196 / 4 / (6 - level))) {
uint amt = GB(r, 8, 8) / 8 / 4 + 1;
/* Production is halved during recessions. */
@ -710,7 +720,7 @@ static void TileLoop_Object(TileIndex tile)
/* Scale by cargo scale setting. */
amt = ScaleByCargoScale(amt, true);
MoveGoodsToStation(CT_MAIL, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
MoveGoodsToStation(mail, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
}
}

View File

@ -286,6 +286,7 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
v->spritenum = rvi->image_index;
v->cargo_type = e->GetDefaultCargoType();
assert(IsValidCargoID(v->cargo_type));
v->cargo_cap = rvi->capacity;
v->refit_cap = 0;

View File

@ -590,14 +590,15 @@ static const OldChunks town_chunk[] = {
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, time_until_rebuild ),
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, growth_rate ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_act ),
/* Slots 0 and 2 are passengers and mail respectively for old saves. */
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_max ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_act ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_act ),
OCL_NULL( 2 ), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
@ -1301,10 +1302,10 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
switch (v->spritenum) {
case 2: // oil tanker && cargo type != oil
if (v->cargo_type != CT_OIL) v->spritenum = 0; // make it a coal/goods ship
if (v->cargo_type != 3) v->spritenum = 0; // make it a coal/goods ship
break;
case 4: // passenger ship && cargo type == mail
if (v->cargo_type == CT_MAIL) v->spritenum = 0; // make it a mail ship
if (v->cargo_type == 2) v->spritenum = 0; // make it a mail ship
break;
default:
break;

View File

@ -222,22 +222,23 @@ static const SaveLoad _town_desc[] = {
SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_UINT32, SLV_9, SLV_165),
/* Slots 0 and 2 are passengers and mail respectively for old saves. */
SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_UINT32, SLV_9, SLV_165),
SLE_CONDVARNAME(Town, received[TAE_FOOD].old_act, "received[TE_FOOD].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
SLE_CONDVARNAME(Town, received[TAE_WATER].old_act, "received[TE_WATER].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),

View File

@ -45,7 +45,7 @@
* like "PASS", "COAL", "OIL_". New ones can be defined by NewGRFs */
std::string cargo_label;
for (uint i = 0; i < sizeof(cargo->label); i++) {
cargo_label.push_back(GB(cargo->label, (uint8_t)(sizeof(cargo->label) - i - 1) * 8, 8));
cargo_label.push_back(GB(cargo->label.base(), (uint8_t)(sizeof(cargo->label) - i - 1) * 8, 8));
}
return cargo_label;
}

View File

@ -934,6 +934,7 @@ CommandCost CmdBuildShip(DoCommandFlag flags, TileIndex tile, const Engine *e, V
v->spritenum = svi->image_index;
v->cargo_type = e->GetDefaultCargoType();
assert(IsValidCargoID(v->cargo_type));
v->cargo_cap = svi->capacity;
v->refit_cap = 0;

View File

@ -1128,8 +1128,10 @@ enum IndustryTypes {
#define MI(tbl, sndc, snd, d, pc, ai1, ai2, ai3, ai4, ag1, ag2, ag3, ag4, col, \
c1, c2, c3, proc, p1, r1, p2, r2, m, a1, im1, a2, im2, a3, im3, pr, clim, bev, in, intx, s1, s2, s3) \
{tbl, d, 0, pc, {c1, c2, c3}, proc, \
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
{p1, p2, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
{r1, r2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, m, \
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
{a1, a2, a3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
{{im1, 0}, {im2, 0}, {im3, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, \
pr, clim, bev, col, in, intx, s1, s2, s3, STR_UNDEFINED, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, \
@ -1530,7 +1532,11 @@ static const IndustrySpec _origin_industry_specs[NEW_INDUSTRYOFFSET] = {
* @param a2 next frame of animation
* @param a3 chooses between animation or construction state
*/
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, {0, ANIM_STATUS_NO_ANIMATION, 2, 0}, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE)}
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) { \
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
{c1, c2, c3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
{ca1, ca2, ca3}, sl, a1, a2, a3, 0, {0, ANIM_STATUS_NO_ANIMATION, 2, 0}, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE) \
}
static const IndustryTileSpec _origin_industry_tile_specs[NEW_INDUSTRYTILEOFFSET] = {
/* Coal Mine */
MT(0, CT_INVALID, 0, CT_INVALID, 0, CT_INVALID, SLOPE_STEEP, INDUSTRYTILE_NOANIM, INDUSTRYTILE_NOANIM, false),

View File

@ -50,56 +50,56 @@
/** Cargo types available by default. */
static const CargoSpec _default_cargo[] = {
MK( 0, 'PASS', 152, 1, 0x400, 3185, 0, 24, false, TAE_PASSENGERS, PASSENGERS, PASSENGER, STR_PASSENGERS, CC_PASSENGERS),
MK( 1, 'COAL', 6, 16, 0x100, 5916, 7, 255, true, TAE_NONE, COAL, COAL, STR_TONS, CC_BULK),
MK( 2, 'MAIL', 15, 4, 0x200, 4550, 20, 90, false, TAE_MAIL, MAIL, MAIL, STR_BAGS, CC_MAIL),
MK( 0, CT_PASSENGERS, 152, 1, 0x400, 3185, 0, 24, false, TAE_PASSENGERS, PASSENGERS, PASSENGER, STR_PASSENGERS, CC_PASSENGERS),
MK( 1, CT_COAL, 6, 16, 0x100, 5916, 7, 255, true, TAE_NONE, COAL, COAL, STR_TONS, CC_BULK),
MK( 2, CT_MAIL, 15, 4, 0x200, 4550, 20, 90, false, TAE_MAIL, MAIL, MAIL, STR_BAGS, CC_MAIL),
/* Oil in temperate and arctic */
MK( 3, 'OIL_', 174, 16, 0x100, 4437, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
MK( 3, CT_OIL, 174, 16, 0x100, 4437, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
/* Oil in subtropic */
MK( 3, 'OIL_', 174, 16, 0x100, 4892, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
MK( 4, 'LVST', 208, 3, 0x100, 4322, 4, 18, true, TAE_NONE, LIVESTOCK, LIVESTOCK, STR_ITEMS, CC_PIECE_GOODS),
MK( 5, 'GOOD', 194, 8, 0x200, 6144, 5, 28, true, TAE_GOODS, GOODS, GOODS, STR_CRATES, CC_EXPRESS),
MK( 6, 'GRAI', 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, GRAIN, GRAIN, STR_TONS, CC_BULK),
MK( 6, 'WHEA', 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, WHEAT, WHEAT, STR_TONS, CC_BULK),
MK( 6, 'MAIZ', 191, 16, 0x100, 4322, 4, 40, true, TAE_NONE, MAIZE, MAIZE, STR_TONS, CC_BULK),
MK( 3, CT_OIL, 174, 16, 0x100, 4892, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
MK( 4, CT_LIVESTOCK, 208, 3, 0x100, 4322, 4, 18, true, TAE_NONE, LIVESTOCK, LIVESTOCK, STR_ITEMS, CC_PIECE_GOODS),
MK( 5, CT_GOODS, 194, 8, 0x200, 6144, 5, 28, true, TAE_GOODS, GOODS, GOODS, STR_CRATES, CC_EXPRESS),
MK( 6, CT_GRAIN, 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, GRAIN, GRAIN, STR_TONS, CC_BULK),
MK( 6, CT_WHEAT, 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, WHEAT, WHEAT, STR_TONS, CC_BULK),
MK( 6, CT_MAIZE, 191, 16, 0x100, 4322, 4, 40, true, TAE_NONE, MAIZE, MAIZE, STR_TONS, CC_BULK),
/* Wood in temperate and arctic */
MK( 7, 'WOOD', 84, 16, 0x100, 5005, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
MK( 7, CT_WOOD, 84, 16, 0x100, 5005, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
/* Wood in subtropic */
MK( 7, 'WOOD', 84, 16, 0x100, 7964, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
MK( 8, 'IORE', 184, 16, 0x100, 5120, 9, 255, true, TAE_NONE, IRON_ORE, IRON_ORE, STR_TONS, CC_BULK),
MK( 9, 'STEL', 10, 16, 0x100, 5688, 7, 255, true, TAE_NONE, STEEL, STEEL, STR_TONS, CC_PIECE_GOODS),
MK( 10, 'VALU', 202, 2, 0x100, 7509, 1, 32, true, TAE_NONE, VALUABLES, VALUABLES, STR_BAGS, CC_ARMOURED),
MK( 10, 'GOLD', 202, 8, 0x100, 5802, 10, 40, true, TAE_NONE, GOLD, GOLD, STR_BAGS, CC_ARMOURED),
MK( 10, 'DIAM', 202, 2, 0x100, 5802, 10, 255, true, TAE_NONE, DIAMONDS, DIAMOND, STR_BAGS, CC_ARMOURED),
MK( 11, 'PAPR', 10, 16, 0x100, 5461, 7, 60, true, TAE_NONE, PAPER, PAPER, STR_TONS, CC_PIECE_GOODS),
MK( 12, 'FOOD', 48, 16, 0x100, 5688, 0, 30, true, TAE_FOOD, FOOD, FOOD, STR_TONS, CC_EXPRESS | CC_REFRIGERATED),
MK( 13, 'FRUT', 208, 16, 0x100, 4209, 0, 15, true, TAE_NONE, FRUIT, FRUIT, STR_TONS, CC_BULK | CC_REFRIGERATED),
MK( 14, 'CORE', 184, 16, 0x100, 4892, 12, 255, true, TAE_NONE, COPPER_ORE, COPPER_ORE, STR_TONS, CC_BULK),
MK( 15, 'WATR', 10, 16, 0x100, 4664, 20, 80, true, TAE_WATER, WATER, WATER, STR_LITERS, CC_LIQUID),
MK( 16, 'RUBR', 6, 16, 0x100, 4437, 2, 20, true, TAE_NONE, RUBBER, RUBBER, STR_LITERS, CC_LIQUID),
MK( 17, 'SUGR', 6, 16, 0x100, 4437, 20, 255, true, TAE_NONE, SUGAR, SUGAR, STR_TONS, CC_BULK),
MK( 18, 'TOYS', 174, 2, 0x100, 5574, 25, 255, true, TAE_NONE, TOYS, TOY, STR_ITEMS, CC_PIECE_GOODS),
MK( 19, 'BATT', 208, 4, 0x100, 4322, 2, 30, true, TAE_NONE, BATTERIES, BATTERY, STR_ITEMS, CC_PIECE_GOODS),
MK( 20, 'SWET', 194, 5, 0x200, 6144, 8, 40, true, TAE_GOODS, SWEETS, SWEETS, STR_BAGS, CC_EXPRESS),
MK( 21, 'TOFF', 191, 16, 0x100, 4778, 14, 60, true, TAE_NONE, TOFFEE, TOFFEE, STR_TONS, CC_BULK),
MK( 22, 'COLA', 84, 16, 0x100, 4892, 5, 75, true, TAE_NONE, COLA, COLA, STR_LITERS, CC_LIQUID),
MK( 23, 'CTCD', 184, 16, 0x100, 5005, 10, 25, true, TAE_NONE, CANDYFLOSS, CANDYFLOSS, STR_TONS, CC_BULK),
MK( 24, 'BUBL', 10, 1, 0x100, 5077, 20, 80, true, TAE_NONE, BUBBLES, BUBBLE, STR_ITEMS, CC_PIECE_GOODS),
MK( 25, 'PLST', 202, 16, 0x100, 4664, 30, 255, true, TAE_NONE, PLASTIC, PLASTIC, STR_LITERS, CC_LIQUID),
MK( 26, 'FZDR', 48, 2, 0x100, 6250, 30, 50, true, TAE_FOOD, FIZZY_DRINKS, FIZZY_DRINK, STR_ITEMS, CC_PIECE_GOODS),
MK( 7, CT_WOOD, 84, 16, 0x100, 7964, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
MK( 8, CT_IRON_ORE, 184, 16, 0x100, 5120, 9, 255, true, TAE_NONE, IRON_ORE, IRON_ORE, STR_TONS, CC_BULK),
MK( 9, CT_STEEL, 10, 16, 0x100, 5688, 7, 255, true, TAE_NONE, STEEL, STEEL, STR_TONS, CC_PIECE_GOODS),
MK( 10, CT_VALUABLES, 202, 2, 0x100, 7509, 1, 32, true, TAE_NONE, VALUABLES, VALUABLES, STR_BAGS, CC_ARMOURED),
MK( 10, CT_GOLD, 202, 8, 0x100, 5802, 10, 40, true, TAE_NONE, GOLD, GOLD, STR_BAGS, CC_ARMOURED),
MK( 10, CT_DIAMONDS, 202, 2, 0x100, 5802, 10, 255, true, TAE_NONE, DIAMONDS, DIAMOND, STR_BAGS, CC_ARMOURED),
MK( 11, CT_PAPER, 10, 16, 0x100, 5461, 7, 60, true, TAE_NONE, PAPER, PAPER, STR_TONS, CC_PIECE_GOODS),
MK( 12, CT_FOOD, 48, 16, 0x100, 5688, 0, 30, true, TAE_FOOD, FOOD, FOOD, STR_TONS, CC_EXPRESS | CC_REFRIGERATED),
MK( 13, CT_FRUIT, 208, 16, 0x100, 4209, 0, 15, true, TAE_NONE, FRUIT, FRUIT, STR_TONS, CC_BULK | CC_REFRIGERATED),
MK( 14, CT_COPPER_ORE, 184, 16, 0x100, 4892, 12, 255, true, TAE_NONE, COPPER_ORE, COPPER_ORE, STR_TONS, CC_BULK),
MK( 15, CT_WATER, 10, 16, 0x100, 4664, 20, 80, true, TAE_WATER, WATER, WATER, STR_LITERS, CC_LIQUID),
MK( 16, CT_RUBBER, 6, 16, 0x100, 4437, 2, 20, true, TAE_NONE, RUBBER, RUBBER, STR_LITERS, CC_LIQUID),
MK( 17, CT_SUGAR, 6, 16, 0x100, 4437, 20, 255, true, TAE_NONE, SUGAR, SUGAR, STR_TONS, CC_BULK),
MK( 18, CT_TOYS, 174, 2, 0x100, 5574, 25, 255, true, TAE_NONE, TOYS, TOY, STR_ITEMS, CC_PIECE_GOODS),
MK( 19, CT_BATTERIES, 208, 4, 0x100, 4322, 2, 30, true, TAE_NONE, BATTERIES, BATTERY, STR_ITEMS, CC_PIECE_GOODS),
MK( 20, CT_CANDY, 194, 5, 0x200, 6144, 8, 40, true, TAE_GOODS, SWEETS, SWEETS, STR_BAGS, CC_EXPRESS),
MK( 21, CT_TOFFEE, 191, 16, 0x100, 4778, 14, 60, true, TAE_NONE, TOFFEE, TOFFEE, STR_TONS, CC_BULK),
MK( 22, CT_COLA, 84, 16, 0x100, 4892, 5, 75, true, TAE_NONE, COLA, COLA, STR_LITERS, CC_LIQUID),
MK( 23, CT_COTTON_CANDY, 184, 16, 0x100, 5005, 10, 25, true, TAE_NONE, CANDYFLOSS, CANDYFLOSS, STR_TONS, CC_BULK),
MK( 24, CT_BUBBLES, 10, 1, 0x100, 5077, 20, 80, true, TAE_NONE, BUBBLES, BUBBLE, STR_ITEMS, CC_PIECE_GOODS),
MK( 25, CT_PLASTIC, 202, 16, 0x100, 4664, 30, 255, true, TAE_NONE, PLASTIC, PLASTIC, STR_LITERS, CC_LIQUID),
MK( 26, CT_FIZZY_DRINKS, 48, 2, 0x100, 6250, 30, 50, true, TAE_FOOD, FIZZY_DRINKS, FIZZY_DRINK, STR_ITEMS, CC_PIECE_GOODS),
/* Void slot in temperate */
MK(0xFF, 0, 1, 0, 0x100, 5688, 0, 30, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
MK(0xFF, CT_INVALID, 1, 0, 0x100, 5688, 0, 30, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
/* Void slot in arctic */
MK(0xFF, 0, 184, 0, 0x100, 5120, 9, 255, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
MK(0xFF, CT_INVALID, 184, 0, 0x100, 5120, 9, 255, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
};
/** Table of cargo types available in each climate, by default */
static const CargoLabel _default_climate_cargo[NUM_LANDSCAPE][NUM_ORIGINAL_CARGO] = {
{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'GRAI', 'WOOD', 'IORE', 'STEL', 'VALU', 33, },
{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'WHEA', 'WOOD', 34, 'PAPR', 'GOLD', 'FOOD', },
{ 'PASS', 'RUBR', 'MAIL', 4, 'FRUT', 'GOOD', 'MAIZ', 11, 'CORE', 'WATR', 'DIAM', 'FOOD', },
{ 'PASS', 'SUGR', 'MAIL', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR', },
static const std::variant<CargoLabel, int> _default_climate_cargo[NUM_LANDSCAPE][NUM_ORIGINAL_CARGO] = {
{ CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_IRON_ORE, CT_STEEL, CT_VALUABLES, 33, },
{ CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_WHEAT, CT_WOOD, 34, CT_PAPER, CT_GOLD, CT_FOOD, },
{ CT_PASSENGERS, CT_RUBBER, CT_MAIL, 4, CT_FRUIT, CT_GOODS, CT_MAIZE, 11, CT_COPPER_ORE, CT_WATER, CT_DIAMONDS, CT_FOOD, },
{ CT_PASSENGERS, CT_SUGAR, CT_MAIL, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, },
};

View File

@ -24,7 +24,7 @@
* @param f Bitmask of the climates
* @note the 5 between b and f is the load amount
*/
#define MT(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MT(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/**
* Writes the properties of a multiple-unit train into the EngineInfo struct.
@ -37,7 +37,7 @@
* @param f Bitmask of the climates
* @note the 5 between b and f is the load amount
*/
#define MM(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MM(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/**
* Writes the properties of a train carriage into the EngineInfo struct.
@ -50,7 +50,7 @@
* @see MT
* @note the 5 between b and f is the load amount
*/
#define MW(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MW(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/**
* Writes the properties of a road vehicle into the EngineInfo struct.
@ -63,7 +63,7 @@
* @param f Bitmask of the climates
* @note the 5 between b and f is the load amount
*/
#define MR(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MR(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/**
* Writes the properties of a ship into the EngineInfo struct.
@ -75,7 +75,7 @@
* @param f Bitmask of the climates
* @note the 10 between b and f is the load amount
*/
#define MS(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MS(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/**
* Writes the properties of an aeroplane into the EngineInfo struct.
@ -86,7 +86,7 @@
* @param e Bitmask of the climates
* @note the 20 between b and e is the load amount
*/
#define MA(a, b, c, d, e) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
#define MA(a, b, c, d, e) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, INVALID_CARGO, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, Ticks::CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
/* Climates
* T = Temperate
@ -102,33 +102,33 @@ static const EngineInfo _orig_engine_info[] = {
* | decay_speed cargo_type
* | | lifelength | climates
* | | | | | | */
MT( 1827, 20, 15, 30, 0 , T ), // 0 Kirby Paul Tank (Steam)
MT( 12784, 20, 22, 30, 0 , A|S ), // 1 MJS 250 (Diesel)
MT( 9497, 20, 20, 50, 0 , Y), // 2 Ploddyphut Choo-Choo
MT( 11688, 20, 20, 30, 0 , Y), // 3 Powernaut Choo-Choo
MT( 16802, 20, 20, 30, 0 , Y), // 4 Mightymover Choo-Choo
MT( 18993, 20, 20, 30, 0 , Y), // 5 Ploddyphut Diesel
MT( 20820, 20, 20, 30, 0 , Y), // 6 Powernaut Diesel
MT( 8766, 20, 20, 30, 0 , A|S ), // 7 Wills 2-8-0 (Steam)
MT( 5114, 20, 21, 30, 0 , T ), // 8 Chaney 'Jubilee' (Steam)
MT( 5479, 20, 20, 30, 0 , T ), // 9 Ginzu 'A4' (Steam)
MT( 12419, 20, 23, 25, 0 , T ), // 10 SH '8P' (Steam)
MT( 1827, 20, 15, 30, CT_NONE , T ), // 0 Kirby Paul Tank (Steam)
MT( 12784, 20, 22, 30, CT_NONE , A|S ), // 1 MJS 250 (Diesel)
MT( 9497, 20, 20, 50, CT_NONE , Y), // 2 Ploddyphut Choo-Choo
MT( 11688, 20, 20, 30, CT_NONE , Y), // 3 Powernaut Choo-Choo
MT( 16802, 20, 20, 30, CT_NONE , Y), // 4 Mightymover Choo-Choo
MT( 18993, 20, 20, 30, CT_NONE , Y), // 5 Ploddyphut Diesel
MT( 20820, 20, 20, 30, CT_NONE , Y), // 6 Powernaut Diesel
MT( 8766, 20, 20, 30, CT_NONE , A|S ), // 7 Wills 2-8-0 (Steam)
MT( 5114, 20, 21, 30, CT_NONE , T ), // 8 Chaney 'Jubilee' (Steam)
MT( 5479, 20, 20, 30, CT_NONE , T ), // 9 Ginzu 'A4' (Steam)
MT( 12419, 20, 23, 25, CT_NONE , T ), // 10 SH '8P' (Steam)
MM( 13149, 20, 12, 30, CT_PASSENGERS , T ), // 11 Manley-Morel DMU (Diesel)
MM( 23376, 20, 15, 35, CT_PASSENGERS , T ), // 12 'Dash' (Diesel)
MT( 14976, 20, 18, 28, 0 , T ), // 13 SH/Hendry '25' (Diesel)
MT( 14245, 20, 20, 30, 0 , T ), // 14 UU '37' (Diesel)
MT( 15341, 20, 22, 33, 0 , T ), // 15 Floss '47' (Diesel)
MT( 14976, 20, 20, 25, 0 , A|S ), // 16 CS 4000 (Diesel)
MT( 16437, 20, 20, 30, 0 , A|S ), // 17 CS 2400 (Diesel)
MT( 18993, 20, 22, 30, 0 , A|S ), // 18 Centennial (Diesel)
MT( 13880, 20, 22, 30, 0 , A|S ), // 19 Kelling 3100 (Diesel)
MM( 20454, 20, 22, 30, 0 , A|S ), // 20 Turner Turbo (Diesel)
MT( 16071, 20, 22, 30, 0 , A|S ), // 21 MJS 1000 (Diesel)
MT( 14976, 20, 18, 28, CT_NONE , T ), // 13 SH/Hendry '25' (Diesel)
MT( 14245, 20, 20, 30, CT_NONE , T ), // 14 UU '37' (Diesel)
MT( 15341, 20, 22, 33, CT_NONE , T ), // 15 Floss '47' (Diesel)
MT( 14976, 20, 20, 25, CT_NONE , A|S ), // 16 CS 4000 (Diesel)
MT( 16437, 20, 20, 30, CT_NONE , A|S ), // 17 CS 2400 (Diesel)
MT( 18993, 20, 22, 30, CT_NONE , A|S ), // 18 Centennial (Diesel)
MT( 13880, 20, 22, 30, CT_NONE , A|S ), // 19 Kelling 3100 (Diesel)
MM( 20454, 20, 22, 30, CT_NONE , A|S ), // 20 Turner Turbo (Diesel)
MT( 16071, 20, 22, 30, CT_NONE , A|S ), // 21 MJS 1000 (Diesel)
MT( 20820, 20, 20, 25, CT_MAIL , T ), // 22 SH '125' (Diesel)
MT( 16437, 20, 23, 30, 0 , T ), // 23 SH '30' (Electric)
MT( 19359, 20, 23, 80, 0 , T ), // 24 SH '40' (Electric)
MM( 23376, 20, 25, 30, 0 , T ), // 25 'T.I.M.' (Electric)
MM( 26298, 20, 25, 50, 0 , T ), // 26 'AsiaStar' (Electric)
MT( 16437, 20, 23, 30, CT_NONE , T ), // 23 SH '30' (Electric)
MT( 19359, 20, 23, 80, CT_NONE , T ), // 24 SH '40' (Electric)
MM( 23376, 20, 25, 30, CT_NONE , T ), // 25 'T.I.M.' (Electric)
MM( 26298, 20, 25, 50, CT_NONE , T ), // 26 'AsiaStar' (Electric)
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 27 Passenger Carriage
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 28 Mail Van
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 29 Coal Truck
@ -156,9 +156,9 @@ static const EngineInfo _orig_engine_info[] = {
MW( 1827, 20, 20, 50, CT_BATTERIES , Y), // 51 Battery Truck
MW( 1827, 20, 20, 50, CT_FIZZY_DRINKS, Y), // 52 Fizzy Drink Truck
MW( 1827, 20, 20, 50, CT_PLASTIC , Y), // 53 Plastic Truck
MT( 28490, 20, 20, 50, 0 , T|A|S ), // 54 'X2001' (Electric)
MT( 28490, 20, 20, 50, CT_NONE , T|A|S ), // 54 'X2001' (Electric)
MT( 31047, 20, 20, 50, CT_PASSENGERS , T|A|S ), // 55 'Millennium Z1' (Electric)
MT( 28855, 20, 20, 50, 0 , Y), // 56 Wizzowow Z99
MT( 28855, 20, 20, 50, CT_NONE , Y), // 56 Wizzowow Z99
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 57 Passenger Carriage
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 58 Mail Van
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 59 Coal Truck
@ -186,11 +186,11 @@ static const EngineInfo _orig_engine_info[] = {
MW( 1827, 20, 20, 50, CT_BATTERIES , Y), // 81 Battery Truck
MW( 1827, 20, 20, 50, CT_FIZZY_DRINKS, Y), // 82 Fizzy Drink Truck
MW( 1827, 20, 20, 50, CT_PLASTIC , Y), // 83 Plastic Truck
MT( 36525, 20, 20, 50, 0 , T|A|S ), // 84 Lev1 'Leviathan' (Electric)
MT( 39447, 20, 20, 50, 0 , T|A|S ), // 85 Lev2 'Cyclops' (Electric)
MT( 42004, 20, 20, 50, 0 , T|A|S ), // 86 Lev3 'Pegasus' (Electric)
MT( 42735, 20, 20, 50, 0 , T|A|S ), // 87 Lev4 'Chimaera' (Electric)
MT( 36891, 20, 20, 60, 0 , Y), // 88 Wizzowow Rocketeer
MT( 36525, 20, 20, 50, CT_NONE , T|A|S ), // 84 Lev1 'Leviathan' (Electric)
MT( 39447, 20, 20, 50, CT_NONE , T|A|S ), // 85 Lev2 'Cyclops' (Electric)
MT( 42004, 20, 20, 50, CT_NONE , T|A|S ), // 86 Lev3 'Pegasus' (Electric)
MT( 42735, 20, 20, 50, CT_NONE , T|A|S ), // 87 Lev4 'Chimaera' (Electric)
MT( 36891, 20, 20, 60, CT_NONE , Y), // 88 Wizzowow Rocketeer
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 89 Passenger Carriage
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 90 Mail Van
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 91 Coal Truck

View File

@ -1812,6 +1812,7 @@ static_assert(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
#define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \
{mnd, mxd, p, rc, bn, rr, mg, \
{ca1, ca2, ca3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
{cg1, cg2, cg3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
bf, ba, true, GRFFileProps(INVALID_HOUSE_ID), 0, {COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN}, \
16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0}

View File

@ -78,7 +78,11 @@ struct Town : TownPool::PoolItem<&_town_pool> {
std::string text; ///< General text with additional information.
inline byte GetPercentTransported(CargoID cid) const { return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1); }
inline byte GetPercentTransported(CargoID cid) const
{
if (!IsValidCargoID(cid)) return 0;
return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1);
}
StationList stations_near; ///< NOSAVE: List of nearby stations.

View File

@ -803,7 +803,7 @@ static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, CargoT
AddAcceptedCargoSetMask(accepts[1], GB(callback, 4, 4), acceptance, always_accepted);
if (_settings_game.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
/* The 'S' bit indicates food instead of goods */
AddAcceptedCargoSetMask(CT_FOOD, GB(callback, 8, 4), acceptance, always_accepted);
AddAcceptedCargoSetMask(GetCargoIDByLabel(CT_FOOD), GB(callback, 8, 4), acceptance, always_accepted);
} else {
AddAcceptedCargoSetMask(accepts[2], GB(callback, 8, 4), acceptance, always_accepted);
}

View File

@ -649,6 +649,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
v->cargo_type = e->GetDefaultCargoType();
assert(IsValidCargoID(v->cargo_type));
v->cargo_cap = rvi->capacity;
v->refit_cap = 0;
@ -773,6 +774,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engin
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
v->spritenum = rvi->image_index;
v->cargo_type = e->GetDefaultCargoType();
assert(IsValidCargoID(v->cargo_type));
v->cargo_cap = rvi->capacity;
v->refit_cap = 0;
v->last_station_visited = INVALID_STATION;

View File

@ -1954,7 +1954,8 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
}
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
if (!IsValidCargoID(cargo_type)) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
assert(IsValidCargoID(cargo_type));
if (e->u.rail.railveh_type == RAILVEH_WAGON) {
if (!CargoSpec::Get(cargo_type)->is_freight) {
if (parent_engine_type == INVALID_ENGINE) {
@ -1994,7 +1995,8 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
cargo_type = v->First()->cargo_type;
}
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
if (!IsValidCargoID(cargo_type)) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
assert(IsValidCargoID(cargo_type));
/* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
@ -2007,7 +2009,8 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
case VEH_SHIP:
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
if (!IsValidCargoID(cargo_type)) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
assert(IsValidCargoID(cargo_type));
return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
case VEH_AIRCRAFT:

View File

@ -167,7 +167,8 @@ std::tuple<CommandCost, VehicleID, uint, uint16_t, CargoArray> CmdBuildVehicle(D
} else {
refitted_capacity = e->GetDisplayDefaultCapacity(&refitted_mail_capacity);
cargo_capacities[default_cargo] = refitted_capacity;
cargo_capacities[CT_MAIL] = refitted_mail_capacity;
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) cargo_capacities[mail] = refitted_mail_capacity;
}
}
@ -410,7 +411,8 @@ static std::tuple<CommandCost, uint, uint16_t, CargoArray> RefitVehicle(Vehicle
total_mail_capacity += mail_capacity;
cargo_capacities[new_cid] += amount;
cargo_capacities[CT_MAIL] += mail_capacity;
CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) cargo_capacities[mail] += mail_capacity;
if (!refittable) continue;

View File

@ -947,7 +947,7 @@ struct RefitWindow : public Window {
Money money = cost.GetCost();
if (mail_capacity > 0) {
SetDParam(2, CT_MAIL);
SetDParam(2, GetCargoIDByLabel(CT_MAIL));
SetDParam(3, mail_capacity);
if (this->order != INVALID_VEH_ORDER_ID) {
/* No predictable cost */