Fix: Don't allow right-click to close world generation progress window. (#13084)
[openttd-github.git] / src / cargotype.h
blob4d7d92c7644332c988200b2576214f492186cdff
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /** @file cargotype.h Types/functions related to cargoes. */
10 #ifndef CARGOTYPE_H
11 #define CARGOTYPE_H
13 #include "economy_type.h"
14 #include "cargo_type.h"
15 #include "gfx_type.h"
16 #include "strings_type.h"
17 #include "landscape_type.h"
18 #include "core/bitmath_func.hpp"
20 /** Town growth effect when delivering cargo. */
21 enum TownAcceptanceEffect : uint8_t {
22 TAE_BEGIN = 0,
23 TAE_NONE = TAE_BEGIN, ///< Cargo has no effect.
24 TAE_PASSENGERS, ///< Cargo behaves passenger-like.
25 TAE_MAIL, ///< Cargo behaves mail-like.
26 TAE_GOODS, ///< Cargo behaves goods/candy-like.
27 TAE_WATER, ///< Cargo behaves water-like.
28 TAE_FOOD, ///< Cargo behaves food/fizzy-drinks-like.
29 TAE_END, ///< End of town effects.
30 NUM_TAE = TAE_END, ///< Amount of town effects.
33 /** Town effect when producing cargo. */
34 enum TownProductionEffect : uint8_t {
35 TPE_NONE, ///< Town will not produce this cargo type.
36 TPE_PASSENGERS, ///< Cargo behaves passenger-like for production.
37 TPE_MAIL, ///< Cargo behaves mail-like for production.
38 NUM_TPE,
40 /**
41 * Invalid town production effect. Used as a sentinel to indicate if a NewGRF has explicitly set an effect.
42 * This does not 'exist' after cargo types are finalised.
44 INVALID_TPE,
47 /** Cargo classes. */
48 enum CargoClass : uint16_t {
49 CC_NOAVAILABLE = 0, ///< No cargo class has been specified
50 CC_PASSENGERS = 1 << 0, ///< Passengers
51 CC_MAIL = 1 << 1, ///< Mail
52 CC_EXPRESS = 1 << 2, ///< Express cargo (Goods, Food, Candy, but also possible for passengers)
53 CC_ARMOURED = 1 << 3, ///< Armoured cargo (Valuables, Gold, Diamonds)
54 CC_BULK = 1 << 4, ///< Bulk cargo (Coal, Grain etc., Ores, Fruit)
55 CC_PIECE_GOODS = 1 << 5, ///< Piece goods (Livestock, Wood, Steel, Paper)
56 CC_LIQUID = 1 << 6, ///< Liquids (Oil, Water, Rubber)
57 CC_REFRIGERATED = 1 << 7, ///< Refrigerated cargo (Food, Fruit)
58 CC_HAZARDOUS = 1 << 8, ///< Hazardous cargo (Nuclear Fuel, Explosives, etc.)
59 CC_COVERED = 1 << 9, ///< Covered/Sheltered Freight (Transportation in Box Vans, Silo Wagons, etc.)
60 CC_SPECIAL = 1 << 15, ///< Special bit used for livery refit tricks instead of normal cargoes.
63 /** Bitmask of cargo classes. */
64 using CargoClasses = uint16_t;
66 static const uint8_t INVALID_CARGO_BITNUM = 0xFF; ///< Constant representing invalid cargo
68 static const uint TOWN_PRODUCTION_DIVISOR = 256;
70 /** Specification of a cargo type. */
71 struct CargoSpec {
72 CargoLabel label; ///< Unique label of the cargo type.
73 uint8_t bitnum = INVALID_CARGO_BITNUM; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec.
74 uint8_t legend_colour;
75 uint8_t rating_colour;
76 uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
77 uint16_t multiplier = 0x100; ///< Capacity multiplier for vehicles. (8 fractional bits)
78 CargoClasses classes; ///< Classes of this cargo type. @see CargoClass
79 int32_t initial_payment; ///< Initial payment rate before inflation is applied.
80 uint8_t transit_periods[2];
82 bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier).
83 TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
84 TownProductionEffect town_production_effect = INVALID_TPE; ///< The effect on town cargo production.
85 uint16_t town_production_multiplier = TOWN_PRODUCTION_DIVISOR; ///< Town production multipler, if commanded by TownProductionEffect.
86 uint8_t callback_mask; ///< Bitmask of cargo callbacks that have to be called
88 StringID name; ///< Name of this type of cargo.
89 StringID name_single; ///< Name of a single entity of this type of cargo.
90 StringID units_volume; ///< Name of a single unit of cargo of this type.
91 StringID quantifier; ///< Text for multiple units of cargo of this type.
92 StringID abbrev; ///< Two letter abbreviation for this cargo type.
94 SpriteID sprite; ///< Icon to display this cargo type, may be \c 0xFFF (which means to resolve an action123 chain).
96 const struct GRFFile *grffile; ///< NewGRF where #group belongs to.
97 const struct SpriteGroup *group;
99 Money current_payment;
102 * Determines index of this cargospec
103 * @return index (in the CargoSpec::array array)
105 inline CargoID Index() const
107 return this - CargoSpec::array;
111 * Tests for validity of this cargospec
112 * @return is this cargospec valid?
113 * @note assert(cs->IsValid()) can be triggered when GRF config is modified
115 inline bool IsValid() const
117 return this->bitnum != INVALID_CARGO_BITNUM;
121 * Total number of cargospecs, both valid and invalid
122 * @return length of CargoSpec::array
124 static inline size_t GetArraySize()
126 return lengthof(CargoSpec::array);
130 * Retrieve cargo details for the given cargo ID
131 * @param index ID of cargo
132 * @pre index is a valid cargo ID
134 static inline CargoSpec *Get(size_t index)
136 assert(index < lengthof(CargoSpec::array));
137 return &CargoSpec::array[index];
140 SpriteID GetCargoIcon() const;
142 inline uint64_t WeightOfNUnits(uint32_t n) const
144 return n * this->weight / 16u;
147 uint64_t WeightOfNUnitsInTrain(uint32_t n) const;
150 * Iterator to iterate all valid CargoSpec
152 struct Iterator {
153 typedef CargoSpec value_type;
154 typedef CargoSpec *pointer;
155 typedef CargoSpec &reference;
156 typedef size_t difference_type;
157 typedef std::forward_iterator_tag iterator_category;
159 explicit Iterator(size_t index) : index(index)
161 this->ValidateIndex();
164 bool operator==(const Iterator &other) const { return this->index == other.index; }
165 bool operator!=(const Iterator &other) const { return !(*this == other); }
166 CargoSpec * operator*() const { return CargoSpec::Get(this->index); }
167 Iterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
169 private:
170 size_t index;
171 void ValidateIndex() { while (this->index < CargoSpec::GetArraySize() && !(CargoSpec::Get(this->index)->IsValid())) this->index++; }
175 * Iterable ensemble of all valid CargoSpec
177 struct IterateWrapper {
178 size_t from;
179 IterateWrapper(size_t from = 0) : from(from) {}
180 Iterator begin() { return Iterator(this->from); }
181 Iterator end() { return Iterator(CargoSpec::GetArraySize()); }
182 bool empty() { return this->begin() == this->end(); }
186 * Returns an iterable ensemble of all valid CargoSpec
187 * @param from index of the first CargoSpec to consider
188 * @return an iterable ensemble of all valid CargoSpec
190 static IterateWrapper Iterate(size_t from = 0) { return IterateWrapper(from); }
192 /** List of cargo specs for each Town Product Effect. */
193 static std::array<std::vector<const CargoSpec *>, NUM_TPE> town_production_cargoes;
195 private:
196 static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
197 static inline std::map<CargoLabel, CargoID> label_map{}; ///< Translation map from CargoLabel to Cargo ID.
199 friend void SetupCargoForClimate(LandscapeID l);
200 friend void BuildCargoLabelMap();
201 friend inline CargoID GetCargoIDByLabel(CargoLabel ct);
202 friend void FinaliseCargoArray();
205 extern CargoTypes _cargo_mask;
206 extern CargoTypes _standard_cargo_mask;
208 void SetupCargoForClimate(LandscapeID l);
209 bool IsDefaultCargo(CargoID cid);
210 void BuildCargoLabelMap();
212 inline CargoID GetCargoIDByLabel(CargoLabel label)
214 auto found = CargoSpec::label_map.find(label);
215 if (found != std::end(CargoSpec::label_map)) return found->second;
216 return INVALID_CARGO;
219 Dimension GetLargestCargoIconSize();
221 void InitializeSortedCargoSpecs();
222 extern std::array<uint8_t, NUM_CARGO> _sorted_cargo_types;
223 extern std::vector<const CargoSpec *> _sorted_cargo_specs;
224 extern std::span<const CargoSpec *> _sorted_standard_cargo_specs;
227 * Does cargo \a c have cargo class \a cc?
228 * @param c Cargo type.
229 * @param cc Cargo class.
230 * @return The type fits in the class.
232 inline bool IsCargoInClass(CargoID c, CargoClass cc)
234 return (CargoSpec::Get(c)->classes & cc) != 0;
237 using SetCargoBitIterator = SetBitIterator<CargoID, CargoTypes>;
239 /** Comparator to sort CargoID by according to desired order. */
240 struct CargoIDComparator {
241 bool operator() (const CargoID &lhs, const CargoID &rhs) const { return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs]; }
244 #endif /* CARGOTYPE_H */