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);
53 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
57 CargoType cargo_type = GetCargoTypeByLabel(cl);
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));
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);
68static bool IsValidGroupID(uint16_t groupid, std::string_view function)
70 if (groupid >
MAX_SPRITEGROUP || _cur_gps.spritegroups[groupid] ==
nullptr) {
71 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
80 static std::vector<EngineID> last_engines;
87 idcount =
GB(idcount, 0, 7);
89 if (last_engines.empty()) {
90 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
94 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
96 last_engines.resize(idcount);
99 std::vector<EngineID> engines;
100 engines.reserve(idcount);
101 for (uint i = 0; i < idcount; i++) {
107 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, feature, 0);
111 engines.push_back(e->index);
112 if (!wagover) last_engines[i] = engines[i];
116 for (uint c = 0; c < cidcount; c++) {
119 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
121 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
123 CargoType cargo_type = TranslateCargo(feature, ctype);
126 for (uint i = 0; i < idcount; i++) {
129 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
132 SetWagonOverrideSprites(engine, cargo_type, _cur_gps.spritegroups[groupid], last_engines);
134 SetCustomEngineSprites(engine, cargo_type, _cur_gps.spritegroups[groupid]);
140 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
142 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
144 for (uint i = 0; i < idcount; i++) {
185 GrfMsg(1,
"MapSpriteGroup: Invalid cargo bitnum {}, skipping.", cid);
186 }
else if (T *spec =
GetSpec<T>(_cur_gps.grffile, local_id); spec ==
nullptr) {
187 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping.", local_id);
195 if (T *spec =
GetSpec<T>(_cur_gps.grffile, local_id); spec ==
nullptr) {
196 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping.", local_id);
199 spec->grf_prop.SetGRFFile(_cur_gps.grffile);
200 spec->grf_prop.local_id = local_id;
206template <
typename T,
typename T
class>
210 CargoType cargo_type = TranslateCargo(GSF_STATIONS, cid);
213 if (T *spec =
GetSpec<T>(_cur_gps.grffile, local_id); spec ==
nullptr) {
214 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping", local_id);
216 spec->grf_prop.SetSpriteGroup(cargo_type, group);
222 if (T *spec =
GetSpec<T>(_cur_gps.grffile, local_id); spec ==
nullptr) {
223 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping", local_id);
224 }
else if (spec->grf_prop.HasGrfFile()) {
225 GrfMsg(1,
"MapSpriteGroup: {} mapped multiple times, skipping", local_id);
228 spec->grf_prop.SetGRFFile(_cur_gps.grffile);
229 spec->grf_prop.local_id = local_id;
230 Tclass::Assign(spec);
240 if (local_id >= CF_END) {
241 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", local_id);
249template <>
auto *
GetSpec<StationSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->stations.size() ? grffile->stations[local_id].get() :
nullptr; }
252template <>
auto *
GetSpec<HouseSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->housespec.size() ? grffile->housespec[local_id].get() :
nullptr; }
255template <>
auto *
GetSpec<IndustrySpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->industryspec.size() ? grffile->industryspec[local_id].get() :
nullptr; }
258template <>
auto *
GetSpec<IndustryTileSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->indtspec.size() ? grffile->indtspec[local_id].get() :
nullptr; }
267 GrfMsg(1,
"CargoMapSpriteGroup: Cargo type {} out of range, skipping", local_id);
270 cs->
grffile = _cur_gps.grffile;
276template <>
auto *
GetSpec<ObjectSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->objectspec.size() ? grffile->objectspec[local_id].get() :
nullptr; }
282 if (cid >= RTSG_END)
return;
284 const auto &type_map = _cur_gps.grffile->railtype_map;
290 rti.
grffile[cid] = _cur_gps.grffile;
291 rti.
group[cid] = group;
297template <RoadTramType TRoadTramType>
301 if (cid >= ROTSG_END)
return;
303 const auto &type_map = (TRoadTramType ==
RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map;
309 rti.
grffile[cid] = _cur_gps.grffile;
310 rti.
group[cid] = group;
316template <>
auto *
GetSpec<AirportSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->airportspec.size() ? grffile->airportspec[local_id].get() :
nullptr; }
319template <>
auto *
GetSpec<AirportTileSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->airtspec.size() ? grffile->airtspec[local_id].get() :
nullptr; }
322template <>
auto *
GetSpec<RoadStopSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->roadstops.size() ? grffile->roadstops[local_id].get() :
nullptr; }
328 if (cid >= GSF_END)
return;
330 auto found = _cur_gps.grffile->badge_map.find(local_id);
331 if (found == std::end(_cur_gps.grffile->badge_map)) {
332 GrfMsg(1,
"BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
334 auto &badge = *
GetBadge(found->second);
335 badge.grf_prop.SetSpriteGroup(
static_cast<GrfSpecFeature>(cid), group);
341 auto found = _cur_gps.grffile->badge_map.find(local_id);
342 if (found == std::end(_cur_gps.grffile->badge_map)) {
343 GrfMsg(1,
"BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
345 auto &badge = *
GetBadge(found->second);
347 badge.grf_prop.SetGRFFile(_cur_gps.grffile);
348 badge.grf_prop.local_id = local_id;
356 std::array<uint16_t, 256> local_ids_buffer;
357 for (uint i = 0; i != idcount; ++i) {
360 std::span<const uint16_t> local_ids{local_ids_buffer.begin(), idcount};
364 for (uint c = 0; c != cidcount; ++c) {
367 if (!IsValidGroupID(groupid,
"MapSpriteGroup"))
continue;
368 for (uint16_t local_id : local_ids) {
369 handler.MapSpecific(local_id, cid, _cur_gps.spritegroups[groupid]);
375 if (!IsValidGroupID(groupid,
"MapSpriteGroup"))
return;
376 for (uint16_t local_id : local_ids) {
377 handler.MapDefault(local_id, _cur_gps.spritegroups[groupid]);
382static void FeatureMapSpriteGroup(
ByteReader &buf)
401 if (feature >= GSF_END) {
402 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
411 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
413 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
420 _cur_gps.grffile->grf_features.Set(feature);
422 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
426 case GSF_ROADVEHICLES:
428 case GSF_AIRCRAFT: VehicleMapSpriteGroup(buf, feature, idcount);
return;
445 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
450template <>
void GrfActionHandler<0x03>::FileScan(
ByteReader &) { }
452template <>
void GrfActionHandler<0x03>::LabelScan(
ByteReader &) { }
453template <>
void GrfActionHandler<0x03>::Init(
ByteReader &) { }
454template <>
void GrfActionHandler<0x03>::Reserve(
ByteReader &) { }
455template <>
void GrfActionHandler<0x03>::Activation(
ByteReader &buf) { FeatureMapSpriteGroup(buf); }
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
StrongType::Typedef< uint32_t, struct CargoLabelTag, StrongType::Compare > CargoLabel
Globally unique label of a cargo type.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
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.
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
const GRFFile * grffile[RTSG_END]
NewGRF providing the Action3 for the railtype.
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
const GRFFile * grffile[ROTSG_END]
NewGRF providing the Action3 for the roadtype.
Functions related to debugging.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
Functions related to errors.
Definition of HouseSpec and accessors.
std::span< const CargoLabel > GetCargoTranslationTable(const GRFFile &grffile)
Get the cargo translation table to use for the given GRF file.
void GRFUnsafe(ByteReader &)
Set the current NewGRF as unsafe for static use.
Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access)
Returns the engine associated to a certain internal_id, resp.
@ GSF_DEFAULT
Unspecified feature, default badge.
static auto * GetSpec(GRFFile *, uint16_t)
Specializable function to retrieve a NewGRF spec of a particular type.
NewGRF handling of airports.
NewGRF handling of airport tiles.
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
Functions related to NewGRF badges.
Types related to NewGRF badges.
NewGRF buffer reader definition.
std::array< WaterFeature, CF_END > _water_feature
Table of canal 'feature' sprite groups.
Handling of NewGRF canals.
Cargo support for NewGRFs.
@ 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.
Functions for NewGRF engines.
void AddGenericCallback(GrfSpecFeature feature, const GRFFile *file, const SpriteGroup *group)
Add a generic feature callback sprite group to the appropriate feature list.
Functions related to NewGRF houses.
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.
Functions related to NewGRF objects.
NewGRF definitions and structures for road stops.
Header file for NewGRF stations.
RailType
Enumeration for all possible railtypes.
@ RAILTYPE_END
Used for iterations.
@ INVALID_RAILTYPE
Flag for invalid railtype.
@ RTT_TRAM
Tram road type.
RoadType
The different roadtypes we support.
@ INVALID_ROADTYPE
flag for invalid roadtype
@ ROADTYPE_END
Used for iterations.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
void MapDefault(uint16_t local_id, const SpriteGroup *group) override
Map default/fallback SpriteGroup to a specification.
void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapSpecific(uint16_t, uint8_t, const SpriteGroup *) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapDefault(uint16_t local_id, const SpriteGroup *group) override
Map default/fallback SpriteGroup to a specification.
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.
void MapDefault(uint16_t local_id, const SpriteGroup *group) override
Map default/fallback SpriteGroup to a specification.
void MapSpecific(uint16_t, uint8_t, const SpriteGroup *) override
Map a SpriteGroup to specific 'cargo type' of a specification.
Specification of a cargo type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
const struct GRFFile * grffile
NewGRF where group belongs to.
Common handler for mapping sprite groups for features which support cargo-type specific sprites.
void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapDefault(uint16_t local_id, const SpriteGroup *group) override
Map default/fallback SpriteGroup to a specification.
Dynamic data of a loaded NewGRF.
Handler interface for mapping sprite groups to their respective feature specific specifications.
virtual void MapDefault(uint16_t local_id, const SpriteGroup *group)=0
Map default/fallback SpriteGroup to a specification.
virtual void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group)=0
Map a SpriteGroup to specific 'cargo type' of a specification.
Common handler for mapping sprite groups for features which only support "Purchase" and "Default" spr...
void MapDefault(uint16_t local_id, const SpriteGroup *group) override
Map default/fallback SpriteGroup to a specification.
void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapDefault(uint16_t, const SpriteGroup *) override
Map default/fallback SpriteGroup to a specification.
void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapSpecific(uint16_t local_id, uint8_t cid, const SpriteGroup *group) override
Map a SpriteGroup to specific 'cargo type' of a specification.
void MapDefault(uint16_t, const SpriteGroup *) override
Map default/fallback SpriteGroup to a specification.
Base class for all vehicles.
VehicleType
Available vehicle types.