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"
26#include "../vehicle_base.h"
28#include "../newgrf_roadstop.h"
33#include "../safeguards.h"
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++) {
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;
169 void MapSpecific(uint16_t local_id, uint8_t cid,
const SpriteGroup *group)
override
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);
180 void MapDefault(uint16_t local_id,
const SpriteGroup *group)
override
182 if (T *spec = GetSpec<T>(_cur_gps.
grffile, local_id); spec ==
nullptr) {
183 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping.", local_id);
186 spec->grf_prop.SetGRFFile(_cur_gps.
grffile);
187 spec->grf_prop.local_id = local_id;
193template <
typename T,
typename T
class>
195 void MapSpecific(uint16_t local_id, uint8_t cid,
const SpriteGroup *group)
override
197 CargoType cargo_type = TranslateCargo(GSF_STATIONS, cid);
200 if (T *spec = GetSpec<T>(_cur_gps.
grffile, local_id); spec ==
nullptr) {
201 GrfMsg(1,
"MapSpriteGroup: {} undefined, skipping", local_id);
203 spec->grf_prop.SetSpriteGroup(cargo_type, group);
207 void MapDefault(uint16_t local_id,
const SpriteGroup *group)
override
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);
215 spec->grf_prop.SetGRFFile(_cur_gps.
grffile);
216 spec->grf_prop.local_id = local_id;
217 Tclass::Assign(spec);
223 void MapSpecific(uint16_t, uint8_t,
const SpriteGroup *)
override {}
225 void MapDefault(uint16_t local_id,
const SpriteGroup *group)
override
227 if (local_id >= CF_END) {
228 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", local_id);
236template <>
auto *GetSpec<StationSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->stations.size() ? grffile->stations[local_id].get() :
nullptr; }
239template <>
auto *GetSpec<HouseSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->housespec.size() ? grffile->housespec[local_id].get() :
nullptr; }
242template <>
auto *GetSpec<IndustrySpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->industryspec.size() ? grffile->industryspec[local_id].get() :
nullptr; }
245template <>
auto *GetSpec<IndustryTileSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->indtspec.size() ? grffile->indtspec[local_id].get() :
nullptr; }
249 void MapSpecific(uint16_t, uint8_t,
const SpriteGroup *)
override {}
251 void MapDefault(uint16_t local_id,
const SpriteGroup *group)
override
254 GrfMsg(1,
"CargoMapSpriteGroup: Cargo type {} out of range, skipping", local_id);
263template <>
auto *GetSpec<ObjectSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->objectspec.size() ? grffile->objectspec[local_id].get() :
nullptr; }
267 void MapSpecific(uint16_t local_id, uint8_t cid,
const SpriteGroup *group)
override
269 if (cid >= RTSG_END)
return;
271 const auto &type_map = _cur_gps.
grffile->railtype_map;
278 rti.
group[cid] = group;
281 void MapDefault(uint16_t,
const SpriteGroup *)
override {}
284template <RoadTramType TRoadTramType>
286 void MapSpecific(uint16_t local_id, uint8_t cid,
const SpriteGroup *group)
override
288 if (cid >= ROTSG_END)
return;
290 const auto &type_map = (TRoadTramType == RTT_TRAM) ? _cur_gps.
grffile->tramtype_map : _cur_gps.
grffile->roadtype_map;
297 rti.
group[cid] = group;
300 void MapDefault(uint16_t,
const SpriteGroup *)
override {}
303template <>
auto *GetSpec<AirportSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->airportspec.size() ? grffile->airportspec[local_id].get() :
nullptr; }
306template <>
auto *GetSpec<AirportTileSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->airtspec.size() ? grffile->airtspec[local_id].get() :
nullptr; }
309template <>
auto *GetSpec<RoadStopSpec>(
GRFFile *grffile, uint16_t local_id) {
return local_id < grffile->roadstops.size() ? grffile->roadstops[local_id].get() :
nullptr; }
313 void MapSpecific(uint16_t local_id, uint8_t cid,
const SpriteGroup *group)
override
315 if (cid >= GSF_END)
return;
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);
321 auto &badge = *
GetBadge(found->second);
322 badge.grf_prop.SetSpriteGroup(
static_cast<GrfSpecFeature>(cid), group);
326 void MapDefault(uint16_t local_id,
const SpriteGroup *group)
override
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);
332 auto &badge = *
GetBadge(found->second);
334 badge.grf_prop.SetGRFFile(_cur_gps.
grffile);
335 badge.grf_prop.local_id = local_id;
343 std::array<uint16_t, 256> local_ids_buffer;
344 for (uint i = 0; i != idcount; ++i) {
347 std::span<const uint16_t> local_ids{local_ids_buffer.begin(), idcount};
351 for (uint c = 0; c != cidcount; ++c) {
354 if (!IsValidGroupID(groupid,
"MapSpriteGroup"))
continue;
355 for (uint16_t local_id : local_ids) {
356 handler.MapSpecific(local_id, cid, _cur_gps.spritegroups[groupid]);
362 if (!IsValidGroupID(groupid,
"MapSpriteGroup"))
return;
363 for (uint16_t local_id : local_ids) {
364 handler.MapDefault(local_id, _cur_gps.spritegroups[groupid]);
369static void FeatureMapSpriteGroup(
ByteReader &buf)
388 if (feature >= GSF_END) {
389 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
398 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
400 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
409 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
413 case GSF_ROADVEHICLES:
415 case GSF_AIRCRAFT: VehicleMapSpriteGroup(buf, feature, idcount);
return;
432 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
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.
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.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
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.
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.
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.
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.
@ RAILTYPE_END
Used for iterations.
@ INVALID_RAILTYPE
Flag for invalid railtype.
RoadType
The different roadtypes we support.
@ INVALID_ROADTYPE
flag for invalid roadtype
@ ROADTYPE_END
Used for iterations.
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.
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.
Dynamic data of a loaded NewGRF.
std::vector< CargoLabel > cargo_list
Cargo translation table (local ID -> label)
GrfSpecFeatures grf_features
Bitset of GrfSpecFeature the grf uses.
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.