diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index e6c979f872..7ad284b5b7 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -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; diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 1f3a8a54b2..110acb3371 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -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 diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 02e86115e2..467b9c0bed 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -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; } diff --git a/src/cargo_type.h b/src/cargo_type.h index 871f958790..5a50a0002d 100644 --- a/src/cargo_type.h +++ b/src/cargo_type.h @@ -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; /** * 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; } diff --git a/src/cargotype.cpp b/src/cargotype.cpp index 7181782ec4..bca7e368b5 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -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 _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(cl)) { /* Copy the default cargo by index. */ - *insert = _default_cargo[cl]; + *insert = _default_cargo[std::get(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(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. diff --git a/src/cargotype.h b/src/cargotype.h index 4c83c3ceba..81758c8b42 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -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 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(); diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 5d8515c6ce..797b8e8ebe 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -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' : '-', diff --git a/src/engine.cpp b/src/engine.cpp index c46f7bb843..979c6a7e31 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -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; diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index bbf5ba5626..4742e6e234 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -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; diff --git a/src/engine_type.h b/src/engine_type.h index 7716fd92e7..daaad1a7f8 100644 --- a/src/engine_type.h +++ b/src/engine_type.h @@ -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 diff --git a/src/house.h b/src/house.h index 4831e289ac..c3308ea59b 100644 --- a/src/house.h +++ b/src/house.h @@ -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) diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 7a4fc70d42..a8752d5208 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -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(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(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); } diff --git a/src/industrytype.h b/src/industrytype.h index 07a3d36bb7..b71b7d29b3 100644 --- a/src/industrytype.h +++ b/src/industrytype.h @@ -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 accepts_cargo; ///< Cargo accepted by this tile + std::array accepts_cargo_label; std::array 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 diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 22455baf61..e3bd89a372 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -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 -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 &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(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(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]); + } } } diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index ffd1c44269..97eaebec87 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -30,7 +30,7 @@ GrfSpecFeature CargoResolverObject::GetFeature() const uint32_t CargoResolverObject::GetDebugID() const { - return this->cargospec->label; + return this->cargospec->label.base(); } /** diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index 57a68941a8..0bd4924e34 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -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(this->t->cache.num_houses); case 0xB9: return this->t->growth_rate / Ticks::TOWN_GROWTH_TICKS; - case 0xBA: return ClampTo(this->t->supplied[CT_PASSENGERS].new_max); - case 0xBB: return GB(ClampTo(this->t->supplied[CT_PASSENGERS].new_max), 8, 8); - case 0xBC: return ClampTo(this->t->supplied[CT_MAIL].new_max); - case 0xBD: return GB(ClampTo(this->t->supplied[CT_MAIL].new_max), 8, 8); - case 0xBE: return ClampTo(this->t->supplied[CT_PASSENGERS].new_act); - case 0xBF: return GB(ClampTo(this->t->supplied[CT_PASSENGERS].new_act), 8, 8); - case 0xC0: return ClampTo(this->t->supplied[CT_MAIL].new_act); - case 0xC1: return GB(ClampTo(this->t->supplied[CT_MAIL].new_act), 8, 8); - case 0xC2: return ClampTo(this->t->supplied[CT_PASSENGERS].old_max); - case 0xC3: return GB(ClampTo(this->t->supplied[CT_PASSENGERS].old_max), 8, 8); - case 0xC4: return ClampTo(this->t->supplied[CT_MAIL].old_max); - case 0xC5: return GB(ClampTo(this->t->supplied[CT_MAIL].old_max), 8, 8); - case 0xC6: return ClampTo(this->t->supplied[CT_PASSENGERS].old_act); - case 0xC7: return GB(ClampTo(this->t->supplied[CT_PASSENGERS].old_act), 8, 8); - case 0xC8: return ClampTo(this->t->supplied[CT_MAIL].old_act); - case 0xC9: return GB(ClampTo(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(this->t->supplied[cid].new_max) : 0; + case 0xBB: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].new_max), 8, 8) : 0; + case 0xBC: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].new_max) : 0; + case 0xBD: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].new_max), 8, 8) : 0; + case 0xBE: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].new_act) : 0; + case 0xBF: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].new_act), 8, 8) : 0; + case 0xC0: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].new_act) : 0; + case 0xC1: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].new_act), 8, 8) : 0; + case 0xC2: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].old_max) : 0; + case 0xC3: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].old_max), 8, 8) : 0; + case 0xC4: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].old_max) : 0; + case 0xC5: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].old_max), 8, 8) : 0; + case 0xC6: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].old_act) : 0; + case 0xC7: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo(this->t->supplied[cid].old_act), 8, 8) : 0; + case 0xC8: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].old_act) : 0; + case 0xC9: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo(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; diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index ab4907eb1f..3e2654a853 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -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()); } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 65ccd3a17d..6aace6b3e9 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -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; diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 57510b739a..8448367c9e 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -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; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 0907b2464f..67409c6449 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -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), diff --git a/src/script/api/script_cargo.cpp b/src/script/api/script_cargo.cpp index 4f6ab51f67..6f86b6f9e2 100644 --- a/src/script/api/script_cargo.cpp +++ b/src/script/api/script_cargo.cpp @@ -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; } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 920a881214..dc57b19125 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -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; diff --git a/src/table/build_industry.h b/src/table/build_industry.h index 43881e8309..f8683e8b09 100644 --- a/src/table/build_industry.h +++ b/src/table/build_industry.h @@ -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), diff --git a/src/table/cargo_const.h b/src/table/cargo_const.h index f182e039df..657dd323d6 100644 --- a/src/table/cargo_const.h +++ b/src/table/cargo_const.h @@ -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 _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, }, }; diff --git a/src/table/engines.h b/src/table/engines.h index ec02f6b908..9bf442fe11 100644 --- a/src/table/engines.h +++ b/src/table/engines.h @@ -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 diff --git a/src/table/town_land.h b/src/table/town_land.h index d2d991c328..2ba1bc173b 100644 --- a/src/table/town_land.h +++ b/src/table/town_land.h @@ -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} diff --git a/src/town.h b/src/town.h index 75182c285a..f096bfa530 100644 --- a/src/town.h +++ b/src/town.h @@ -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. diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index a2c3df76fb..ffa3d746b3 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -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); } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index da95bfc218..1a3d74b00b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -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; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 8ac20d9b14..d4a50101c9 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -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: diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index eb8da1ebb1..4817627e8c 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -167,7 +167,8 @@ std::tuple 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 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; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index b07e978f64..b7f117e9c1 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -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 */