diff --git a/src/cargotype.cpp b/src/cargotype.cpp index dafb4e1164..7181782ec4 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -22,6 +22,7 @@ #include "safeguards.h" CargoSpec CargoSpec::array[NUM_CARGO]; +std::array, NUM_TPE> CargoSpec::town_production_cargoes{}; /** * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes. @@ -192,6 +193,7 @@ static bool CargoSpecClassSorter(const CargoSpec * const &a, const CargoSpec * c /** Initialize the list of sorted cargo specifications. */ void InitializeSortedCargoSpecs() { + for (auto &tpc : CargoSpec::town_production_cargoes) tpc.clear(); _sorted_cargo_specs.clear(); /* Add each cargo spec to the list, and determine the largest cargo icon size. */ for (const CargoSpec *cargo : CargoSpec::Iterate()) { @@ -210,6 +212,8 @@ void InitializeSortedCargoSpecs() _standard_cargo_mask = 0; uint8_t nb_standard_cargo = 0; for (const auto &cargo : _sorted_cargo_specs) { + assert(cargo->town_production_effect != INVALID_TPE); + CargoSpec::town_production_cargoes[cargo->town_production_effect].push_back(cargo); if (cargo->classes & CC_SPECIAL) break; nb_standard_cargo++; SetBit(_standard_cargo_mask, cargo->Index()); diff --git a/src/cargotype.h b/src/cargotype.h index f6b638f3af..06e2661461 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -33,6 +33,20 @@ enum TownAcceptanceEffect : byte { NUM_TAE = TAE_END, ///< Amount of town effects. }; +/** Town effect when producing cargo. */ +enum TownProductionEffect : byte { + TPE_NONE, ///< Town will not produce this cargo type. + TPE_PASSENGERS, ///< Cargo behaves passenger-like for production. + TPE_MAIL, ///< Cargo behaves mail-like for production. + NUM_TPE, + + /** + * Invalid town production effect. Used as a sentinel to indicate if a NewGRF has explicitly set an effect. + * This does not 'exist' after cargo types are finalised. + */ + INVALID_TPE, +}; + /** Cargo classes. */ enum CargoClass { CC_NOAVAILABLE = 0, ///< No cargo class has been specified @@ -65,6 +79,7 @@ struct CargoSpec { bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier). TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies. + TownProductionEffect town_production_effect{INVALID_TPE}; ///< The effect on town cargo production. uint8_t callback_mask; ///< Bitmask of cargo callbacks that have to be called StringID name; ///< Name of this type of cargo. @@ -171,6 +186,9 @@ struct CargoSpec { */ static IterateWrapper Iterate(size_t from = 0) { return IterateWrapper(from); } + /** List of cargo specs for each Town Product Effect. */ + static std::array, NUM_TPE> town_production_cargoes; + private: static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 659e2de913..34246726a1 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -9186,6 +9186,14 @@ static void FinaliseEngineArray() 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; + } + } if (!cs.IsValid()) { cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO; cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY; diff --git a/src/table/cargo_const.h b/src/table/cargo_const.h index 52f615d2ae..b7fc6213fd 100644 --- a/src/table/cargo_const.h +++ b/src/table/cargo_const.h @@ -44,7 +44,7 @@ * @param classes Classes of this cargo type. @see CargoClass */ #define MK(bt, label, colour, weight, mult, ip, td1, td2, freight, tae, str_plural, str_singular, str_volume, classes) \ - {label, bt, colour, colour, weight, mult, classes, ip, {td1, td2}, freight, tae, 0, \ + {label, bt, colour, colour, weight, mult, classes, ip, {td1, td2}, freight, tae, INVALID_TPE, 0, \ MK_STR_CARGO_PLURAL(str_plural), MK_STR_CARGO_SINGULAR(str_singular), str_volume, MK_STR_QUANTITY(str_plural), MK_STR_ABBREV(str_plural), \ MK_SPRITE(str_plural), nullptr, nullptr, 0}