OpenTTD Source 20250924-master-gbec4e71d53
newgrf_act3.cpp
Go to the documentation of this file.
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 */
7
10#include "../stdafx.h"
11
12#include "../debug.h"
13#include "../house.h"
14#include "../newgrf_engine.h"
15#include "../newgrf_badge.h"
16#include "../newgrf_badge_type.h"
17#include "../newgrf_cargo.h"
18#include "../newgrf_house.h"
19#include "../newgrf_station.h"
20#include "../industrytype.h"
21#include "../newgrf_canal.h"
22#include "../newgrf_airporttiles.h"
23#include "../newgrf_airport.h"
24#include "../newgrf_object.h"
25#include "../error.h"
26#include "../vehicle_base.h"
27#include "../road.h"
28#include "../newgrf_roadstop.h"
29#include "newgrf_bytereader.h"
31#include "newgrf_internal.h"
32
33#include "../safeguards.h"
34
35
36static CargoType TranslateCargo(GrfSpecFeature feature, uint8_t ctype)
37{
38 /* Special cargo types for purchase list and stations */
39 if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return CargoGRFFileProps::SG_DEFAULT_NA;
40 if (ctype == 0xFF) return CargoGRFFileProps::SG_PURCHASE;
41
42 auto cargo_list = GetCargoTranslationTable(*_cur_gps.grffile);
43
44 /* Check if the cargo type is out of bounds of the cargo translation table */
45 if (ctype >= cargo_list.size()) {
46 GrfMsg(1, "TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (unsigned int)_cur_gps.grffile->cargo_list.size() - 1);
47 return INVALID_CARGO;
48 }
49
50 /* Look up the cargo label from the translation table */
51 CargoLabel cl = cargo_list[ctype];
52 if (cl == CT_INVALID) {
53 GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
54 return INVALID_CARGO;
55 }
56
57 CargoType cargo_type = GetCargoTypeByLabel(cl);
58 if (!IsValidCargoType(cargo_type)) {
59 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));
60 return INVALID_CARGO;
61 }
62
63 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), cargo_type);
64 return cargo_type;
65}
66
67
68static bool IsValidGroupID(uint16_t groupid, std::string_view function)
69{
70 if (groupid > MAX_SPRITEGROUP || _cur_gps.spritegroups[groupid] == nullptr) {
71 GrfMsg(1, "{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
72 return false;
73 }
74
75 return true;
76}
77
78static void VehicleMapSpriteGroup(ByteReader &buf, GrfSpecFeature feature, uint8_t idcount)
79{
80 static std::vector<EngineID> last_engines; // Engine IDs are remembered in case the next action is a wagon override.
81 bool wagover = false;
82
83 /* Test for 'wagon override' flag */
84 if (HasBit(idcount, 7)) {
85 wagover = true;
86 /* Strip off the flag */
87 idcount = GB(idcount, 0, 7);
88
89 if (last_engines.empty()) {
90 GrfMsg(0, "VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
91 return;
92 }
93
94 GrfMsg(6, "VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
95 } else {
96 last_engines.resize(idcount);
97 }
98
99 std::vector<EngineID> engines;
100 engines.reserve(idcount);
101 for (uint i = 0; i < idcount; i++) {
102 Engine *e = GetNewEngine(_cur_gps.grffile, (VehicleType)feature, buf.ReadExtendedByte());
103 if (e == nullptr) {
104 /* No engine could be allocated?!? Deal with it. Okay,
105 * this might look bad. Also make sure this NewGRF
106 * gets disabled, as a half loaded one is bad. */
107 HandleChangeInfoResult("VehicleMapSpriteGroup", CIR_INVALID_ID, feature, 0);
108 return;
109 }
110
111 engines.push_back(e->index);
112 if (!wagover) last_engines[i] = engines[i];
113 }
114
115 uint8_t cidcount = buf.ReadByte();
116 for (uint c = 0; c < cidcount; c++) {
117 uint8_t ctype = buf.ReadByte();
118 uint16_t groupid = buf.ReadWord();
119 if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) continue;
120
121 GrfMsg(8, "VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
122
123 CargoType cargo_type = TranslateCargo(feature, ctype);
124 if (!IsValidCargoType(cargo_type)) continue;
125
126 for (uint i = 0; i < idcount; i++) {
127 EngineID engine = engines[i];
128
129 GrfMsg(7, "VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
130
131 if (wagover) {
132 SetWagonOverrideSprites(engine, cargo_type, _cur_gps.spritegroups[groupid], last_engines);
133 } else {
134 SetCustomEngineSprites(engine, cargo_type, _cur_gps.spritegroups[groupid]);
135 }
136 }
137 }
138
139 uint16_t groupid = buf.ReadWord();
140 if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
141
142 GrfMsg(8, "-- Default group id 0x{:04X}", groupid);
143
144 for (uint i = 0; i < idcount; i++) {
145 EngineID engine = engines[i];
146
147 if (wagover) {
148 SetWagonOverrideSprites(engine, CargoGRFFileProps::SG_DEFAULT, _cur_gps.spritegroups[groupid], last_engines);
149 } else {
150 SetCustomEngineSprites(engine, CargoGRFFileProps::SG_DEFAULT, _cur_gps.spritegroups[groupid]);
151 SetEngineGRF(engine, _cur_gps.grffile);
152 }
153 }
154}
155
158 virtual ~MapSpriteGroupHandler() {}
159 virtual void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) = 0;
160 virtual void MapDefault(uint16_t local_id, const SpriteGroup *group) = 0;
161};
162
164template <typename T> static auto *GetSpec(GRFFile *, uint16_t);
165
167template <typename T>
169 void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
170 {
171 if (cid != 0xFF) {
172 GrfMsg(1, "MapSpriteGroup: Invalid cargo bitnum {}, skipping.", cid);
173 } else if (T *spec = GetSpec<T>(_cur_gps.grffile, local_id); spec == nullptr) {
174 GrfMsg(1, "MapSpriteGroup: {} undefined, skipping.", local_id);
175 } else {
176 spec->grf_prop.SetSpriteGroup(StandardSpriteGroup::Purchase, group);
177 }
178 }
179
180 void MapDefault(uint16_t local_id, const SpriteGroup *group) override
181 {
182 if (T *spec = GetSpec<T>(_cur_gps.grffile, local_id); spec == nullptr) {
183 GrfMsg(1, "MapSpriteGroup: {} undefined, skipping.", local_id);
184 } else {
185 spec->grf_prop.SetSpriteGroup(StandardSpriteGroup::Default, group);
186 spec->grf_prop.SetGRFFile(_cur_gps.grffile);
187 spec->grf_prop.local_id = local_id;
188 }
189 }
190};
191
193template <typename T, typename Tclass>
195 void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
196 {
197 CargoType cargo_type = TranslateCargo(GSF_STATIONS, cid);
198 if (!IsValidCargoType(cargo_type)) return;
199
200 if (T *spec = GetSpec<T>(_cur_gps.grffile, local_id); spec == nullptr) {
201 GrfMsg(1, "MapSpriteGroup: {} undefined, skipping", local_id);
202 } else {
203 spec->grf_prop.SetSpriteGroup(cargo_type, group);
204 }
205 }
206
207 void MapDefault(uint16_t local_id, const SpriteGroup *group) override
208 {
209 if (T *spec = GetSpec<T>(_cur_gps.grffile, local_id); spec == nullptr) {
210 GrfMsg(1, "MapSpriteGroup: {} undefined, skipping", local_id);
211 } else if (spec->grf_prop.HasGrfFile()) {
212 GrfMsg(1, "MapSpriteGroup: {} mapped multiple times, skipping", local_id);
213 } else {
214 spec->grf_prop.SetSpriteGroup(CargoGRFFileProps::SG_DEFAULT, group);
215 spec->grf_prop.SetGRFFile(_cur_gps.grffile);
216 spec->grf_prop.local_id = local_id;
217 Tclass::Assign(spec);
218 }
219 }
220};
221
223 void MapSpecific(uint16_t, uint8_t, const SpriteGroup *) override {}
224
225 void MapDefault(uint16_t local_id, const SpriteGroup *group) override
226 {
227 if (local_id >= CF_END) {
228 GrfMsg(1, "CanalMapSpriteGroup: Canal subset {} out of range, skipping", local_id);
229 } else {
230 _water_feature[local_id].grffile = _cur_gps.grffile;
231 _water_feature[local_id].group = group;
232 }
233 }
234};
235
236template <> auto *GetSpec<StationSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->stations.size() ? grffile->stations[local_id].get() : nullptr; }
238
239template <> auto *GetSpec<HouseSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->housespec.size() ? grffile->housespec[local_id].get() : nullptr; }
241
242template <> auto *GetSpec<IndustrySpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->industryspec.size() ? grffile->industryspec[local_id].get() : nullptr; }
244
245template <> auto *GetSpec<IndustryTileSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->indtspec.size() ? grffile->indtspec[local_id].get() : nullptr; }
247
249 void MapSpecific(uint16_t, uint8_t, const SpriteGroup *) override {}
250
251 void MapDefault(uint16_t local_id, const SpriteGroup *group) override
252 {
253 if (local_id >= NUM_CARGO) {
254 GrfMsg(1, "CargoMapSpriteGroup: Cargo type {} out of range, skipping", local_id);
255 } else {
256 CargoSpec *cs = CargoSpec::Get(local_id);
257 cs->grffile = _cur_gps.grffile;
258 cs->group = group;
259 }
260 }
261};
262
263template <> auto *GetSpec<ObjectSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->objectspec.size() ? grffile->objectspec[local_id].get() : nullptr; }
265
267 void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
268 {
269 if (cid >= RTSG_END) return;
270
271 const auto &type_map = _cur_gps.grffile->railtype_map;
272 RailType railtype = local_id < std::size(type_map) ? type_map[local_id] : INVALID_RAILTYPE;
273 if (railtype == INVALID_RAILTYPE) return;
274
275 extern RailTypeInfo _railtypes[RAILTYPE_END];
276 RailTypeInfo &rti = _railtypes[railtype];
277 rti.grffile[cid] = _cur_gps.grffile;
278 rti.group[cid] = group;
279 }
280
281 void MapDefault(uint16_t, const SpriteGroup *) override {}
282};
283
284template <RoadTramType TRoadTramType>
286 void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
287 {
288 if (cid >= ROTSG_END) return;
289
290 const auto &type_map = (TRoadTramType == RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map;
291 RoadType roadtype = local_id < std::size(type_map) ? type_map[local_id] : INVALID_ROADTYPE;
292 if (roadtype == INVALID_ROADTYPE) return;
293
294 extern RoadTypeInfo _roadtypes[ROADTYPE_END];
295 RoadTypeInfo &rti = _roadtypes[roadtype];
296 rti.grffile[cid] = _cur_gps.grffile;
297 rti.group[cid] = group;
298 }
299
300 void MapDefault(uint16_t, const SpriteGroup *) override {}
301};
302
303template <> auto *GetSpec<AirportSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->airportspec.size() ? grffile->airportspec[local_id].get() : nullptr; }
305
306template <> auto *GetSpec<AirportTileSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->airtspec.size() ? grffile->airtspec[local_id].get() : nullptr; }
308
309template <> auto *GetSpec<RoadStopSpec>(GRFFile *grffile, uint16_t local_id) { return local_id < grffile->roadstops.size() ? grffile->roadstops[local_id].get() : nullptr; }
310struct RoadStopMapSpriteGroupHandler : CargoTypeMapSpriteGroupHandler<RoadStopSpec, RoadStopClass> {};
311
313 void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
314 {
315 if (cid >= GSF_END) return;
316
317 auto found = _cur_gps.grffile->badge_map.find(local_id);
318 if (found == std::end(_cur_gps.grffile->badge_map)) {
319 GrfMsg(1, "BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
320 } else {
321 auto &badge = *GetBadge(found->second);
322 badge.grf_prop.SetSpriteGroup(static_cast<GrfSpecFeature>(cid), group);
323 }
324 }
325
326 void MapDefault(uint16_t local_id, const SpriteGroup *group) override
327 {
328 auto found = _cur_gps.grffile->badge_map.find(local_id);
329 if (found == std::end(_cur_gps.grffile->badge_map)) {
330 GrfMsg(1, "BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
331 } else {
332 auto &badge = *GetBadge(found->second);
333 badge.grf_prop.SetSpriteGroup(GSF_DEFAULT, group);
334 badge.grf_prop.SetGRFFile(_cur_gps.grffile);
335 badge.grf_prop.local_id = local_id;
336 }
337 }
338};
339
340static void MapSpriteGroup(ByteReader &buf, uint8_t idcount, MapSpriteGroupHandler &&handler)
341{
342 /* Read IDs to map into memory. */
343 std::array<uint16_t, 256> local_ids_buffer;
344 for (uint i = 0; i != idcount; ++i) {
345 local_ids_buffer[i] = buf.ReadExtendedByte();
346 }
347 std::span<const uint16_t> local_ids{local_ids_buffer.begin(), idcount};
348
349 /* Handle specific mappings. */
350 uint8_t cidcount = buf.ReadByte();
351 for (uint c = 0; c != cidcount; ++c) {
352 uint8_t cid = buf.ReadByte();
353 uint16_t groupid = buf.ReadWord();
354 if (!IsValidGroupID(groupid, "MapSpriteGroup")) continue;
355 for (uint16_t local_id : local_ids) {
356 handler.MapSpecific(local_id, cid, _cur_gps.spritegroups[groupid]);
357 }
358 }
359
360 /* Handle default mapping. */
361 uint16_t groupid = buf.ReadWord();
362 if (!IsValidGroupID(groupid, "MapSpriteGroup")) return;
363 for (uint16_t local_id : local_ids) {
364 handler.MapDefault(local_id, _cur_gps.spritegroups[groupid]);
365 }
366}
367
368/* Action 0x03 */
369static void FeatureMapSpriteGroup(ByteReader &buf)
370{
371 /* <03> <feature> <n-id> <ids>... <num-cid> [<cargo-type> <cid>]... <def-cid>
372 * id-list := [<id>] [id-list]
373 * cargo-list := <cargo-type> <cid> [cargo-list]
374 *
375 * B feature see action 0
376 * B n-id bits 0-6: how many IDs this definition applies to
377 * bit 7: if set, this is a wagon override definition (see below)
378 * E ids the IDs for which this definition applies
379 * B num-cid number of cargo IDs (sprite group IDs) in this definition
380 * can be zero, in that case the def-cid is used always
381 * B cargo-type type of this cargo type (e.g. mail=2, wood=7, see below)
382 * W cid cargo ID (sprite group ID) for this type of cargo
383 * W def-cid default cargo ID (sprite group ID) */
384
385 GrfSpecFeature feature{buf.ReadByte()};
386 uint8_t idcount = buf.ReadByte();
387
388 if (feature >= GSF_END) {
389 GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
390 return;
391 }
392
393 /* If idcount is zero, this is a feature callback */
394 if (idcount == 0) {
395 /* Skip number of cargo ids? */
396 buf.ReadByte();
397 uint16_t groupid = buf.ReadWord();
398 if (!IsValidGroupID(groupid, "FeatureMapSpriteGroup")) return;
399
400 GrfMsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
401
402 AddGenericCallback(feature, _cur_gps.grffile, _cur_gps.spritegroups[groupid]);
403 return;
404 }
405
406 /* Mark the feature as used by the grf (generic callbacks do not count) */
407 _cur_gps.grffile->grf_features.Set(feature);
408
409 GrfMsg(6, "FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
410
411 switch (feature) {
412 case GSF_TRAINS:
413 case GSF_ROADVEHICLES:
414 case GSF_SHIPS:
415 case GSF_AIRCRAFT: VehicleMapSpriteGroup(buf, feature, idcount); return;
416 case GSF_CANALS: MapSpriteGroup(buf, idcount, CanalMapSpriteGroupHandler{}); return;
417 case GSF_STATIONS: MapSpriteGroup(buf, idcount, StationMapSpriteGroupHandler{}); return;
418 case GSF_HOUSES: MapSpriteGroup(buf, idcount, TownHouseMapSpriteGroupHandler{}); return;
419 case GSF_INDUSTRIES: MapSpriteGroup(buf, idcount, IndustryMapSpriteGroupHandler{}); return;
420 case GSF_INDUSTRYTILES: MapSpriteGroup(buf, idcount, IndustryTileMapSpriteGroupHandler{}); return;
421 case GSF_CARGOES: MapSpriteGroup(buf, idcount, CargoMapSpriteGroupHandler{}); return;
422 case GSF_AIRPORTS: MapSpriteGroup(buf, idcount, AirportMapSpriteGroupHandler{}); return;
423 case GSF_OBJECTS: MapSpriteGroup(buf, idcount, ObjectMapSpriteGroupHandler{}); return;
424 case GSF_RAILTYPES: MapSpriteGroup(buf, idcount, RailTypeMapSpriteGroupHandler{}); return;
425 case GSF_ROADTYPES: MapSpriteGroup(buf, idcount, RoadTypeMapSpriteGroupHandler<RTT_ROAD>{}); return;
426 case GSF_TRAMTYPES: MapSpriteGroup(buf, idcount, RoadTypeMapSpriteGroupHandler<RTT_TRAM>{}); return;
427 case GSF_AIRPORTTILES: MapSpriteGroup(buf, idcount, AirportTileMapSpriteGroupHandler{}); return;
428 case GSF_ROADSTOPS: MapSpriteGroup(buf, idcount, RoadStopMapSpriteGroupHandler{}); return;
429 case GSF_BADGES: MapSpriteGroup(buf, idcount, BadgeMapSpriteGroupHandler{}); return;
430
431 default:
432 GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
433 return;
434 }
435}
436
437template <> void GrfActionHandler<0x03>::FileScan(ByteReader &) { }
438template <> void GrfActionHandler<0x03>::SafetyScan(ByteReader &buf) { GRFUnsafe(buf); }
439template <> void GrfActionHandler<0x03>::LabelScan(ByteReader &) { }
440template <> void GrfActionHandler<0x03>::Init(ByteReader &) { }
441template <> void GrfActionHandler<0x03>::Reserve(ByteReader &) { }
442template <> void GrfActionHandler<0x03>::Activation(ByteReader &buf) { FeatureMapSpriteGroup(buf); }
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
Definition cargo_type.h:72
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:75
constexpr Timpl & Set()
Set all bits.
Class to read from a NewGRF file.
uint16_t ReadWord()
Read a single Word (16 bits).
uint16_t ReadExtendedByte()
Read a single Extended Byte (8 or 16 bits).
uint8_t ReadByte()
Read a single byte (8 bits).
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:115
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
Definition rail.h:269
const GRFFile * grffile[RTSG_END]
NewGRF providing the Action3 for the railtype.
Definition rail.h:264
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
Definition road.h:180
const GRFFile * grffile[ROTSG_END]
NewGRF providing the Action3 for the roadtype.
Definition road.h:175
std::span< const CargoLabel > GetCargoTranslationTable(const GRFFile &grffile)
Get the cargo translation table to use for the given GRF file.
Definition newgrf.cpp:518
void GRFUnsafe(ByteReader &)
Set the current NewGRF as unsafe for static use.
Definition newgrf.cpp:370
Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access)
Returns the engine associated to a certain internal_id, resp.
Definition newgrf.cpp:211
GrfSpecFeature
Definition newgrf.h:69
@ GSF_DEFAULT
Unspecified feature, default badge.
Definition newgrf.h:94
static auto * GetSpec(GRFFile *, uint16_t)
Specializable function to retrieve a NewGRF spec of a particular type.
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
NewGRF buffer reader definition.
std::array< WaterFeature, CF_END > _water_feature
Table of canal 'feature' sprite groups.
@ Purchase
Used before an entity exists.
@ Default
Default type used when no more-specific group matches.
void SetEngineGRF(EngineID engine, const GRFFile *file)
Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters etc during a game.
void AddGenericCallback(GrfSpecFeature feature, const GRFFile *file, const SpriteGroup *group)
Add a generic feature callback sprite group to the appropriate feature list.
NewGRF internal processing state.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
static constexpr uint MAX_SPRITEGROUP
Maximum GRF-local ID for a spritegroup.
NewGRF internal processing state for vehicles.
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
@ RAILTYPE_END
Used for iterations.
Definition rail_type.h:31
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:27
static constexpr CargoType SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoType SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoType SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
Specification of a cargo type.
Definition cargotype.h:74
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
Definition cargotype.h:137
const struct GRFFile * grffile
NewGRF where group belongs to.
Definition cargotype.h:99
Common handler for mapping sprite groups for features which support cargo-type specific sprites.
Dynamic data of a loaded NewGRF.
Definition newgrf.h:115
std::vector< CargoLabel > cargo_list
Cargo translation table (local ID -> label)
Definition newgrf.h:136
GrfSpecFeatures grf_features
Bitset of GrfSpecFeature the grf uses.
Definition newgrf.h:158
GRF action handler.
GRFFile * grffile
Currently processed GRF file.
Handler interface for mapping sprite groups.
Tindex index
Index of this pool item.
Common handler for mapping sprite groups for features which only support "Purchase" and "Default" spr...
VehicleType
Available vehicle types.