55#include "table/strings.h"
72const std::vector<GRFFile *> &GetAllGRFFiles()
121 this->skip_sprites = 0;
123 for (uint i = 0; i < GSF_END; i++) {
124 this->spritesets[i].clear();
127 memset(this->spritegroups, 0,
sizeof(this->spritegroups));
140 assert(feature < GSF_END);
141 for (uint i = 0; i < numsets; i++) {
142 SpriteSet &set = this->spritesets[feature][first_set + i];
143 set.
sprite = first_sprite + i * numents;
156 assert(feature < GSF_END);
157 return !this->spritesets[feature].empty();
169 assert(feature < GSF_END);
170 return this->spritesets[feature].find(set) != this->spritesets[feature].end();
182 return this->spritesets[feature].find(set)->second.sprite;
194 return this->spritesets[feature].find(set)->second.num_sprites;
207template <VehicleType T>
210 return image_index == 0xFD || IsValidImageIndex<T>(image_index);
222 ByteReader(uint8_t *data, uint8_t *end) : data(data), end(end) { }
224 inline uint8_t *ReadBytes(
size_t size)
226 if (data + size >= end) {
237 inline uint8_t ReadByte()
239 if (data < end)
return *(data)++;
245 uint16_t val = ReadByte();
246 return val | (ReadByte() << 8);
249 uint16_t ReadExtendedByte()
251 uint16_t val = ReadByte();
252 return val == 0xFF ? ReadWord() : val;
257 uint32_t val = ReadWord();
258 return val | (ReadWord() << 16);
264 return this->ReadDWord();
267 uint32_t ReadVarSize(uint8_t size)
270 case 1:
return ReadByte();
271 case 2:
return ReadWord();
272 case 4:
return ReadDWord();
279 std::string_view ReadString()
281 char *
string =
reinterpret_cast<char *
>(data);
282 size_t string_length =
ttd_strnlen(
string, Remaining());
285 Skip(std::min(string_length + 1, Remaining()));
287 return std::string_view(
string, string_length);
290 inline size_t Remaining()
const
295 inline bool HasData(
size_t count = 1)
const
297 return data + count <= end;
300 inline void Skip(
size_t len)
309typedef void (*SpecialSpriteHandler)(
ByteReader &buf);
326 RailTypeLabel railtypelabel;
327 uint8_t roadtramtype;
342 }
else if (this->refittability ==
UNSET) {
343 this->refittability =
EMPTY;
348static std::vector<GRFTempEngineData>
_gted;
363 GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
367 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
372 return this->grfid == other.grfid && this->nfoline == other.nfoline;
376static std::map<GRFLocation, std::pair<SpriteID, uint16_t>> _grm_sprites;
377typedef std::map<GRFLocation, std::vector<uint8_t>> GRFLineToSpriteOverride;
378static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
390void GrfMsgI(
int severity,
const std::string &msg)
403 if (file->grfid == grfid)
return file;
416 if (file->filename == filename)
return file;
436 if (config !=
nullptr) {
447 if (message == STR_NULL)
return nullptr;
449 config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
451 return &config->error.value();
499 static const StringID units_volume[] = {
500 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
501 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
502 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
503 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
504 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
505 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
506 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
507 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
513#define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
514 static_assert(stringend - stringid == end - begin); \
515 if (str >= begin && str <= end) return str + (stringid - begin)
518 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
519 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
520 if (str >= 0x004E && str <= 0x006D)
return units_volume[str - 0x004E];
521 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
522 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
523 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
528 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
529 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
530 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
533 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
534 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
535 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
536 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
537 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
540 case 0x4830:
return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
541 case 0x4831:
return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
542 case 0x483B:
return STR_ERROR_CAN_ONLY_BE_POSITIONED;
544#undef TEXTID_TO_STRINGID
546 if (str == STR_NULL)
return STR_EMPTY;
548 Debug(grf, 0,
"Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
587static std::map<uint32_t, uint32_t> _grf_id_overrides;
596 if (target_grfid == 0) {
597 _grf_id_overrides.erase(source_grfid);
598 GrfMsg(5,
"SetNewGRFOverride: Removed override of 0x{:X}",
BSWAP32(source_grfid));
600 _grf_id_overrides[source_grfid] = target_grfid;
601 GrfMsg(5,
"SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}",
BSWAP32(source_grfid),
BSWAP32(target_grfid));
611 auto found = _grf_id_overrides.find(_cur.
grffile->grfid);
612 if (found != std::end(_grf_id_overrides)) {
614 if (grffile !=
nullptr)
return grffile;
631 uint32_t scope_grfid = INVALID_GRFID;
634 scope_grfid = file->grfid;
635 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
636 scope_grfid = it->second;
638 if (grf_match ==
nullptr) {
639 GrfMsg(5,
"Tried mapping from GRFID {:x} to {:x} but target is not loaded",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
641 GrfMsg(5,
"Mapping from GRFID {:x} to {:x}",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
646 EngineID engine = _engine_mngr.
GetID(type, internal_id, scope_grfid);
665 GrfMsg(5,
"Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
671 if (static_access)
return nullptr;
674 GrfMsg(0,
"Can't allocate any more engines");
686 _engine_mngr.SetID(type, internal_id, scope_grfid, std::min<uint8_t>(internal_id,
_engine_counts[type]), e->
index);
696 GrfMsg(5,
"Created new engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
713 uint32_t scope_grfid = INVALID_GRFID;
715 scope_grfid = file->grfid;
716 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
717 scope_grfid = it->second;
721 return _engine_mngr.
GetID(type, internal_id, scope_grfid);
761 grf_sprite->
sprite = buf.ReadWord();
762 grf_sprite->
pal = buf.ReadWord();
767 bool custom_sprite =
HasBit(grf_sprite->
pal, 15) != invert_action1_flag;
771 uint index =
GB(grf_sprite->
sprite, 0, 14);
773 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {}", index);
774 grf_sprite->
sprite = SPR_IMG_QUERY;
775 grf_sprite->
pal = PAL_NONE;
778 if (max_sprite_offset !=
nullptr) *max_sprite_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
783 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
784 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
790 uint index =
GB(grf_sprite->
pal, 0, 14);
792 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {} for 'palette'", index);
793 grf_sprite->
pal = PAL_NONE;
796 if (max_palette_offset !=
nullptr) *max_palette_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
801 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
802 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
831 regs.delta.
parent[0] = buf.ReadByte();
832 regs.delta.
parent[1] = buf.ReadByte();
843 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
sprite_var10,
TLR_MAX_VAR10);
844 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
852 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
palette_var10,
TLR_MAX_VAR10);
853 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
872 bool has_flags =
HasBit(num_building_sprites, 6);
873 ClrBit(num_building_sprites, 6);
875 if (!allow_var10) valid_flags &= ~TLF_VAR10_FLAGS;
876 dts->
Allocate(num_building_sprites);
878 std::vector<uint16_t> max_sprite_offset(num_building_sprites + 1, 0);
879 std::vector<uint16_t> max_palette_offset(num_building_sprites + 1, 0);
886 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses invalid flag 0x{:X} for ground sprite", flags & ~(valid_flags & ~
TLF_NON_GROUND_FLAGS));
887 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
894 for (uint i = 0; i < num_building_sprites; i++) {
897 flags =
ReadSpriteLayoutSprite(buf, has_flags,
false, use_cur_spritesets, feature, &seq->image, max_sprite_offset.data() + i + 1, max_palette_offset.data() + i + 1);
900 if (flags & ~valid_flags) {
901 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses unknown flag 0x{:X}", flags & ~valid_flags);
902 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
907 seq->delta_y = buf.ReadByte();
909 if (!no_z_position) seq->
delta_z = buf.ReadByte();
912 seq->size_x = buf.ReadByte();
913 seq->size_y = buf.ReadByte();
914 seq->size_z = buf.ReadByte();
922 bool is_consistent =
true;
924 for (uint i = 0; i < num_building_sprites + 1; i++) {
925 if (max_sprite_offset[i] > 0) {
929 is_consistent =
false;
933 if (max_palette_offset[i] > 0) {
937 is_consistent =
false;
946 if (!is_consistent || dts->registers !=
nullptr) {
950 for (uint i = 0; i < num_building_sprites + 1; i++) {
965 CargoTypes result = 0;
983 if (base_pointer == 0) {
984 *index = INVALID_PRICE;
988 static const uint32_t start = 0x4B34;
989 static const uint32_t size = 6;
991 if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
992 GrfMsg(1,
"{}: Unsupported running cost base 0x{:04X}, ignoring", error_location, base_pointer);
996 *index = (
Price)((base_pointer - start) / size);
1025 ei->decay_speed = buf.ReadByte();
1042 ei->load_amount = buf.ReadByte();
1064 for (
int i = 0; i < numinfo; i++) {
1073 uint8_t tracktype = buf.ReadByte();
1075 if (tracktype < _cur.grffile->railtype_list.size()) {
1080 switch (tracktype) {
1081 case 0:
_gted[e->
index].railtypelabel = rvi->
engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL;
break;
1082 case 1:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MONO;
break;
1083 case 2:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MAGLEV;
break;
1085 GrfMsg(1,
"RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1098 uint16_t speed = buf.ReadWord();
1099 if (speed == 0xFFFF) speed = 0;
1106 rvi->
power = buf.ReadWord();
1109 if (rvi->
power != 0) {
1127 uint8_t spriteid = buf.ReadByte();
1128 uint8_t orig_spriteid = spriteid;
1132 if (spriteid < 0xFD) spriteid >>= 1;
1134 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1135 rvi->image_index = spriteid;
1137 GrfMsg(1,
"RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1138 rvi->image_index = 0;
1144 uint8_t dual = buf.ReadByte();
1149 rvi->railveh_type = rvi->
power == 0 ?
1161 uint8_t ctype = buf.ReadByte();
1163 if (ctype == 0xFF) {
1165 ei->cargo_type = INVALID_CARGO;
1169 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1176 SB(rvi->
weight, 0, 8, buf.ReadByte());
1184 GrfMsg(2,
"RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1196 uint8_t traction = buf.ReadByte();
1199 if (traction <= 0x07) {
1201 }
else if (traction <= 0x27) {
1203 }
else if (traction <= 0x31) {
1205 }
else if (traction <= 0x37) {
1207 }
else if (traction <= 0x41) {
1233 ei->refit_cost = buf.ReadByte();
1237 uint32_t mask = buf.ReadDWord();
1238 _gted[e->
index].UpdateRefittability(mask != 0);
1275 uint8_t weight = buf.ReadByte();
1278 GrfMsg(2,
"RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1299 _gted[e->
index].cargo_allowed = buf.ReadWord();
1305 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1319 uint8_t count = buf.ReadByte();
1320 _gted[e->
index].UpdateRefittability(prop == 0x2C && count != 0);
1322 CargoTypes &ctt = prop == 0x2C ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1348 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1372 for (
int i = 0; i < numinfo; i++) {
1383 _gted[e->
index].roadtramtype = buf.ReadByte() + 1;
1391 rvi->running_cost = buf.ReadByte();
1399 uint8_t spriteid = buf.ReadByte();
1400 uint8_t orig_spriteid = spriteid;
1403 if (spriteid == 0xFF) spriteid = 0xFD;
1405 if (spriteid < 0xFD) spriteid >>= 1;
1407 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1408 rvi->image_index = spriteid;
1410 GrfMsg(1,
"RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1411 rvi->image_index = 0;
1417 rvi->capacity = buf.ReadByte();
1422 uint8_t ctype = buf.ReadByte();
1424 if (ctype == 0xFF) {
1426 ei->cargo_type = INVALID_CARGO;
1430 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1437 rvi->cost_factor = buf.ReadByte();
1445 rvi->
power = buf.ReadByte();
1449 rvi->
weight = buf.ReadByte();
1453 _gted[e->
index].rv_max_speed = buf.ReadByte();
1457 uint32_t mask = buf.ReadDWord();
1458 _gted[e->
index].UpdateRefittability(mask != 0);
1477 ei->refit_cost = buf.ReadByte();
1490 _gted[e->
index].cargo_allowed = buf.ReadWord();
1496 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1528 uint8_t count = buf.ReadByte();
1529 _gted[e->
index].UpdateRefittability(prop == 0x24 && count != 0);
1531 CargoTypes &ctt = prop == 0x24 ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1553 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1577 for (
int i = 0; i < numinfo; i++) {
1586 uint8_t spriteid = buf.ReadByte();
1587 uint8_t orig_spriteid = spriteid;
1590 if (spriteid == 0xFF) spriteid = 0xFD;
1592 if (spriteid < 0xFD) spriteid >>= 1;
1594 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1595 svi->image_index = spriteid;
1597 GrfMsg(1,
"ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1598 svi->image_index = 0;
1608 svi->cost_factor = buf.ReadByte();
1617 uint8_t ctype = buf.ReadByte();
1619 if (ctype == 0xFF) {
1621 ei->cargo_type = INVALID_CARGO;
1625 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1632 svi->capacity = buf.ReadWord();
1636 svi->running_cost = buf.ReadByte();
1644 uint32_t mask = buf.ReadDWord();
1645 _gted[e->
index].UpdateRefittability(mask != 0);
1656 ei->refit_cost = buf.ReadByte();
1677 _gted[e->
index].cargo_allowed = buf.ReadWord();
1683 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1711 uint8_t count = buf.ReadByte();
1712 _gted[e->
index].UpdateRefittability(prop == 0x1E && count != 0);
1714 CargoTypes &ctt = prop == 0x1E ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1740 svi->
acceleration = std::max<uint8_t>(1, buf.ReadByte());
1744 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1768 for (
int i = 0; i < numinfo; i++) {
1777 uint8_t spriteid = buf.ReadByte();
1778 uint8_t orig_spriteid = spriteid;
1781 if (spriteid == 0xFF) spriteid = 0xFD;
1783 if (spriteid < 0xFD) spriteid >>= 1;
1785 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1786 avi->image_index = spriteid;
1788 GrfMsg(1,
"AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1789 avi->image_index = 0;
1795 if (buf.ReadByte() == 0) {
1807 avi->cost_factor = buf.ReadByte();
1811 avi->
max_speed = (buf.ReadByte() * 128) / 10;
1815 avi->acceleration = buf.ReadByte();
1819 avi->running_cost = buf.ReadByte();
1835 uint32_t mask = buf.ReadDWord();
1836 _gted[e->
index].UpdateRefittability(mask != 0);
1847 ei->refit_cost = buf.ReadByte();
1860 _gted[e->
index].cargo_allowed = buf.ReadWord();
1866 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1884 uint8_t count = buf.ReadByte();
1885 _gted[e->
index].UpdateRefittability(prop == 0x1D && count != 0);
1887 CargoTypes &ctt = prop == 0x1D ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1913 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1938 GrfMsg(1,
"StationChangeInfo: Station {} is invalid, max {}, ignoring", stid + numinfo,
NUM_STATIONS_PER_GRF);
1943 if (_cur.
grffile->stations.size() < stid + numinfo) _cur.
grffile->stations.resize(stid + numinfo);
1945 for (
int i = 0; i < numinfo; i++) {
1946 auto &statspec = _cur.
grffile->stations[stid + i];
1949 if (statspec ==
nullptr && prop != 0x08) {
1950 GrfMsg(2,
"StationChangeInfo: Attempt to modify undefined station {}, ignoring", stid + i);
1957 if (statspec ==
nullptr) {
1958 statspec = std::make_unique<StationSpec>();
1962 uint32_t classid = buf.ReadDWord();
1968 uint16_t tiles = buf.ReadExtendedByte();
1969 statspec->renderdata.clear();
1970 statspec->renderdata.reserve(tiles);
1972 for (uint t = 0; t < tiles; t++) {
1976 if (buf.HasData(4) && buf.PeekDWord() == 0) {
1979 dts->
Clone(&_station_display_datas_rail[t % 8]);
1987 static std::vector<DrawTileSeqStruct> tmp_layout;
1994 dtss.
delta_x = buf.ReadByte();
1996 dtss.delta_y = buf.ReadByte();
1997 dtss.
delta_z = buf.ReadByte();
1998 dtss.size_x = buf.ReadByte();
1999 dtss.size_y = buf.ReadByte();
2000 dtss.size_z = buf.ReadByte();
2006 dts->
Clone(tmp_layout.data());
2010 if (statspec->renderdata.size() & 1) {
2011 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
2012 statspec->renderdata.pop_back();
2018 uint16_t srcid = buf.ReadExtendedByte();
2019 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2021 if (srcstatspec ==
nullptr) {
2022 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid, stid + i);
2026 statspec->renderdata.clear();
2027 statspec->renderdata.reserve(srcstatspec->
renderdata.size());
2029 for (
const auto &it : srcstatspec->
renderdata) {
2037 statspec->callback_mask = buf.ReadByte();
2041 statspec->disallowed_platforms = buf.ReadByte();
2045 statspec->disallowed_lengths = buf.ReadByte();
2049 while (buf.HasData()) {
2050 uint8_t length = buf.ReadByte();
2051 uint8_t number = buf.ReadByte();
2053 if (length == 0 || number == 0)
break;
2055 const uint8_t *buf_layout = buf.ReadBytes(length * number);
2059 layout.assign(buf_layout, buf_layout + length * number);
2062 for (
auto &tile : layout) {
2063 if ((tile & ~1U) != tile) {
2064 GrfMsg(1,
"StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2072 uint16_t srcid = buf.ReadExtendedByte();
2073 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2075 if (srcstatspec ==
nullptr) {
2076 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid, stid + i);
2080 statspec->layouts = srcstatspec->
layouts;
2085 statspec->cargo_threshold = buf.ReadWord();
2089 uint8_t pylons = buf.ReadByte();
2090 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2091 for (
int j = 0; j < 8; ++j) {
2095 statspec->tileflags[j] &=
~StationSpec::TileFlags::Pylons;
2102 if (_cur.
grffile->grf_version >= 7) {
2105 statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2110 statspec->flags = buf.ReadByte();
2114 uint8_t wires = buf.ReadByte();
2115 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2116 for (
int j = 0; j < 8; ++j) {
2120 statspec->tileflags[j] &=
~StationSpec::TileFlags::NoWires;
2127 uint8_t blocked = buf.ReadByte();
2128 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2129 for (
int j = 0; j < 8; ++j) {
2130 if (
HasBit(blocked, j)) {
2133 statspec->tileflags[j] &=
~StationSpec::TileFlags::Blocked;
2140 statspec->animation.
frames = buf.ReadByte();
2141 statspec->animation.status = buf.ReadByte();
2145 statspec->animation.speed = buf.ReadByte();
2149 statspec->animation.triggers = buf.ReadWord();
2155 uint16_t tiles = buf.ReadExtendedByte();
2156 statspec->renderdata.clear();
2157 statspec->renderdata.reserve(tiles);
2159 for (uint t = 0; t < tiles; t++) {
2161 uint num_building_sprites = buf.ReadByte();
2167 if (statspec->renderdata.size() & 1) {
2168 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
2169 statspec->renderdata.pop_back();
2186 AddStringForMapping(buf.ReadWord(), [statspec = statspec.get()](
StringID str) { StationClass::Get(statspec->class_index)->name = str; });
2190 uint16_t tiles = buf.ReadExtendedByte();
2192 statspec->tileflags.assign(flags, flags + tiles);
2217 if (
id + numinfo > CF_END) {
2218 GrfMsg(1,
"CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring",
id + numinfo, CF_END);
2222 for (
int i = 0; i < numinfo; i++) {
2231 cp->
flags = buf.ReadByte();
2256 GrfMsg(1,
"BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", brid + numinfo,
MAX_BRIDGES);
2260 for (
int i = 0; i < numinfo; i++) {
2266 uint8_t year = buf.ReadByte();
2281 bridge->
price = buf.ReadByte();
2285 bridge->
speed = buf.ReadWord();
2286 if (bridge->
speed == 0) bridge->
speed = UINT16_MAX;
2290 uint8_t tableid = buf.ReadByte();
2291 uint8_t numtables = buf.ReadByte();
2295 bridge->
sprite_table = CallocT<PalSpriteID*>(NUM_BRIDGE_PIECES);
2298 for (; numtables-- != 0; tableid++) {
2299 if (tableid >= NUM_BRIDGE_PIECES) {
2300 GrfMsg(1,
"BridgeChangeInfo: Table {} >= {}, skipping", tableid, NUM_BRIDGE_PIECES);
2323 bridge->
flags = buf.ReadByte();
2332 if (newone != STR_UNDEFINED) bridge->
material = newone;
2339 if (newone != STR_UNDEFINED) bridge->
transport_name[prop - 0x11] = newone;
2344 bridge->
price = buf.ReadWord();
2401 for (uint j = 0; j < 4; j++) buf.ReadByte();
2405 uint8_t count = buf.ReadByte();
2406 for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2411 buf.Skip(buf.ReadByte() * 2);
2434 GrfMsg(1,
"TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", hid + numinfo,
NUM_HOUSES_PER_GRF);
2439 if (_cur.
grffile->housespec.size() < hid + numinfo) _cur.
grffile->housespec.resize(hid + numinfo);
2441 for (
int i = 0; i < numinfo; i++) {
2442 auto &housespec = _cur.
grffile->housespec[hid + i];
2444 if (prop != 0x08 && housespec ==
nullptr) {
2447 if (cir > ret) ret = cir;
2453 uint8_t subs_id = buf.ReadByte();
2454 if (subs_id == 0xFF) {
2461 GrfMsg(2,
"TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id, hid + i);
2466 if (housespec ==
nullptr) {
2468 housespec = std::make_unique<HouseSpec>(*
HouseSpec::Get(subs_id));
2470 housespec->enabled =
true;
2471 housespec->grf_prop.local_id = hid + i;
2472 housespec->grf_prop.subst_id = subs_id;
2473 housespec->grf_prop.grfid = _cur.
grffile->grfid;
2474 housespec->grf_prop.grffile = _cur.
grffile;
2476 housespec->random_colour[0] = COLOUR_RED;
2477 housespec->random_colour[1] = COLOUR_BLUE;
2478 housespec->random_colour[2] = COLOUR_ORANGE;
2479 housespec->random_colour[3] = COLOUR_GREEN;
2482 housespec->building_flags &= ~(BUILDING_IS_CHURCH | BUILDING_IS_STADIUM);
2488 CargoID cid = housespec->accepts_cargo[2];
2489 if (!
IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
2491 housespec->cargo_acceptance[2] = 0;
2498 housespec->building_flags = (BuildingFlags)buf.ReadByte();
2502 uint16_t years = buf.ReadWord();
2509 housespec->population = buf.ReadByte();
2513 housespec->mail_generation = buf.ReadByte();
2518 housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2522 int8_t goods = buf.ReadByte();
2532 housespec->accepts_cargo[2] = cid;
2533 housespec->accepts_cargo_label[2] =
CT_INVALID;
2534 housespec->cargo_acceptance[2] =
abs(goods);
2539 housespec->remove_rating_decrease = buf.ReadWord();
2543 housespec->removal_cost = buf.ReadByte();
2551 housespec->building_availability = (
HouseZones)buf.ReadWord();
2555 housespec->callback_mask |= buf.ReadByte();
2559 uint8_t
override = buf.ReadByte();
2563 GrfMsg(2,
"TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.",
override, hid + i);
2567 _house_mngr.
Add(hid + i, _cur.
grffile->grfid,
override);
2572 housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2576 for (uint j = 0; j < 4; j++) housespec->random_colour[j] =
static_cast<Colours
>(
GB(buf.ReadByte(), 0, 4));
2580 housespec->probability = buf.ReadByte();
2588 housespec->animation.frames = buf.ReadByte();
2589 housespec->animation.status =
GB(housespec->animation.frames, 7, 1);
2590 SB(housespec->animation.frames, 7, 1, 0);
2594 housespec->animation.speed =
Clamp(buf.ReadByte(), 2, 16);
2598 housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.
grffile->grfid);
2602 housespec->callback_mask |= (buf.ReadByte() << 8);
2606 uint32_t cargotypes = buf.ReadDWord();
2609 if (cargotypes == 0xFFFFFFFF)
break;
2613 uint8_t cargo_part =
GB(cargotypes, 8 * j, 8);
2618 housespec->cargo_acceptance[j] = 0;
2620 housespec->accepts_cargo[j] = cargo;
2622 housespec->accepts_cargo_label[j] =
CT_INVALID;
2628 housespec->minimum_life = buf.ReadByte();
2632 uint8_t count = buf.ReadByte();
2633 for (uint8_t j = 0; j < count; j++) {
2641 housespec->min_year = buf.ReadWord();
2645 housespec->max_year = buf.ReadWord();
2650 uint count = buf.ReadByte();
2651 if (count >
lengthof(housespec->accepts_cargo)) {
2659 for (uint i = 0; i <
lengthof(housespec->accepts_cargo); i++) {
2662 housespec->cargo_acceptance[i] = buf.ReadByte();
2664 housespec->accepts_cargo[i] = INVALID_CARGO;
2665 housespec->cargo_acceptance[i] = 0;
2667 if (i < std::size(housespec->accepts_cargo_label)) housespec->accepts_cargo_label[i] =
CT_INVALID;
2691 if (grffile ==
nullptr)
return nullptr;
2694 if (it == std::end(grffile->
language_map))
return nullptr;
2708template <
typename T,
typename TGetTableFunc>
2712 GrfMsg(1,
"LoadTranslationTable: {} translation table must start at zero", name);
2716 std::vector<T> &translation_table = gettable(*_cur.
grffile);
2717 translation_table.clear();
2718 translation_table.reserve(numinfo);
2719 for (
int i = 0; i < numinfo; i++) {
2720 translation_table.push_back(T(
BSWAP32(buf.ReadDWord())));
2724 if (grf_override !=
nullptr) {
2726 GrfMsg(1,
"LoadTranslationTable: Copying {} translation table to override GRFID '{}'", name,
BSWAP32(grf_override->grfid));
2727 std::vector<T> &override_table = gettable(*grf_override);
2728 override_table = translation_table;
2743 for (
int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2760 return LoadTranslationTable<CargoLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
2763 return LoadTranslationTable<RailTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
2766 return LoadTranslationTable<RoadTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
2769 return LoadTranslationTable<RoadTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
2777 for (
int i = 0; i < numinfo; i++) {
2780 int factor = buf.ReadByte();
2781 uint price = gvid + i;
2783 if (price < PR_END) {
2786 GrfMsg(1,
"GlobalVarChangeInfo: Price {} out of range, ignoring", price);
2795 if ((newone != STR_UNDEFINED) && (curidx <
CURRENCY_END)) {
2804 uint32_t rate = buf.ReadDWord();
2812 GrfMsg(1,
"GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2819 uint16_t options = buf.ReadWord();
2828 GrfMsg(1,
"GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2840 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2852 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2864 GrfMsg(1,
"GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2871 GrfMsg(1,
"GlobalVarChangeInfo: The snowline can only be set once ({})", numinfo);
2873 GrfMsg(1,
"GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2879 table[i][j] = buf.ReadByte();
2880 if (_cur.
grffile->grf_version >= 8) {
2883 if (table[i][j] >= 128) {
2905 uint curidx = gvid + i;
2907 if (lang ==
nullptr) {
2908 GrfMsg(1,
"GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
2913 while (buf.ReadByte() != 0) {
2921 uint plural_form = buf.ReadByte();
2922 if (plural_form >= LANGUAGE_MAX_PLURAL) {
2923 GrfMsg(1,
"GlobalVarChanceInfo: Plural form {} is out of range, ignoring", plural_form);
2930 uint8_t newgrf_id = buf.ReadByte();
2931 while (newgrf_id != 0) {
2932 std::string_view name = buf.ReadString();
2947 GrfMsg(1,
"GlobalVarChangeInfo: Gender name {} is not known, ignoring",
StrMakeValid(name));
2954 GrfMsg(1,
"GlobalVarChangeInfo: Case name {} is not known, ignoring",
StrMakeValid(name));
2959 newgrf_id = buf.ReadByte();
2978 return LoadTranslationTable<CargoLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
2981 return LoadTranslationTable<RailTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
2984 return LoadTranslationTable<RoadTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
2987 return LoadTranslationTable<RoadTypeLabel>(gvid, numinfo, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
2995 for (
int i = 0; i < numinfo; i++) {
3019 uint32_t s = buf.ReadDWord();
3020 uint32_t t = buf.ReadDWord();
3027 while (buf.ReadByte() != 0) {
3055 GrfMsg(2,
"CargoChangeInfo: Cargo type {} out of range (max {})", cid + numinfo,
NUM_CARGO - 1);
3059 for (
int i = 0; i < numinfo; i++) {
3064 cs->
bitnum = buf.ReadByte();
3103 cs->
sprite = buf.ReadWord();
3107 cs->
weight = buf.ReadByte();
3111 cs->transit_periods[0] = buf.ReadByte();
3115 cs->transit_periods[1] = buf.ReadByte();
3123 cs->rating_colour = buf.ReadByte();
3127 cs->legend_colour = buf.ReadByte();
3144 uint8_t substitute_type = buf.ReadByte();
3146 switch (substitute_type) {
3153 GrfMsg(1,
"CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3169 cs->
multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3173 uint8_t substitute_type = buf.ReadByte();
3175 switch (substitute_type) {
3179 GrfMsg(1,
"CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3212 if (_cur.
grffile->sound_offset == 0) {
3213 GrfMsg(1,
"SoundEffectChangeInfo: No effects defined, skipping");
3218 GrfMsg(1,
"SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", sid + numinfo,
ORIGINAL_SAMPLE_COUNT + _cur.
grffile->num_sounds);
3222 for (
int i = 0; i < numinfo; i++) {
3227 sound->volume =
Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3231 sound->priority = buf.ReadByte();
3235 SoundID orig_sound = buf.ReadByte();
3238 GrfMsg(1,
"SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound,
ORIGINAL_SAMPLE_COUNT);
3240 SoundEntry *old_sound = GetSound(orig_sound);
3243 *old_sound = *sound;
3285 buf.Skip(buf.ReadByte() * 2);
3308 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", indtid + numinfo,
NUM_INDUSTRYTILES_PER_GRF);
3313 if (_cur.
grffile->indtspec.size() < indtid + numinfo) _cur.
grffile->indtspec.resize(indtid + numinfo);
3315 for (
int i = 0; i < numinfo; i++) {
3316 auto &tsp = _cur.
grffile->indtspec[indtid + i];
3318 if (prop != 0x08 && tsp ==
nullptr) {
3320 if (cir > ret) ret = cir;
3326 uint8_t subs_id = buf.ReadByte();
3329 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id, indtid + i);
3334 if (tsp ==
nullptr) {
3335 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3337 tsp->enabled =
true;
3345 tsp->grf_prop.local_id = indtid + i;
3346 tsp->grf_prop.subst_id = subs_id;
3347 tsp->grf_prop.grfid = _cur.
grffile->grfid;
3348 tsp->grf_prop.grffile = _cur.
grffile;
3355 uint8_t ovrid = buf.ReadByte();
3359 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid, indtid + i);
3363 _industile_mngr.
Add(indtid + i, _cur.
grffile->grfid, ovrid);
3370 uint16_t acctp = buf.ReadWord();
3372 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
3373 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
3378 tsp->slopes_refused = (
Slope)buf.ReadByte();
3382 tsp->callback_mask = buf.ReadByte();
3386 tsp->animation.frames = buf.ReadByte();
3387 tsp->animation.status = buf.ReadByte();
3391 tsp->animation.speed = buf.ReadByte();
3395 tsp->animation.triggers = buf.ReadByte();
3403 uint8_t num_cargoes = buf.ReadByte();
3404 if (num_cargoes > std::size(tsp->acceptance)) {
3409 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3410 if (i < num_cargoes) {
3413 tsp->acceptance[i] = (int8_t)buf.ReadByte();
3415 tsp->accepts_cargo[i] = INVALID_CARGO;
3416 tsp->acceptance[i] = 0;
3418 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
3478 uint8_t num_table = buf.ReadByte();
3479 for (uint8_t j = 0; j < num_table; j++) {
3480 for (uint k = 0;; k++) {
3481 uint8_t x = buf.ReadByte();
3482 if (x == 0xFE && k == 0) {
3488 uint8_t y = buf.ReadByte();
3489 if (x == 0 && y == 0x80)
break;
3491 uint8_t gfx = buf.ReadByte();
3492 if (gfx == 0xFE) buf.ReadWord();
3506 buf.Skip(buf.ReadByte());
3510 int num_inputs = buf.ReadByte();
3511 int num_outputs = buf.ReadByte();
3512 buf.Skip(num_inputs * num_outputs * 2);
3530 const size_t size = layout.size();
3531 if (size == 0)
return false;
3533 for (
size_t i = 0; i < size - 1; i++) {
3534 for (
size_t j = i + 1; j < size; j++) {
3535 if (layout[i].ti.x == layout[j].ti.x &&
3536 layout[i].ti.y == layout[j].ti.y) {
3542 bool have_regular_tile =
false;
3543 for (
const auto &tilelayout : layout) {
3545 have_regular_tile =
true;
3550 return have_regular_tile;
3566 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", indid + numinfo,
NUM_INDUSTRYTYPES_PER_GRF);
3571 if (_cur.
grffile->industryspec.size() < indid + numinfo) _cur.
grffile->industryspec.resize(indid + numinfo);
3573 for (
int i = 0; i < numinfo; i++) {
3574 auto &indsp = _cur.
grffile->industryspec[indid + i];
3576 if (prop != 0x08 && indsp ==
nullptr) {
3578 if (cir > ret) ret = cir;
3584 uint8_t subs_id = buf.ReadByte();
3585 if (subs_id == 0xFF) {
3588 _industry_specs[indid + i].
enabled =
false;
3592 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id, indid + i);
3599 if (indsp ==
nullptr) {
3600 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3602 indsp->enabled =
true;
3603 indsp->grf_prop.local_id = indid + i;
3604 indsp->grf_prop.subst_id = subs_id;
3605 indsp->grf_prop.grfid = _cur.
grffile->grfid;
3606 indsp->grf_prop.grffile = _cur.
grffile;
3615 uint8_t ovrid = buf.ReadByte();
3619 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid, indid + i);
3622 indsp->grf_prop.override = ovrid;
3623 _industry_mngr.
Add(indid + i, _cur.
grffile->grfid, ovrid);
3628 uint8_t new_num_layouts = buf.ReadByte();
3629 uint32_t definition_size = buf.ReadDWord();
3630 uint32_t bytes_read = 0;
3631 std::vector<IndustryTileLayout> new_layouts;
3634 for (uint8_t j = 0; j < new_num_layouts; j++) {
3636 layout.reserve(new_num_layouts);
3638 for (uint k = 0;; k++) {
3639 if (bytes_read >= definition_size) {
3640 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.", indid);
3642 definition_size = UINT32_MAX;
3647 it.ti.
x = buf.ReadByte();
3650 if (it.ti.
x == 0xFE && k == 0) {
3652 IndustryType type = buf.ReadByte();
3653 uint8_t laynbr = buf.ReadByte();
3656 if (type >=
lengthof(_origin_industry_specs)) {
3657 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", indid);
3661 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3662 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", indid);
3666 layout = _origin_industry_specs[type].layouts[laynbr];
3670 it.ti.
y = buf.ReadByte();
3673 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
3679 it.gfx = buf.ReadByte();
3682 if (it.gfx == 0xFE) {
3684 int local_tile_id = buf.ReadWord();
3688 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3691 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, indid);
3697 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
3698 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
3707 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
3713 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", indid);
3717 new_layouts.push_back(layout);
3722 indsp->layouts = new_layouts;
3743 indsp->cost_multiplier = buf.ReadByte();
3763 indsp->production_rate[prop - 0x12] = buf.ReadByte();
3767 indsp->minimal_cargo = buf.ReadByte();
3771 uint8_t num_sounds = buf.ReadByte();
3773 std::vector<uint8_t> sounds;
3774 sounds.reserve(num_sounds);
3775 for (uint8_t j = 0; j < num_sounds; ++j) {
3776 sounds.push_back(buf.ReadByte());
3779 indsp->random_sounds = std::move(sounds);
3784 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3796 indsp->map_colour = buf.ReadByte();
3810 uint32_t multiples = buf.ReadDWord();
3811 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
3812 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
3821 indsp->prospecting_chance = buf.ReadDWord();
3826 uint8_t aflag = buf.ReadByte();
3827 SB(indsp->callback_mask, (prop - 0x21) * 8, 8, aflag);
3832 indsp->removal_cost_multiplier = buf.ReadDWord();
3836 uint16_t str = buf.ReadWord();
3838 indsp->station_name = STR_NULL;
3846 uint8_t num_cargoes = buf.ReadByte();
3847 if (num_cargoes > std::size(indsp->produced_cargo)) {
3852 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3853 if (i < num_cargoes) {
3855 indsp->produced_cargo[i] = cargo;
3857 indsp->produced_cargo[i] = INVALID_CARGO;
3859 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
3865 uint8_t num_cargoes = buf.ReadByte();
3866 if (num_cargoes > std::size(indsp->accepts_cargo)) {
3871 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3872 if (i < num_cargoes) {
3874 indsp->accepts_cargo[i] = cargo;
3876 indsp->accepts_cargo[i] = INVALID_CARGO;
3878 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
3884 uint8_t num_cargoes = buf.ReadByte();
3885 if (num_cargoes >
lengthof(indsp->production_rate)) {
3890 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
3891 if (i < num_cargoes) {
3892 indsp->production_rate[i] = buf.ReadByte();
3894 indsp->production_rate[i] = 0;
3901 uint8_t num_inputs = buf.ReadByte();
3902 uint8_t num_outputs = buf.ReadByte();
3903 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
3908 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3909 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
3911 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
3912 indsp->input_cargo_multiplier[i][j] = mult;
3940 GrfMsg(1,
"AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", airport + numinfo,
NUM_AIRPORTS_PER_GRF);
3945 if (_cur.
grffile->airportspec.size() < airport + numinfo) _cur.
grffile->airportspec.resize(airport + numinfo);
3947 for (
int i = 0; i < numinfo; i++) {
3948 auto &as = _cur.
grffile->airportspec[airport + i];
3950 if (as ==
nullptr && prop != 0x08 && prop != 0x09) {
3951 GrfMsg(2,
"AirportChangeInfo: Attempt to modify undefined airport {}, ignoring", airport + i);
3957 uint8_t subs_id = buf.ReadByte();
3958 if (subs_id == 0xFF) {
3965 GrfMsg(2,
"AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id, airport + i);
3972 if (as ==
nullptr) {
3976 as->grf_prop.local_id = airport + i;
3977 as->grf_prop.subst_id = subs_id;
3978 as->grf_prop.grfid = _cur.
grffile->grfid;
3979 as->grf_prop.grffile = _cur.
grffile;
3981 _airport_mngr.
Add(airport + i, _cur.
grffile->grfid, subs_id);
3987 uint8_t num_layouts = buf.ReadByte();
3992 std::vector<AirportTileLayout> layouts;
3993 layouts.reserve(num_layouts);
3995 for (uint8_t j = 0; j != num_layouts; ++j) {
3996 auto &layout = layouts.emplace_back();
3997 layout.rotation =
static_cast<Direction>(buf.ReadByte() & 6);
4000 auto &tile = layout.tiles.emplace_back();
4001 tile.ti.x = buf.ReadByte();
4002 tile.ti.y = buf.ReadByte();
4003 if (tile.ti.x == 0 && tile.ti.y == 0x80) {
4011 tile.gfx = buf.ReadByte();
4013 if (tile.gfx == 0xFE) {
4015 int local_tile_id = buf.ReadWord();
4018 uint16_t tempid = _airporttile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
4021 GrfMsg(2,
"AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i);
4026 }
else if (tile.gfx == 0xFF) {
4027 tile.ti.x =
static_cast<int8_t
>(
GB(tile.ti.x, 0, 8));
4028 tile.ti.y =
static_cast<int8_t
>(
GB(tile.ti.y, 0, 8));
4032 if (layout.rotation ==
DIR_E || layout.rotation ==
DIR_W) {
4033 size_x = std::max<uint8_t>(size_x, tile.ti.y + 1);
4034 size_y = std::max<uint8_t>(size_y, tile.ti.x + 1);
4036 size_x = std::max<uint8_t>(size_x, tile.ti.x + 1);
4037 size_y = std::max<uint8_t>(size_y, tile.ti.y + 1);
4041 as->layouts = std::move(layouts);
4042 as->size_x = size_x;
4043 as->size_y = size_y;
4048 as->min_year = buf.ReadWord();
4049 as->max_year = buf.ReadWord();
4062 as->noise_level = buf.ReadByte();
4070 as->maintenance_cost = buf.ReadWord();
4140 GrfMsg(1,
"ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.",
id + numinfo,
NUM_OBJECTS_PER_GRF);
4145 if (_cur.
grffile->objectspec.size() <
id + numinfo) _cur.
grffile->objectspec.resize(
id + numinfo);
4147 for (
int i = 0; i < numinfo; i++) {
4148 auto &spec = _cur.
grffile->objectspec[
id + i];
4150 if (prop != 0x08 && spec ==
nullptr) {
4153 if (cir > ret) ret = cir;
4160 if (spec ==
nullptr) {
4161 spec = std::make_unique<ObjectSpec>();
4167 uint32_t classid = buf.ReadDWord();
4182 spec->climate = buf.ReadByte();
4186 spec->size = buf.ReadByte();
4187 if (
GB(spec->size, 0, 4) == 0 ||
GB(spec->size, 4, 4) == 0) {
4188 GrfMsg(0,
"ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size,
id + i);
4194 spec->build_cost_multiplier = buf.ReadByte();
4195 spec->clear_cost_multiplier = spec->build_cost_multiplier;
4199 spec->introduction_date = buf.ReadDWord();
4203 spec->end_of_life_date = buf.ReadDWord();
4212 spec->animation.frames = buf.ReadByte();
4213 spec->animation.status = buf.ReadByte();
4217 spec->animation.speed = buf.ReadByte();
4221 spec->animation.triggers = buf.ReadWord();
4225 spec->clear_cost_multiplier = buf.ReadByte();
4229 spec->callback_mask = buf.ReadWord();
4233 spec->height = buf.ReadByte();
4237 spec->views = buf.ReadByte();
4238 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
4239 GrfMsg(2,
"ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views,
id + i);
4245 spec->generate_amount = buf.ReadByte();
4272 GrfMsg(1,
"RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4276 for (
int i = 0; i < numinfo; i++) {
4289 uint16_t str = buf.ReadWord();
4291 if (_cur.
grffile->grf_version < 8) {
4321 int n = buf.ReadByte();
4322 for (
int j = 0; j != n; j++) {
4323 RailTypeLabel label = buf.ReadDWord();
4383 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4402 GrfMsg(1,
"RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4406 for (
int i = 0; i < numinfo; i++) {
4410 RailTypeLabel rtl = buf.ReadDWord();
4419 _cur.
grffile->railtype_map[
id + i] = rt;
4437 int n = buf.ReadByte();
4438 for (
int j = 0; j != n; j++) {
4443 GrfMsg(1,
"RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set",
id + i);
4450 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4488 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.
grffile->roadtype_map;
4491 GrfMsg(1,
"RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4495 for (
int i = 0; i < numinfo; i++) {
4508 uint16_t str = buf.ReadWord();
4535 int n = buf.ReadByte();
4536 for (
int j = 0; j != n; j++) {
4537 RoadTypeLabel label = buf.ReadDWord();
4542 if (GetRoadTramType(resolved_rt) == rtt) {
4545 GrfMsg(1,
"RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4590 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4618 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
4621 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4625 for (
int i = 0; i < numinfo; i++) {
4628 RoadTypeLabel rtl = buf.ReadDWord();
4635 }
else if (GetRoadTramType(rt) != rtt) {
4636 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring",
id + numinfo);
4640 type_map[
id + i] = rt;
4657 int n = buf.ReadByte();
4658 for (
int j = 0; j != n; j++) {
4663 GrfMsg(1,
"RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set",
id + i);
4669 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4693 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_ROAD);
4698 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_TRAM);
4706 GrfMsg(1,
"AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", airtid + numinfo,
NUM_AIRPORTTILES_PER_GRF);
4711 if (_cur.
grffile->airtspec.size() < airtid + numinfo) _cur.
grffile->airtspec.resize(airtid + numinfo);
4713 for (
int i = 0; i < numinfo; i++) {
4714 auto &tsp = _cur.
grffile->airtspec[airtid + i];
4716 if (prop != 0x08 && tsp ==
nullptr) {
4717 GrfMsg(2,
"AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.", airtid + i);
4723 uint8_t subs_id = buf.ReadByte();
4726 GrfMsg(2,
"AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id, airtid + i);
4731 if (tsp ==
nullptr) {
4734 tsp->enabled =
true;
4738 tsp->grf_prop.local_id = airtid + i;
4739 tsp->grf_prop.subst_id = subs_id;
4740 tsp->grf_prop.grfid = _cur.
grffile->grfid;
4741 tsp->grf_prop.grffile = _cur.
grffile;
4748 uint8_t
override = buf.ReadByte();
4752 GrfMsg(2,
"AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.",
override, airtid + i);
4756 _airporttile_mngr.
Add(airtid + i, _cur.
grffile->grfid,
override);
4761 tsp->callback_mask = buf.ReadByte();
4765 tsp->animation.frames = buf.ReadByte();
4766 tsp->animation.status = buf.ReadByte();
4770 tsp->animation.speed = buf.ReadByte();
4774 tsp->animation.triggers = buf.ReadByte();
4831 GrfMsg(1,
"RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring",
id + numinfo,
NUM_ROADSTOPS_PER_GRF);
4835 if (_cur.
grffile->roadstops.size() <
id + numinfo) _cur.
grffile->roadstops.resize(
id + numinfo);
4837 for (
int i = 0; i < numinfo; i++) {
4838 auto &rs = _cur.
grffile->roadstops[
id + i];
4840 if (rs ==
nullptr && prop != 0x08) {
4841 GrfMsg(1,
"RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring",
id + i);
4843 if (cir > ret) ret = cir;
4849 if (rs ==
nullptr) {
4850 rs = std::make_unique<RoadStopSpec>();
4853 uint32_t classid = buf.ReadDWord();
4879 rs->animation.frames = buf.ReadByte();
4880 rs->animation.status = buf.ReadByte();
4884 rs->animation.speed = buf.ReadByte();
4888 rs->animation.triggers = buf.ReadWord();
4892 rs->callback_mask = buf.ReadByte();
4896 rs->flags = (uint16_t)buf.ReadDWord();
4900 rs->build_cost_multiplier = buf.ReadByte();
4901 rs->clear_cost_multiplier = buf.ReadByte();
4913static bool HandleChangeInfoResult(
const char *caller,
ChangeInfoResult cir, uint8_t feature, uint8_t property)
4916 default: NOT_REACHED();
4926 GrfMsg(1,
"{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
4930 GrfMsg(0,
"{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
4943static void FeatureChangeInfo(
ByteReader &buf)
4956 static const VCI_Handler handler[] = {
4974 AirportTilesChangeInfo,
4979 static_assert(GSF_END ==
lengthof(handler));
4981 uint8_t feature = buf.ReadByte();
4982 uint8_t numprops = buf.ReadByte();
4983 uint numinfo = buf.ReadByte();
4984 uint engine = buf.ReadExtendedByte();
4986 if (feature >= GSF_END) {
4987 GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4991 GrfMsg(6,
"FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
4992 feature, numprops, engine, numinfo);
4994 if (handler[feature] ==
nullptr) {
4995 if (feature != GSF_CARGOES) GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
5002 while (numprops-- && buf.HasData()) {
5003 uint8_t prop = buf.ReadByte();
5006 if (HandleChangeInfoResult(
"FeatureChangeInfo", cir, feature, prop))
return;
5013 uint8_t feature = buf.ReadByte();
5014 uint8_t numprops = buf.ReadByte();
5015 uint numinfo = buf.ReadByte();
5016 buf.ReadExtendedByte();
5018 if (feature == GSF_BRIDGES && numprops == 1) {
5019 uint8_t prop = buf.ReadByte();
5022 if (prop == 0x0D)
return;
5023 }
else if (feature == GSF_GLOBALVAR && numprops == 1) {
5024 uint8_t prop = buf.ReadByte();
5027 bool is_safe =
true;
5028 for (uint i = 0; i < numinfo; i++) {
5029 uint32_t s = buf.ReadDWord();
5037 if (is_safe)
return;
5048static void ReserveChangeInfo(
ByteReader &buf)
5050 uint8_t feature = buf.ReadByte();
5052 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES)
return;
5054 uint8_t numprops = buf.ReadByte();
5055 uint8_t numinfo = buf.ReadByte();
5056 uint8_t index = buf.ReadExtendedByte();
5058 while (numprops-- && buf.HasData()) {
5059 uint8_t prop = buf.ReadByte();
5063 default: NOT_REACHED();
5069 cir = GlobalVarReserveInfo(index, numinfo, prop, buf);
5073 cir = RailTypeReserveInfo(index, numinfo, prop, buf);
5077 cir = RoadTypeReserveInfo(index, numinfo, prop, buf);
5081 cir = TramTypeReserveInfo(index, numinfo, prop, buf);
5085 if (HandleChangeInfoResult(
"ReserveChangeInfo", cir, feature, prop))
return;
5106 uint8_t feature = buf.ReadByte();
5107 uint16_t num_sets = buf.ReadByte();
5108 uint16_t first_set = 0;
5110 if (num_sets == 0 && buf.HasData(3)) {
5113 first_set = buf.ReadExtendedByte();
5114 num_sets = buf.ReadExtendedByte();
5116 uint16_t num_ents = buf.ReadExtendedByte();
5118 if (feature >= GSF_END) {
5120 GrfMsg(1,
"NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.
skip_sprites);
5126 GrfMsg(7,
"New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
5127 _cur.
spriteid, feature, num_sets, num_ents, num_sets * num_ents
5130 for (
int i = 0; i < num_sets * num_ents; i++) {
5140 uint16_t num_sets = buf.ReadByte();
5142 if (num_sets == 0 && buf.HasData(3)) {
5145 buf.ReadExtendedByte();
5146 num_sets = buf.ReadExtendedByte();
5148 uint16_t num_ents = buf.ReadExtendedByte();
5152 GrfMsg(3,
"SkipAct1: Skipping {} sprites", _cur.
skip_sprites);
5155using CachedCallback = std::pair<uint16_t, SpriteGroupID>;
5158static const SpriteGroup *GetCallbackResultGroup(uint16_t value)
5162 if (_cur.
grffile->grf_version < 8 &&
GB(value, 8, 8) == 0xFF) {
5181static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5183 if (
HasBit(groupid, 15))
return GetCallbackResultGroup(groupid);
5185 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5186 GrfMsg(1,
"GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
5190 return _cur.spritegroups[groupid];
5203 if (
HasBit(spriteid, 15))
return GetCallbackResultGroup(spriteid);
5206 GrfMsg(1,
"CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5211 uint num_sprites = _cur.
GetNumEnts(feature, spriteid);
5214 assert(spriteset_start + num_sprites <= _cur.
spriteid);
5235 uint8_t feature = buf.ReadByte();
5236 if (feature >= GSF_END) {
5237 GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5241 uint8_t setid = buf.ReadByte();
5242 uint8_t type = buf.ReadByte();
5266 switch (
GB(type, 2, 2)) {
5267 default: NOT_REACHED();
5268 case 0: group->size = DSG_SIZE_BYTE; varsize = 1;
break;
5269 case 1: group->size = DSG_SIZE_WORD; varsize = 2;
break;
5270 case 2: group->size = DSG_SIZE_DWORD; varsize = 4;
break;
5280 adjust.variable = buf.ReadByte();
5281 if (adjust.variable == 0x7E) {
5283 adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5288 varadjust = buf.ReadByte();
5289 adjust.shift_num =
GB(varadjust, 0, 5);
5290 adjust.type = (DeterministicSpriteGroupAdjustType)
GB(varadjust, 6, 2);
5291 adjust.and_mask = buf.ReadVarSize(varsize);
5293 if (adjust.type != DSGA_TYPE_NONE) {
5294 adjust.add_val = buf.ReadVarSize(varsize);
5295 adjust.divmod_val = buf.ReadVarSize(varsize);
5296 if (adjust.divmod_val == 0) adjust.divmod_val = 1;
5299 adjust.divmod_val = 0;
5303 }
while (
HasBit(varadjust, 5));
5305 std::vector<DeterministicSpriteGroupRange> ranges;
5306 ranges.resize(buf.ReadByte());
5307 for (
auto &range : ranges) {
5308 range.group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5309 range.low = buf.ReadVarSize(varsize);
5310 range.high = buf.ReadVarSize(varsize);
5313 group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5314 group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5316 group->calculated_result = ranges.empty();
5319 std::vector<uint32_t> bounds;
5320 bounds.reserve(ranges.size());
5321 for (
const auto &range : ranges) {
5322 bounds.push_back(range.low);
5323 if (range.high != UINT32_MAX) bounds.push_back(range.high + 1);
5325 std::sort(bounds.begin(), bounds.end());
5326 bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5328 std::vector<const SpriteGroup *> target;
5329 target.reserve(bounds.size());
5330 for (
const auto &bound : bounds) {
5332 for (
const auto &range : ranges) {
5333 if (range.low <= bound && bound <= range.high) {
5338 target.push_back(t);
5340 assert(target.size() == bounds.size());
5342 for (uint j = 0; j < bounds.size(); ) {
5343 if (target[j] != group->default_group) {
5345 r.group = target[j];
5347 while (j < bounds.size() && target[j] == r.group) {
5350 r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5372 group->count = buf.ReadByte();
5375 uint8_t triggers = buf.ReadByte();
5376 group->triggers =
GB(triggers, 0, 7);
5377 group->
cmp_mode =
HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
5380 uint8_t num_groups = buf.ReadByte();
5382 GrfMsg(1,
"NewSpriteGroup: Random Action 2 nrand should be power of 2");
5385 group->
groups.reserve(num_groups);
5386 for (uint i = 0; i < num_groups; i++) {
5387 group->
groups.push_back(GetGroupFromGroupID(setid, type, buf.ReadWord()));
5398 case GSF_ROADVEHICLES:
5409 uint8_t num_loaded = type;
5410 uint8_t num_loading = buf.ReadByte();
5413 GrfMsg(0,
"NewSpriteGroup: No sprite set to work on! Skipping");
5417 GrfMsg(6,
"NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5418 setid, num_loaded, num_loading);
5420 if (num_loaded + num_loading == 0) {
5421 GrfMsg(1,
"NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5425 if (num_loaded + num_loading == 1) {
5427 uint16_t spriteid = buf.ReadWord();
5429 GrfMsg(8,
"NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5433 std::vector<uint16_t> loaded;
5434 std::vector<uint16_t> loading;
5436 loaded.reserve(num_loaded);
5437 for (uint i = 0; i < num_loaded; i++) {
5438 loaded.push_back(buf.ReadWord());
5439 GrfMsg(8,
"NewSpriteGroup: + rg->loaded[{}] = subset {}", i, loaded[i]);
5442 loading.reserve(num_loading);
5443 for (uint i = 0; i < num_loading; i++) {
5444 loading.push_back(buf.ReadWord());
5445 GrfMsg(8,
"NewSpriteGroup: + rg->loading[{}] = subset {}", i, loading[i]);
5448 bool loaded_same = !loaded.empty() && std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end();
5449 bool loading_same = !loading.empty() && std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end();
5450 if (loaded_same && loading_same && loaded[0] == loading[0]) {
5453 GrfMsg(8,
"NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5462 if (loaded_same && loaded.size() > 1) loaded.resize(1);
5463 group->
loaded.reserve(loaded.size());
5464 for (uint16_t spriteid : loaded) {
5466 group->
loaded.push_back(t);
5469 if (loading_same && loading.size() > 1) loading.resize(1);
5470 group->
loading.reserve(loading.size());
5471 for (uint16_t spriteid : loading) {
5480 case GSF_AIRPORTTILES:
5482 case GSF_INDUSTRYTILES:
5483 case GSF_ROADSTOPS: {
5484 uint8_t num_building_sprites = std::max((uint8_t)1, type);
5492 if (
ReadSpriteLayout(buf, num_building_sprites,
true, feature,
false, type == 0, &group->dts))
return;
5496 case GSF_INDUSTRIES: {
5498 GrfMsg(1,
"NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5516 group->again = buf.ReadByte();
5517 }
else if (type == 1) {
5526 group->again = buf.ReadByte();
5527 }
else if (type == 2) {
5531 error->
data =
"too many inputs (max 16)";
5534 for (uint i = 0; i < group->
num_input; i++) {
5535 uint8_t rawcargo = buf.ReadByte();
5544 error->
data =
"duplicate input cargo";
5553 error->
data =
"too many outputs (max 16)";
5556 for (uint i = 0; i < group->
num_output; i++) {
5557 uint8_t rawcargo = buf.ReadByte();
5564 error->
data =
"duplicate output cargo";
5570 group->again = buf.ReadByte();
5578 default: GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5583 _cur.spritegroups[setid] = act_group;
5603static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
5612 if (ctype >= cargo_list.size()) {
5613 GrfMsg(1,
"TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (
unsigned int)_cur.
grffile->
cargo_list.size() - 1);
5614 return INVALID_CARGO;
5620 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5621 return INVALID_CARGO;
5624 CargoID cid = GetCargoIDByLabel(cl);
5626 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));
5627 return INVALID_CARGO;
5630 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), cid);
5635static bool IsValidGroupID(uint16_t groupid,
const char *function)
5637 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5638 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
5645static void VehicleMapSpriteGroup(
ByteReader &buf, uint8_t feature, uint8_t idcount)
5647 static std::vector<EngineID> last_engines;
5648 bool wagover =
false;
5651 if (
HasBit(idcount, 7)) {
5654 idcount =
GB(idcount, 0, 7);
5656 if (last_engines.empty()) {
5657 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5661 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5663 last_engines.resize(idcount);
5666 std::vector<EngineID> engines;
5667 engines.reserve(idcount);
5668 for (uint i = 0; i < idcount; i++) {
5674 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, 0, 0);
5678 engines.push_back(e->
index);
5679 if (!wagover) last_engines[i] = engines[i];
5682 uint8_t cidcount = buf.ReadByte();
5683 for (uint c = 0; c < cidcount; c++) {
5684 uint8_t ctype = buf.ReadByte();
5685 uint16_t groupid = buf.ReadWord();
5686 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
5688 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5690 CargoID cid = TranslateCargo(feature, ctype);
5693 for (uint i = 0; i < idcount; i++) {
5696 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5699 SetWagonOverrideSprites(engine, cid, _cur.spritegroups[groupid], last_engines);
5701 SetCustomEngineSprites(engine, cid, _cur.spritegroups[groupid]);
5706 uint16_t groupid = buf.ReadWord();
5707 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
5709 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
5711 for (uint i = 0; i < idcount; i++) {
5724static void CanalMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5726 std::vector<uint16_t> cfs;
5727 cfs.reserve(idcount);
5728 for (uint i = 0; i < idcount; i++) {
5729 cfs.push_back(buf.ReadExtendedByte());
5732 uint8_t cidcount = buf.ReadByte();
5733 buf.Skip(cidcount * 3);
5735 uint16_t groupid = buf.ReadWord();
5736 if (!IsValidGroupID(groupid,
"CanalMapSpriteGroup"))
return;
5738 for (
auto &cf : cfs) {
5740 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5750static void StationMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5752 if (_cur.
grffile->stations.empty()) {
5753 GrfMsg(1,
"StationMapSpriteGroup: No stations defined, skipping");
5757 std::vector<uint16_t> stations;
5758 stations.reserve(idcount);
5759 for (uint i = 0; i < idcount; i++) {
5760 stations.push_back(buf.ReadExtendedByte());
5763 uint8_t cidcount = buf.ReadByte();
5764 for (uint c = 0; c < cidcount; c++) {
5765 uint8_t ctype = buf.ReadByte();
5766 uint16_t groupid = buf.ReadWord();
5767 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
continue;
5769 ctype = TranslateCargo(GSF_STATIONS, ctype);
5772 for (
auto &station : stations) {
5775 if (statspec ==
nullptr) {
5776 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5784 uint16_t groupid = buf.ReadWord();
5785 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
return;
5787 for (
auto &station : stations) {
5790 if (statspec ==
nullptr) {
5791 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5796 GrfMsg(1,
"StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
5809static void TownHouseMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5811 if (_cur.
grffile->housespec.empty()) {
5812 GrfMsg(1,
"TownHouseMapSpriteGroup: No houses defined, skipping");
5816 std::vector<uint16_t> houses;
5817 houses.reserve(idcount);
5818 for (uint i = 0; i < idcount; i++) {
5819 houses.push_back(buf.ReadExtendedByte());
5823 uint8_t cidcount = buf.ReadByte();
5824 buf.Skip(cidcount * 3);
5826 uint16_t groupid = buf.ReadWord();
5827 if (!IsValidGroupID(groupid,
"TownHouseMapSpriteGroup"))
return;
5829 for (
auto &house : houses) {
5832 if (hs ==
nullptr) {
5833 GrfMsg(1,
"TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
5841static void IndustryMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5843 if (_cur.
grffile->industryspec.empty()) {
5844 GrfMsg(1,
"IndustryMapSpriteGroup: No industries defined, skipping");
5848 std::vector<uint16_t> industries;
5849 industries.reserve(idcount);
5850 for (uint i = 0; i < idcount; i++) {
5851 industries.push_back(buf.ReadExtendedByte());
5855 uint8_t cidcount = buf.ReadByte();
5856 buf.Skip(cidcount * 3);
5858 uint16_t groupid = buf.ReadWord();
5859 if (!IsValidGroupID(groupid,
"IndustryMapSpriteGroup"))
return;
5861 for (
auto &industry : industries) {
5864 if (indsp ==
nullptr) {
5865 GrfMsg(1,
"IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
5873static void IndustrytileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5875 if (_cur.
grffile->indtspec.empty()) {
5876 GrfMsg(1,
"IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
5880 std::vector<uint16_t> indtiles;
5881 indtiles.reserve(idcount);
5882 for (uint i = 0; i < idcount; i++) {
5883 indtiles.push_back(buf.ReadExtendedByte());
5887 uint8_t cidcount = buf.ReadByte();
5888 buf.Skip(cidcount * 3);
5890 uint16_t groupid = buf.ReadWord();
5891 if (!IsValidGroupID(groupid,
"IndustrytileMapSpriteGroup"))
return;
5893 for (
auto &indtile : indtiles) {
5896 if (indtsp ==
nullptr) {
5897 GrfMsg(1,
"IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
5905static void CargoMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5907 std::vector<uint16_t> cargoes;
5908 cargoes.reserve(idcount);
5909 for (uint i = 0; i < idcount; i++) {
5910 cargoes.push_back(buf.ReadExtendedByte());
5914 uint8_t cidcount = buf.ReadByte();
5915 buf.Skip(cidcount * 3);
5917 uint16_t groupid = buf.ReadWord();
5918 if (!IsValidGroupID(groupid,
"CargoMapSpriteGroup"))
return;
5920 for (
auto &cid : cargoes) {
5922 GrfMsg(1,
"CargoMapSpriteGroup: Cargo ID {} out of range, skipping", cid);
5928 cs->group = _cur.spritegroups[groupid];
5932static void ObjectMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5934 if (_cur.
grffile->objectspec.empty()) {
5935 GrfMsg(1,
"ObjectMapSpriteGroup: No object tiles defined, skipping");
5939 std::vector<uint16_t> objects;
5940 objects.reserve(idcount);
5941 for (uint i = 0; i < idcount; i++) {
5942 objects.push_back(buf.ReadExtendedByte());
5945 uint8_t cidcount = buf.ReadByte();
5946 for (uint c = 0; c < cidcount; c++) {
5947 uint8_t ctype = buf.ReadByte();
5948 uint16_t groupid = buf.ReadWord();
5949 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
continue;
5952 if (ctype != 0xFF) {
5953 GrfMsg(1,
"ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
5957 for (
auto &
object : objects) {
5960 if (spec ==
nullptr) {
5961 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5969 uint16_t groupid = buf.ReadWord();
5970 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
return;
5972 for (
auto &
object : objects) {
5975 if (spec ==
nullptr) {
5976 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5981 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} mapped multiple times, skipping",
object);
5992static void RailTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5994 std::vector<uint8_t> railtypes;
5995 railtypes.reserve(idcount);
5996 for (uint i = 0; i < idcount; i++) {
5997 uint16_t
id = buf.ReadExtendedByte();
5998 railtypes.push_back(id < RAILTYPE_END ? _cur.grffile->railtype_map[
id] :
INVALID_RAILTYPE);
6001 uint8_t cidcount = buf.ReadByte();
6002 for (uint c = 0; c < cidcount; c++) {
6003 uint8_t ctype = buf.ReadByte();
6004 uint16_t groupid = buf.ReadWord();
6005 if (!IsValidGroupID(groupid,
"RailTypeMapSpriteGroup"))
continue;
6007 if (ctype >= RTSG_END)
continue;
6010 for (
auto &railtype : railtypes) {
6015 rti->
group[ctype] = _cur.spritegroups[groupid];
6024static void RoadTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount, RoadTramType rtt)
6026 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
6028 std::vector<uint8_t> roadtypes;
6029 roadtypes.reserve(idcount);
6030 for (uint i = 0; i < idcount; i++) {
6031 uint16_t
id = buf.ReadExtendedByte();
6035 uint8_t cidcount = buf.ReadByte();
6036 for (uint c = 0; c < cidcount; c++) {
6037 uint8_t ctype = buf.ReadByte();
6038 uint16_t groupid = buf.ReadWord();
6039 if (!IsValidGroupID(groupid,
"RoadTypeMapSpriteGroup"))
continue;
6041 if (ctype >= ROTSG_END)
continue;
6044 for (
auto &roadtype : roadtypes) {
6049 rti->
group[ctype] = _cur.spritegroups[groupid];
6058static void AirportMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6060 if (_cur.
grffile->airportspec.empty()) {
6061 GrfMsg(1,
"AirportMapSpriteGroup: No airports defined, skipping");
6065 std::vector<uint16_t> airports;
6066 airports.reserve(idcount);
6067 for (uint i = 0; i < idcount; i++) {
6068 airports.push_back(buf.ReadExtendedByte());
6072 uint8_t cidcount = buf.ReadByte();
6073 buf.Skip(cidcount * 3);
6075 uint16_t groupid = buf.ReadWord();
6076 if (!IsValidGroupID(groupid,
"AirportMapSpriteGroup"))
return;
6078 for (
auto &airport : airports) {
6081 if (as ==
nullptr) {
6082 GrfMsg(1,
"AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6090static void AirportTileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6092 if (_cur.
grffile->airtspec.empty()) {
6093 GrfMsg(1,
"AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6097 std::vector<uint16_t> airptiles;
6098 airptiles.reserve(idcount);
6099 for (uint i = 0; i < idcount; i++) {
6100 airptiles.push_back(buf.ReadExtendedByte());
6104 uint8_t cidcount = buf.ReadByte();
6105 buf.Skip(cidcount * 3);
6107 uint16_t groupid = buf.ReadWord();
6108 if (!IsValidGroupID(groupid,
"AirportTileMapSpriteGroup"))
return;
6110 for (
auto &airptile : airptiles) {
6113 if (airtsp ==
nullptr) {
6114 GrfMsg(1,
"AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6122static void RoadStopMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6124 if (_cur.
grffile->roadstops.empty()) {
6125 GrfMsg(1,
"RoadStopMapSpriteGroup: No roadstops defined, skipping");
6129 std::vector<uint16_t> roadstops;
6130 roadstops.reserve(idcount);
6131 for (uint i = 0; i < idcount; i++) {
6132 roadstops.push_back(buf.ReadExtendedByte());
6135 uint8_t cidcount = buf.ReadByte();
6136 for (uint c = 0; c < cidcount; c++) {
6137 uint8_t ctype = buf.ReadByte();
6138 uint16_t groupid = buf.ReadWord();
6139 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
continue;
6141 ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6144 for (
auto &roadstop : roadstops) {
6147 if (roadstopspec ==
nullptr) {
6148 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6156 uint16_t groupid = buf.ReadWord();
6157 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
return;
6159 for (
auto &roadstop : roadstops) {
6162 if (roadstopspec ==
nullptr) {
6163 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6168 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6181static void FeatureMapSpriteGroup(
ByteReader &buf)
6197 uint8_t feature = buf.ReadByte();
6198 uint8_t idcount = buf.ReadByte();
6200 if (feature >= GSF_END) {
6201 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6209 uint16_t groupid = buf.ReadWord();
6210 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
6212 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6221 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6225 case GSF_ROADVEHICLES:
6228 VehicleMapSpriteGroup(buf, feature, idcount);
6232 CanalMapSpriteGroup(buf, idcount);
6236 StationMapSpriteGroup(buf, idcount);
6240 TownHouseMapSpriteGroup(buf, idcount);
6243 case GSF_INDUSTRIES:
6244 IndustryMapSpriteGroup(buf, idcount);
6247 case GSF_INDUSTRYTILES:
6248 IndustrytileMapSpriteGroup(buf, idcount);
6252 CargoMapSpriteGroup(buf, idcount);
6256 AirportMapSpriteGroup(buf, idcount);
6260 ObjectMapSpriteGroup(buf, idcount);
6264 RailTypeMapSpriteGroup(buf, idcount);
6268 RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6272 RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6275 case GSF_AIRPORTTILES:
6276 AirportTileMapSpriteGroup(buf, idcount);
6280 RoadStopMapSpriteGroup(buf, idcount);
6284 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6308 bool new_scheme = _cur.
grffile->grf_version >= 7;
6310 uint8_t feature = buf.ReadByte();
6311 if (feature >= GSF_END && feature != 0x48) {
6312 GrfMsg(1,
"FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6316 uint8_t lang = buf.ReadByte();
6317 uint8_t num = buf.ReadByte();
6318 bool generic =
HasBit(lang, 7);
6321 id = buf.ReadWord();
6322 }
else if (feature <= GSF_AIRCRAFT) {
6323 id = buf.ReadExtendedByte();
6325 id = buf.ReadByte();
6330 uint16_t endid =
id + num;
6332 GrfMsg(6,
"FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6333 id, endid, feature, lang);
6335 for (;
id < endid && buf.HasData();
id++) {
6336 const std::string_view name = buf.ReadString();
6337 GrfMsg(8,
"FeatureNewName: 0x{:04X} <- {}",
id,
StrMakeValid(name));
6341 case GSF_ROADVEHICLES:
6346 if (e ==
nullptr)
break;
6360 switch (
GB(
id, 8, 8)) {
6362 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6363 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6371 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6372 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6379 if (
GB(
id, 0, 8) >= _cur.
grffile->airtspec.size() || _cur.
grffile->airtspec[
GB(
id, 0, 8)] ==
nullptr) {
6380 GrfMsg(1,
"FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring",
GB(
id, 0, 8));
6387 if (
GB(
id, 0, 8) >= _cur.
grffile->housespec.size() || _cur.
grffile->housespec[
GB(
id, 0, 8)] ==
nullptr) {
6388 GrfMsg(1,
"FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.",
GB(
id, 0, 8));
6390 _cur.
grffile->housespec[
GB(
id, 0, 8)]->building_name =
AddGRFString(_cur.
grffile->grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
6395 GrfMsg(7,
"FeatureNewName: Unsupported ID (0x{:04X})",
id);
6414 if (offset >= max_sprites) {
6415 GrfMsg(1,
"GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6416 uint orig_num = num;
6421 if (offset + num > max_sprites) {
6422 GrfMsg(4,
"GraphicsNew: {} sprite overflow, truncating...", name);
6423 uint orig_num = num;
6424 num = std::max(max_sprites - offset, 0);
6425 return orig_num - num;
6439 {
A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT,
"Signal graphics" },
6441 {
A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT,
"Foundation graphics" },
6481 uint8_t type = buf.ReadByte();
6482 uint16_t num = buf.ReadExtendedByte();
6483 uint16_t offset =
HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6489 GrfMsg(2,
"GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6506 GrfMsg(2,
"GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6517 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->
name, type);
6524 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->
name, type, action5_type->
min_sprites, num);
6534 GrfMsg(2,
"GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->
name, type, replace);
6546 bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= SPR_ONEWAY_SLOPE_N_OFFSET));
6548 for (; num > 0; num--) {
6552 if (dup_oneway_sprites) {
6553 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_N_OFFSET);
6554 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_S_OFFSET);
6570 GrfMsg(3,
"SkipAct5: Skipping {} sprites", _cur.
skip_sprites);
6623 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6653 *value = _game_mode;
6687 *value =
Clamp(snowline * (grffile->grf_version >= 8 ? 1 :
TILE_HEIGHT), 0, 0xFE);
6696 *value = _openttd_newgrf_version;
6711 default:
return false;
6715static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
6734 if (cond_val ==
nullptr) {
6738 uint32_t index = *cond_val / 0x20;
6754 GrfMsg(1,
"Unsupported in-game variable 0x{:02X}", param);
6775 size_t pos = file.
GetPos();
6781 GrfMsg(2,
"CfgApply: Ignoring (next sprite is real, unsupported)");
6784 file.
SeekTo(pos, SEEK_SET);
6790 std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
6793 if (preload_sprite.empty()) {
6794 preload_sprite.resize(num);
6795 file.
ReadBlock(preload_sprite.data(), num);
6799 file.
SeekTo(pos, SEEK_SET);
6810 param_num = buf.ReadByte();
6811 if (param_num == 0xFF)
break;
6815 param_size = buf.ReadByte();
6819 add_value =
HasBit(param_size, 7);
6820 param_size =
GB(param_size, 0, 7);
6823 offset = buf.ReadExtendedByte();
6827 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= std::size(_cur.
grffile->param)) {
6828 GrfMsg(2,
"CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
6832 GrfMsg(8,
"CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
6835 for (i = 0; i < param_size && offset + i < num; i++) {
6836 uint32_t value = GetParamVal(param_num + i / 4,
nullptr);
6839 if (i % 4 == 0) carry =
false;
6842 uint new_value = preload_sprite[offset + i] +
GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
6843 preload_sprite[offset + i] =
GB(new_value, 0, 8);
6845 carry = new_value >= 256;
6847 preload_sprite[offset + i] =
GB(value, (i % 4) * 8, 8);
6879 uint32_t cond_val = 0;
6883 uint8_t param = buf.ReadByte();
6884 uint8_t paramsize = buf.ReadByte();
6885 uint8_t condtype = buf.ReadByte();
6892 switch (paramsize) {
6893 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord();
break;
6894 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF;
break;
6895 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF;
break;
6896 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF;
break;
6900 if (param < 0x80 && std::size(_cur.
grffile->param) <= param) {
6901 GrfMsg(7,
"SkipIf: Param {} undefined, skipping test", param);
6905 GrfMsg(7,
"SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
6910 if (condtype >= 0x0B) {
6941 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6943 }
else if (param == 0x88) {
6953 if (condtype != 10 && c ==
nullptr) {
6954 GrfMsg(7,
"SkipIf: GRFID 0x{:08X} unknown, skipping test",
BSWAP32(cond_val));
6981 default: GrfMsg(1,
"SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype);
return;
6985 uint32_t param_val = GetParamVal(param, &cond_val);
6987 case 0x00: result = !!(param_val & (1 << cond_val));
6989 case 0x01: result = !(param_val & (1 << cond_val));
6991 case 0x02: result = (param_val & mask) == cond_val;
6993 case 0x03: result = (param_val & mask) != cond_val;
6995 case 0x04: result = (param_val & mask) < cond_val;
6997 case 0x05: result = (param_val & mask) > cond_val;
6999 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
7004 GrfMsg(2,
"SkipIf: Not skipping sprites, test was false");
7008 uint8_t numsprites = buf.ReadByte();
7015 for (
const auto &label : _cur.grffile->labels) {
7016 if (label.label != numsprites)
continue;
7019 if (choice ==
nullptr) choice = &label;
7021 if (label.nfo_line > _cur.
nfo_line) {
7027 if (choice !=
nullptr) {
7028 GrfMsg(2,
"SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
7034 GrfMsg(2,
"SkipIf: Skipping {} sprites, test was true", numsprites);
7053 uint8_t grf_version = buf.ReadByte();
7054 uint32_t grfid = buf.ReadDWord();
7055 std::string_view name = buf.ReadString();
7059 if (grf_version < 2 || grf_version > 8) {
7069 if (buf.HasData()) {
7070 std::string_view info = buf.ReadString();
7088 uint8_t version = buf.ReadByte();
7089 uint32_t grfid = buf.ReadDWord();
7090 std::string_view name = buf.ReadString();
7093 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7097 if (_cur.
grffile->grfid != grfid) {
7098 Debug(grf, 0,
"GRFInfo: GRFID {:08X} in FILESCAN stage does not match GRFID {:08X} in INIT/RESERVE/ACTIVATION stage",
BSWAP32(_cur.
grffile->grfid),
BSWAP32(grfid));
7102 _cur.
grffile->grf_version = version;
7117 for (
const auto &grm_sprite : _grm_sprites) {
7118 if (grm_sprite.first.grfid != _cur.
grffile->grfid)
continue;
7119 if (grm_sprite.second.first <= first_sprite && grm_sprite.second.first + grm_sprite.second.second >= first_sprite + num_sprites)
return true;
7135 uint8_t num_sets = buf.ReadByte();
7137 for (uint i = 0; i < num_sets; i++) {
7138 uint8_t num_sprites = buf.ReadByte();
7139 uint16_t first_sprite = buf.ReadWord();
7141 GrfMsg(2,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7142 i, num_sprites, first_sprite
7148 GrfMsg(0,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7157 for (uint j = 0; j < num_sprites; j++) {
7158 SpriteID load_index = first_sprite + j;
7164 if (
IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7174 uint8_t num_sets = buf.ReadByte();
7176 for (uint i = 0; i < num_sets; i++) {
7183 GrfMsg(3,
"SkipActA: Skipping {} sprites", _cur.
skip_sprites);
7205 STR_NEWGRF_ERROR_VERSION_NUMBER,
7206 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
7207 STR_NEWGRF_ERROR_UNSET_SWITCH,
7208 STR_NEWGRF_ERROR_INVALID_PARAMETER,
7209 STR_NEWGRF_ERROR_LOAD_BEFORE,
7210 STR_NEWGRF_ERROR_LOAD_AFTER,
7211 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
7215 STR_NEWGRF_ERROR_MSG_INFO,
7216 STR_NEWGRF_ERROR_MSG_WARNING,
7217 STR_NEWGRF_ERROR_MSG_ERROR,
7218 STR_NEWGRF_ERROR_MSG_FATAL
7221 uint8_t severity = buf.ReadByte();
7222 uint8_t lang = buf.ReadByte();
7223 uint8_t message_id = buf.ReadByte();
7226 if (!CheckGrfLangID(lang, _cur.
grffile->grf_version))
return;
7230 if (!
HasBit(severity, 7) && _cur.
stage == GLS_INIT) {
7231 GrfMsg(7,
"GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.
stage);
7236 if (severity >=
lengthof(sevstr)) {
7237 GrfMsg(7,
"GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7239 }
else if (severity == 3) {
7248 if (message_id >=
lengthof(msgstr) && message_id != 0xFF) {
7249 GrfMsg(7,
"GRFLoadError: Invalid message id.");
7253 if (buf.Remaining() <= 1) {
7254 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7264 if (message_id == 0xFF) {
7266 if (buf.HasData()) {
7267 std::string_view message = buf.ReadString();
7271 GrfMsg(7,
"GRFLoadError: No custom message supplied.");
7275 error->
message = msgstr[message_id];
7278 if (buf.HasData()) {
7279 std::string_view data = buf.ReadString();
7283 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7284 error->
data.clear();
7288 for (uint i = 0; i < error->
param_value.size() && buf.HasData(); i++) {
7289 uint param_number = buf.ReadByte();
7301 if (!buf.HasData())
return;
7303 std::string_view text = buf.ReadString();
7310 uint8_t target = buf.ReadByte();
7313 if (target < 0x80 || target == 0x9E)
return;
7327static uint32_t GetPatchVariable(uint8_t param)
7337 case 0x0F:
return 0;
7353 case 0x11:
return SPR_2CCMAP_BASE;
7367 uint8_t map_bits = 0;
7370 uint8_t max_edge = std::max(log_X, log_Y);
7372 if (log_X == log_Y) {
7375 if (max_edge == log_Y)
SetBit(map_bits, 1);
7378 return (map_bits << 24) | (std::min(log_X, log_Y) << 20) | (max_edge << 16) |
7379 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
7388 return SPR_SLOPES_BASE;
7399 GrfMsg(2,
"ParamSet: Unknown Patch variable 0x{:02X}.", param);
7405static uint32_t PerformGRM(uint32_t *grm, uint16_t num_ids, uint16_t count, uint8_t op, uint8_t target,
const char *type)
7418 for (uint i = start; i < num_ids; i++) {
7422 if (op == 2 || op == 3)
break;
7427 if (size == count)
break;
7430 if (size == count) {
7432 if (op == 0 || op == 3) {
7433 GrfMsg(2,
"ParamSet: GRM: Reserving {} {} at {}", count, type, start);
7434 for (uint i = 0; i < count; i++) grm[start + i] = _cur.
grffile->grfid;
7440 if (op != 4 && op != 5) {
7442 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7447 GrfMsg(1,
"ParamSet: GRM: Unable to allocate {} {}", count, type);
7477 uint8_t target = buf.ReadByte();
7478 uint8_t oper = buf.ReadByte();
7479 uint32_t src1 = buf.ReadByte();
7480 uint32_t src2 = buf.ReadByte();
7483 if (buf.Remaining() >= 4) data = buf.ReadDWord();
7492 if (target < 0x80 && target < std::size(_cur.
grffile->param)) {
7493 GrfMsg(7,
"ParamSet: Param {} already defined, skipping", target);
7497 oper =
GB(oper, 0, 7);
7501 if (
GB(data, 0, 8) == 0xFF) {
7502 if (data == 0x0000FFFF) {
7504 src1 = GetPatchVariable(src1);
7508 uint8_t feature =
GB(data, 8, 8);
7509 uint16_t count =
GB(data, 16, 16);
7511 if (_cur.
stage == GLS_RESERVE) {
7512 if (feature == 0x08) {
7516 if (_cur.
spriteid + count >= 16384) {
7517 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7523 GrfMsg(4,
"ParamSet: GRM: Allocated {} sprites at {}", count, _cur.
spriteid);
7530 }
else if (_cur.
stage == GLS_ACTIVATION) {
7559 GrfMsg(4,
"ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7567 GrfMsg(1,
"ParamSet: GRM: Unsupported operation {} for general sprites", op);
7578 default: GrfMsg(1,
"ParamSet: GRM: Unsupported feature 0x{:X}", feature);
return;
7595 }
else if (src1 == 0xFE) {
7607 src1 = (src1 == 0xFF) ? data : GetParamVal(src1,
nullptr);
7608 src2 = (src2 == 0xFF) ? data : GetParamVal(src2,
nullptr);
7630 res = (int32_t)src1 * (int32_t)src2;
7634 if ((int32_t)src2 < 0) {
7635 res = src1 >> -(int32_t)src2;
7637 res = src1 << (src2 & 0x1F);
7642 if ((int32_t)src2 < 0) {
7643 res = (int32_t)src1 >> -(int32_t)src2;
7645 res = (int32_t)src1 << (src2 & 0x1F);
7669 res = (int32_t)src1 / (int32_t)src2;
7685 res = (int32_t)src1 % (int32_t)src2;
7689 default: GrfMsg(0,
"ParamSet: Unknown operation {}, skipping", oper);
return;
7718 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7729 uint32_t safe_bits = 0;
7730 SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
7739 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7743 if (target < 0x80) {
7745 if (target >= std::size(_cur.
grffile->param)) _cur.
grffile->param.resize(target + 1);
7746 _cur.
grffile->param[target] = res;
7748 GrfMsg(7,
"ParamSet: Skipping unknown target 0x{:02X}", target);
7762 uint8_t num = buf.ReadByte();
7764 for (uint i = 0; i < num; i++) {
7765 uint32_t grfid = buf.ReadDWord();
7787 uint8_t num = buf.ReadByte();
7789 for (uint i = 0; i < num; i++) {
7790 uint32_t grfid = buf.ReadDWord();
7794 if (file !=
nullptr && file != _cur.
grfconfig) {
7795 GrfMsg(2,
"GRFInhibit: Deactivating file '{}'", file->
filename);
7812 uint32_t grfid = _cur.
grffile->grfid;
7816 uint8_t
id = buf.ReadByte();
7817 GrfMsg(6,
"FeatureTownName: definition 0x{:02X}",
id & 0x7F);
7822 bool new_scheme = _cur.
grffile->grf_version >= 7;
7824 uint8_t lang = buf.ReadByte();
7830 std::string_view name = buf.ReadString();
7833 GrfMsg(6,
"FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
7835 style =
AddGRFString(grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
7837 lang = buf.ReadByte();
7838 }
while (lang != 0);
7839 townname->
styles.emplace_back(style,
id);
7842 uint8_t parts = buf.ReadByte();
7843 GrfMsg(6,
"FeatureTownName: {} parts", parts);
7846 for (uint partnum = 0; partnum < parts; partnum++) {
7848 uint8_t texts = buf.ReadByte();
7849 partlist.
bitstart = buf.ReadByte();
7850 partlist.
bitcount = buf.ReadByte();
7852 GrfMsg(6,
"FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.
bitstart, partlist.
bitcount);
7854 partlist.
parts.reserve(texts);
7855 for (uint textnum = 0; textnum < texts; textnum++) {
7857 part.
prob = buf.ReadByte();
7860 uint8_t ref_id = buf.ReadByte();
7862 GrfMsg(0,
"FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
7863 DelGRFTownName(grfid);
7868 GrfMsg(6,
"FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.
prob & 0x7F);
7870 std::string_view text = buf.ReadString();
7872 GrfMsg(6,
"FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.
text, part.
prob);
7876 GrfMsg(6,
"FeatureTownName: part {}, total probability {}", partnum, partlist.
maxprob);
7888 uint8_t nfo_label = buf.ReadByte();
7892 GrfMsg(2,
"DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
7906 if (file ==
nullptr || file->sound_offset == 0) {
7907 GrfMsg(1,
"ImportGRFSound: Source file not available");
7911 if (sound_id >= file->num_sounds) {
7912 GrfMsg(1,
"ImportGRFSound: Sound effect {} is invalid", sound_id);
7916 GrfMsg(2,
"ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
7918 *sound = *GetSound(file->sound_offset + sound_id);
7921 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7922 sound->priority = 0;
7933 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7934 sound->priority = 0;
7936 if (offs != SIZE_MAX) {
7938 sound->file = _cur.
file;
7939 sound->file_offset = offs;
7940 sound->source = SoundSource::NewGRF;
7952 uint16_t num = buf.ReadWord();
7953 if (num == 0)
return;
7956 if (_cur.
grffile->sound_offset == 0) {
7957 _cur.
grffile->sound_offset = GetNumSounds();
7958 _cur.
grffile->num_sounds = num;
7961 sound = GetSound(_cur.
grffile->sound_offset);
7966 for (
int i = 0; i < num; i++) {
7971 bool invalid = i >= _cur.
grffile->num_sounds;
7973 size_t offs = file.
GetPos();
7978 if (grf_container_version >= 2 && type == 0xFD) {
7981 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
7983 }
else if (len != 4) {
7984 GrfMsg(1,
"GRFSound: Invalid sprite section import");
7994 GrfMsg(1,
"GRFSound: Unexpected RealSprite found, skipping");
8001 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
8009 if (_cur.
stage == GLS_INIT) {
8010 if (grf_container_version >= 2) {
8011 GrfMsg(1,
"GRFSound: Inline sounds are not supported for container version >= 2");
8020 if (_cur.
stage == GLS_ACTIVATION) {
8023 if (file.
ReadByte() != 0) GrfMsg(1,
"GRFSound: Import type mismatch");
8031 GrfMsg(1,
"GRFSound: Unexpected Action {:x} found, skipping", action);
8047 GrfMsg(3,
"SkipAct11: Skipping {} sprites", _cur.
skip_sprites);
8060 uint8_t num_def = buf.ReadByte();
8062 for (uint i = 0; i < num_def; i++) {
8064 uint8_t num_char = buf.ReadByte();
8065 uint16_t base_char = buf.ReadWord();
8067 if (size >= FS_END) {
8068 GrfMsg(1,
"LoadFontGlyph: Size {} is not supported, ignoring", size);
8071 GrfMsg(7,
"LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8073 for (uint c = 0; c < num_char; c++) {
8091 uint8_t num_def = buf.ReadByte();
8093 for (uint i = 0; i < num_def; i++) {
8104 GrfMsg(3,
"SkipAct12: Skipping {} sprites", _cur.
skip_sprites);
8117 uint32_t grfid = buf.ReadDWord();
8120 GrfMsg(7,
"TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13",
BSWAP32(grfid));
8129 error->
data =
GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8139 uint8_t language = _cur.
grffile->grf_version >= 8 ? buf.ReadByte() : 0x7F;
8140 uint8_t num_strings = buf.ReadByte();
8141 uint16_t first_id = buf.ReadWord();
8143 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
8144 GrfMsg(7,
"TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
8148 for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8149 std::string_view
string = buf.ReadString();
8151 if (
string.empty()) {
8152 GrfMsg(7,
"TranslateGRFString: Ignoring empty string.");
8156 AddGRFString(grfid, first_id + i, language,
true,
true,
string, STR_UNDEFINED);
8185 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8197 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8200 char data = buf.ReadByte();
8208 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8223 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8226 char data = buf.ReadByte();
8232 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8245 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8258 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8263 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8294 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8301 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8311 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8313 }
else if (len != 8) {
8314 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8317 uint32_t min_value = buf.ReadDWord();
8318 uint32_t max_value = buf.ReadDWord();
8319 if (min_value <= max_value) {
8323 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8332 if (len < 1 || len > 3) {
8333 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
8336 uint8_t param_nr = buf.ReadByte();
8337 if (param_nr >= GRFConfig::MAX_NUM_PARAMS) {
8338 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8354 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8390 this->handler.data = handler;
8402 this->handler.text = handler;
8414 this->handler.call_handler =
true;
8415 this->handler.u.branch = handler;
8427 this->handler.call_handler =
false;
8428 this->handler.u.subtags =
subtags;
8457 uint8_t type = buf.ReadByte();
8459 uint32_t
id = buf.ReadDWord();
8461 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8463 type = buf.ReadByte();
8467 uint8_t langid = buf.ReadByte();
8468 std::string_view name_string = buf.ReadString();
8479 type = buf.ReadByte();
8504 uint8_t type = buf.ReadByte();
8506 uint32_t
id = buf.ReadDWord();
8508 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8510 type = buf.ReadByte();
8523 type = buf.ReadByte();
8560 uint8_t new_type = buf.ReadByte();
8561 while (new_type != 0) {
8564 new_type = buf.ReadByte();
8575 uint16_t size = buf.ReadWord();
8599 while ((tag = &subtags[i++])->type != 0) {
8602 default: NOT_REACHED();
8605 uint8_t langid = buf.ReadByte();
8606 return tag->handler.
text(langid, buf.ReadString());
8610 size_t len = buf.ReadWord();
8611 if (buf.Remaining() < len)
return false;
8612 return tag->handler.
data(len, buf);
8617 return tag->handler.u.
branch(buf);
8619 return HandleNodes(buf, tag->handler.u.
subtags);
8623 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
8635 uint8_t type = buf.ReadByte();
8637 uint32_t
id = buf.ReadDWord();
8638 if (!
HandleNode(type,
id, buf, subtags))
return false;
8639 type = buf.ReadByte();
8760 file->stations.clear();
8768 file->housespec.clear();
8776 file->airportspec.clear();
8777 file->airtspec.clear();
8785 file->industryspec.clear();
8786 file->indtspec.clear();
8794 file->objectspec.clear();
8798static void ResetCustomRoadStops()
8801 file->roadstops.clear();
8830 CleanUpGRFTownNames();
8890 ResetCustomRoadStops();
8916 _grf_id_overrides.clear();
8918 InitializeSoundPool();
8948 if (!cs->IsValid())
continue;
8963 if (newfile !=
nullptr) {
8969 newfile =
new GRFFile(config);
8987 for (
Price i = PR_BEGIN; i < PR_END; i++) {
9007 this->param = config->
param;
9018 CargoID cid = GetCargoIDByLabel(label);
9019 if (cid != INVALID_CARGO)
return label;
9039 default: NOT_REACHED();
9044 return std::visit(visitor{}, label);
9052 CargoTypes original_known_cargoes = 0;
9060 bool only_defaultcargo;
9068 if (
_gted[engine].defaultcargo_grf ==
nullptr) {
9071 static constexpr uint8_t T = 1 << LT_TEMPERATE;
9072 static constexpr uint8_t A = 1 << LT_ARCTIC;
9073 static constexpr uint8_t S = 1 << LT_TROPIC;
9074 static constexpr uint8_t Y = 1 << LT_TOYLAND;
9075 static const struct DefaultRefitMasks {
9080 } _default_refit_masks[] = {
9082 {T | A | S , CT_MAIL,
CC_MAIL, 0},
9085 {T | A , CT_COAL,
CC_BULK, 0},
9086 { S , CT_COPPER_ORE,
CC_BULK, 0},
9102 switch (label.base()) {
9106 _gted[engine].cargo_disallowed = 0;
9111 _gted[engine].cargo_disallowed = 0;
9130 _gted[engine].cargo_disallowed = 0;
9134 for (
const auto &drm : _default_refit_masks) {
9136 if (drm.cargo_label != label)
continue;
9138 _gted[engine].cargo_allowed = drm.cargo_allowed;
9139 _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9144 _gted[engine].ctt_exclude_mask = original_known_cargoes;
9147 _gted[engine].UpdateRefittability(
_gted[engine].cargo_allowed != 0);
9154 CargoTypes mask = 0;
9155 CargoTypes not_mask = 0;
9156 CargoTypes xor_mask = ei->refit_mask;
9162 if (
_gted[engine].cargo_allowed != 0) {
9165 if ((
_gted[engine].cargo_allowed & cs->classes) != 0 && (
_gted[engine].cargo_allowed_required & cs->classes) ==
_gted[engine].cargo_allowed_required)
SetBit(mask, cs->Index());
9166 if (
_gted[engine].cargo_disallowed & cs->classes)
SetBit(not_mask, cs->Index());
9170 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) &
_cargo_mask;
9173 ei->refit_mask |=
_gted[engine].ctt_include_mask;
9174 ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
9178 if (file ==
nullptr) file = e->
GetGRF();
9181 uint8_t local_slot = file->
cargo_map[cs->Index()];
9187 case 1:
SetBit(ei->refit_mask, cs->Index());
break;
9188 case 2:
ClrBit(ei->refit_mask, cs->Index());
break;
9202 ei->cargo_type = INVALID_CARGO;
9210 if (file ==
nullptr) file = e->
GetGRF();
9211 if (file !=
nullptr && file->grf_version >= 8 && !file->
cargo_list.empty()) {
9213 uint8_t best_local_slot = UINT8_MAX;
9215 uint8_t local_slot = file->
cargo_map[cargo_type];
9216 if (local_slot < best_local_slot) {
9217 best_local_slot = local_slot;
9218 ei->cargo_type = cargo_type;
9248 for (uint i = 0; i < CF_END; i++) {
9260 if (e->
GetGRF() ==
nullptr) {
9261 auto found = std::ranges::find(_engine_mngr.mappings[e->
type], e->
index, &EngineIDMapping::engine);
9262 if (found == std::end(_engine_mngr.mappings[e->
type]) || found->grfid != INVALID_GRFID || found->internal_id != found->substitute_id) {
9263 e->info.
string_id = STR_NEWGRF_INVALID_ENGINE;
9296 default: NOT_REACHED();
9308 if (parent != e->
index)
continue;
9313 GrfMsg(1,
"FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", e->
grf_prop.
local_id, e->
GetGRF()->filename);
9329 switch (cs.label.base()) {
9331 case CT_MAIL.base(): cs.town_production_effect =
TPE_MAIL;
break;
9332 default: cs.town_production_effect =
TPE_NONE;
break;
9335 if (!cs.IsValid()) {
9336 cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO;
9337 cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
9338 cs.abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
9362 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} as multitile, but no suitable tiles follow. Disabling house.", filename, hs->
grf_prop.
local_id);
9372 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines multitile house {} with non-zero population on additional tiles. Disabling house.", filename, hs->
grf_prop.
local_id);
9380 Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->
grf_prop.
local_id);
9387 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} without a size but marked it as available. Disabling house.", filename, hs->
grf_prop.
local_id);
9410 if (min_year == 0)
return;
9437 if (file->housespec.empty())
continue;
9439 size_t num_houses = file->housespec.size();
9440 for (
size_t i = 0; i < num_houses; i++) {
9441 HouseSpec *hs = file->housespec[i].get();
9443 if (hs ==
nullptr)
continue;
9445 const HouseSpec *next1 = (i + 1 < num_houses ? file->housespec[i + 1].get() :
nullptr);
9446 const HouseSpec *next2 = (i + 2 < num_houses ? file->housespec[i + 2].get() :
nullptr);
9447 const HouseSpec *next3 = (i + 3 < num_houses ? file->housespec[i + 3].get() :
nullptr);
9506 for (
const auto &indsp : file->industryspec) {
9507 if (indsp ==
nullptr || !indsp->
enabled)
continue;
9514 if (strid != STR_UNDEFINED) indsp->
name = strid;
9517 if (strid != STR_UNDEFINED) indsp->
closure_text = strid;
9532 if (strid != STR_UNDEFINED) indsp->
station_name = strid;
9538 for (
const auto &indtsp : file->indtspec) {
9539 if (indtsp !=
nullptr) {
9540 _industile_mngr.SetEntitySpec(indtsp.get());
9545 for (
auto &indsp : _industry_specs) {
9552 indsp.
name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9564 for (
auto &indtsp : _industry_tile_specs) {
9580 for (
auto &objectspec : file->objectspec) {
9581 if (objectspec !=
nullptr && objectspec->grf_prop.HasGrfFile() && objectspec->IsEnabled()) {
9598 for (
auto &as : file->airportspec) {
9599 if (as !=
nullptr && as->
enabled) {
9600 _airport_mngr.SetEntitySpec(as.get());
9604 for (
auto &ats : file->airtspec) {
9605 if (ats !=
nullptr && ats->enabled) {
9606 _airporttile_mngr.SetEntitySpec(ats.get());
9618static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9632 static const SpecialSpriteHandler handlers[][GLS_END] = {
9633 {
nullptr, SafeChangeInfo,
nullptr,
nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9634 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9635 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, NewSpriteGroup, },
9636 {
nullptr,
GRFUnsafe,
nullptr,
nullptr,
nullptr, FeatureMapSpriteGroup, },
9637 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, FeatureNewName, },
9638 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9639 {
nullptr,
nullptr,
nullptr, CfgApply, CfgApply, CfgApply, },
9640 {
nullptr,
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, },
9641 { ScanInfo,
nullptr,
nullptr, GRFInfo, GRFInfo, GRFInfo, },
9642 {
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, SkipIf, },
9643 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9644 {
nullptr,
nullptr,
nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9645 {
nullptr,
nullptr,
nullptr, GRFComment,
nullptr, GRFComment, },
9647 {
nullptr, SafeGRFInhibit,
nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9650 { SkipAct11,
GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9653 {
StaticGRFInfo,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, },
9658 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9659 if (it == _grf_line_to_action6_sprite_override.end()) {
9665 buf = _grf_line_to_action6_sprite_override[location].data();
9666 GrfMsg(7,
"DecodeSpecialSprite: Using preloaded pseudo sprite data");
9675 uint8_t action = br.ReadByte();
9677 if (action == 0xFF) {
9678 GrfMsg(2,
"DecodeSpecialSprite: Unexpected data block, skipping");
9679 }
else if (action == 0xFE) {
9680 GrfMsg(2,
"DecodeSpecialSprite: Unexpected import block, skipping");
9681 }
else if (action >=
lengthof(handlers)) {
9682 GrfMsg(7,
"DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
9683 }
else if (handlers[action][stage] ==
nullptr) {
9684 GrfMsg(7,
"DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
9686 GrfMsg(7,
"DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9687 handlers[action][stage](br);
9690 GrfMsg(1,
"DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9706 Debug(grf, 2,
"LoadNewGRFFile: Reading NewGRF-file '{}'", config->
filename);
9709 if (grf_container_version == 0) {
9710 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9714 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9720 if (grf_container_version >= 2) file.
ReadDword();
9723 if (grf_container_version >= 2) {
9725 uint8_t compression = file.
ReadByte();
9726 if (compression != 0) {
9727 Debug(grf, 7,
"LoadNewGRFFile: Unsupported compression format");
9736 if (num == 4 && file.
ReadByte() == 0xFF) {
9739 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9747 while ((num = (grf_container_version >= 2 ? file.
ReadDword() : file.
ReadWord())) != 0) {
9753 DecodeSpecialSprite(buf.
Allocate(num), num, stage);
9764 GrfMsg(0,
"LoadNewGRFFile: Unexpected sprite, disabling");
9765 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9769 if (grf_container_version >= 2 && type == 0xFD) {
9792 const std::string &filename = config->
filename;
9803 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
9805 if (_cur.
grffile ==
nullptr) UserError(
"File '{}' lost in cache.\n", filename);
9812 SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
9866 DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0);
9867 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
9868 DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2);
9869 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
9870 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
9871 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
9882 static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
9886 std::vector<int> grf_overrides(num_grfs, -1);
9887 for (
int i = 0; i < num_grfs; i++) {
9889 auto it = _grf_id_overrides.find(source->grfid);
9890 if (it == std::end(_grf_id_overrides))
continue;
9891 uint32_t
override = it->second;
9894 if (dest ==
nullptr)
continue;
9897 assert(grf_overrides[i] >= 0);
9901 for (
int i = 0; i < num_grfs; i++) {
9902 if (grf_overrides[i] < 0 || grf_overrides[i] >= i)
continue;
9910 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9913 Debug(grf, 3,
"'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
9919 for (
int i = num_grfs - 1; i >= 0; i--) {
9920 if (grf_overrides[i] < 0 || grf_overrides[i] <= i)
continue;
9928 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9931 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
9937 for (
int i = 0; i < num_grfs; i++) {
9938 if (grf_overrides[i] < 0)
continue;
9946 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9947 if (!
HasBit(features, _price_base_specs[p].grf_feature))
continue;
9949 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
9957 if (file->grf_version >= 8)
continue;
9958 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9959 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9961 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9964 price_base_multipliers[p] = price_base_multipliers[fallback_price];
9971 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9972 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9973 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9975 price_base_multipliers[p] = 0;
9980 Debug(grf, 3,
"'{}' sets global price base multiplier {}", file->
filename, p);
9982 price_base_multipliers[p] = 0;
9984 Debug(grf, 3,
"'{}' sets local price base multiplier {}", file->
filename, p);
10006 _grf_line_to_action6_sprite_override.clear();
10069 if (file ==
nullptr ||
_gted[e->
index].roadtramtype == 0) {
10078 if (
_gted[e->
index].roadtramtype < list->size())
10080 RoadTypeLabel rtl = (*list)[
_gted[e->
index].roadtramtype];
10109 _grm_sprites.clear();
10167 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10174 if (stage == GLS_RESERVE) {
10175 static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10180 for (
const auto &grf_override : default_grf_overrides) {
10186 uint num_non_static = 0;
10188 _cur.
stage = stage;
10195 Debug(grf, 0,
"NewGRF file is missing '{}'; disabling", c->
filename);
10204 Debug(grf, 0,
"'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->
filename);
10206 c->
error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10215 if (stage == GLS_RESERVE) {
10217 }
else if (stage == GLS_ACTIVATION) {
10222 Debug(sprite, 2,
"LoadNewGRF: Currently {} sprites are loaded", _cur.
spriteid);
static const uint INVALID_AIRPORTTILE
id for an invalid airport tile
static const uint NEW_AIRPORTTILE_OFFSET
offset of first newgrf airport tile
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
@ NUM_AIRPORTS_PER_GRF
Maximal number of airports per NewGRF.
static const uint NUM_AIRPORTTILES_PER_GRF
Number of airport tiles per NewGRF; limited to 255 to allow extending Action3 with an extended byte l...
Class for backupping variables and making sure they are restored later.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
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.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
constexpr uint SPRITES_PER_BRIDGE_PIECE
Number of sprites there are per bridge piece.
static const uint MAX_BRIDGES
Maximal number of available bridge specs.
BridgeSpec _bridge[MAX_BRIDGES]
The specification of all bridges.
void ResetBridges()
Reset the data been eventually changed by the grf loaded.
Tables with default industry layouts and behaviours.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
static constexpr CargoLabel CT_PASSENGERS
Available types of cargo Labels may be re-used between different climates.
StrongType::Typedef< uint32_t, struct CargoLabelTag, StrongType::Compare > CargoLabel
Globally unique label of a cargo type.
MixedCargoType
Mixed cargo types for definitions with cargo that can vary depending on climate.
@ MCT_GRAIN_WHEAT_MAIZE
Cargo can be grain, wheat or maize.
@ MCT_LIVESTOCK_FRUIT
Cargo can be livestock or fruit.
@ MCT_VALUABLES_GOLD_DIAMONDS
Cargo can be valuables, gold or diamonds.
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
bool IsDefaultCargo(CargoID cid)
Test if a cargo is a default cargo type.
std::span< const CargoLabel > GetClimateDependentCargoTranslationTable()
Get default climate-dependent cargo translation table for a NewGRF, used if the NewGRF does not provi...
CargoTypes _standard_cargo_mask
Bitmask of real cargo types available.
std::span< const CargoLabel > GetClimateIndependentCargoTranslationTable()
Get default climate-independent cargo translation table for a NewGRF, used if the NewGRF does not pro...
void BuildCargoLabelMap()
Build cargo label map.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
void SetupCargoForClimate(LandscapeID l)
Set up the default cargo types for the given landscape type.
CargoTypes _cargo_mask
Bitmask of cargo types available.
@ CC_REFRIGERATED
Refrigerated cargo (Food, Fruit)
@ CC_ARMOURED
Armoured cargo (Valuables, Gold, Diamonds)
@ CC_BULK
Bulk cargo (Coal, Grain etc., Ores, Fruit)
@ CC_EXPRESS
Express cargo (Goods, Food, Candy, but also possible for passengers)
@ CC_LIQUID
Liquids (Oil, Water, Rubber)
@ CC_PIECE_GOODS
Piece goods (Livestock, Wood, Steel, Paper)
@ CC_PASSENGERS
Passengers.
@ INVALID_TPE
Invalid town production effect.
@ 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.
uint16_t CargoClasses
Bitmask of cargo classes.
@ TAE_GOODS
Cargo behaves goods/candy-like.
@ TAE_NONE
Cargo has no effect.
@ TAE_PASSENGERS
Cargo behaves passenger-like.
@ TAE_MAIL
Cargo behaves mail-like.
@ TAE_FOOD
Cargo behaves food/fizzy-drinks-like.
@ TAE_WATER
Cargo behaves water-like.
Class to read from a NewGRF file.
void SetEntitySpec(const HouseSpec *hs)
Install the specs into the HouseSpecs array It will find itself the proper slot on which it will go.
void SetEntitySpec(IndustrySpec *inds)
Method to install the new industry data in its proper slot The slot assignment is internal of this me...
static void Assign(Tspec *spec)
Assign a spec to one of the classes.
StringID name
Name of this class.
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
static void Reset()
Reset the classes, i.e.
void SetEntitySpec(ObjectSpec *spec)
Method to install the new object data in its proper slot The slot assignment is internal of this meth...
void ResetMapping()
Resets the mapping, which is used while initializing game.
virtual uint16_t GetID(uint16_t grf_local_id, uint32_t grfid) const
Return the ID (if ever available) of a previously inserted entity.
void Add(uint16_t local_id, uint32_t grfid, uint entity_type)
Since the entity IDs defined by the GRF file does not necessarily correlate to those used by the game...
virtual uint16_t AddEntityID(uint16_t grf_local_id, uint32_t grfid, uint16_t substitute_id)
Reserves a place in the mapping array for an entity to be installed.
This struct contains all the info that is needed to draw and construct tracks.
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
TimerGameCalendar::Date introduction_date
Introduction date.
struct RailTypeInfo::@26 strings
Strings associated with the rail type.
RailTypes powered_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype generates power
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
RailTypes introduction_required_railtypes
Bitmask of railtypes that are required for this railtype to be introduced at a given introduction_dat...
uint8_t sorting_order
The sorting order of this railtype for the toolbar dropdown.
RailTypeLabel label
Unique 32 bit rail type identifier.
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this rail type.
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
uint8_t map_colour
Colour on mini-map.
StringID menu_text
Name of this rail type in the main toolbar dropdown.
StringID name
Name of this rail type.
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel
uint8_t fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations.
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
RailTypeFlags flags
Bit mask of rail type flags.
uint8_t curve_speed
Multiplier for curve maximum speed advantage.
uint16_t cost_multiplier
Cost multiplier for building this rail type.
StringID replace_text
Text used in the autoreplace GUI.
RailTypeLabelList alternate_labels
Rail type labels this type provides in addition to the main label.
StringID build_caption
Caption of the build vehicle GUI for this rail type.
StringID new_loco
Name of an engine for this type of rail in the engine preview GUI.
const GRFFile * grffile[RTSG_END]
NewGRF providing the Action3 for the railtype.
uint8_t acceleration_type
Acceleration type of this rail type.
void ReadBlock(void *ptr, size_t size)
Read a block.
size_t GetPos() const
Get position in the file.
void SeekTo(size_t pos, int mode)
Seek in the current file.
std::string filename
Full name of the file; relative path to subdir plus the extension of the file.
uint8_t ReadByte()
Read a byte from the file.
uint32_t ReadDword()
Read a double word (32 bits) from the file (in low endian format).
void SkipBytes(size_t n)
Skip n bytes ahead in the file.
uint16_t ReadWord()
Read a word (16 bits) from the file (in low endian format).
A reusable buffer that can be used for places that temporary allocate a bit of memory and do that ver...
T * Allocate(size_t count)
Get buffer of at least count times T.
StringID menu_text
Name of this rail type in the main toolbar dropdown.
StringID replace_text
Text used in the autoreplace GUI.
RoadTypeLabelList alternate_labels
Road type labels this type provides in addition to the main label.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
TimerGameCalendar::Date introduction_date
Introduction date.
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this road type.
RoadTypeFlags flags
Bit mask of road type flags.
struct RoadTypeInfo::@29 strings
Strings associated with the rail type.
uint8_t map_colour
Colour on mini-map.
const GRFFile * grffile[ROTSG_END]
NewGRF providing the Action3 for the roadtype.
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
StringID name
Name of this rail type.
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
StringID new_engine
Name of an engine for this type of road in the engine preview GUI.
RoadTypes introduction_required_roadtypes
Bitmask of roadtypes that are required for this roadtype to be introduced at a given introduction_dat...
uint16_t cost_multiplier
Cost multiplier for building this road type.
StringID build_caption
Caption of the build vehicle GUI for this rail type.
RandomAccessFile with some extra information specific for sprite files.
uint8_t GetContainerVersion() const
Get the version number of container type used by the file.
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static DateFract date_fract
Fractional part of the day.
static constexpr TimerGame< struct Calendar >::Year ORIGINAL_MAX_YEAR
The maximum year of the original TTD.
static constexpr TimerGame< struct Calendar >::Year MIN_YEAR
The absolute minimum year in OTTD.
static constexpr TimerGame< struct Calendar >::Year ORIGINAL_BASE_YEAR
The minimum starting year/base year of the original TTD.
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static DateFract date_fract
Fractional part of the day.
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
uint16_t DateFract
The fraction of a date we're in, i.e.
static constexpr bool IsLeapYear(Year year)
Checks whether the given year is a leap year or not.
Configuration options of the network stuff.
static const uint NETWORK_MAX_GRF_COUNT
Maximum number of GRFs that can be sent.
Some simple functions to help with accessing containers.
int find_index(Container const &container, typename Container::const_reference item)
Helper function to get the index of an item Consider using std::set, std::unordered_set or std::flat_...
void ResetCurrencies(bool preserve_custom)
Will fill _currency_specs array with default values from origin_currency_specs Called only from newgr...
uint8_t GetNewgrfCurrencyIdConverted(uint8_t grfcurr_id)
Will return the ottd's index correspondence to the ttdpatch's id.
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Functions to handle different currencies.
@ CURRENCY_END
always the last item
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Direction
Defines the 8 directions on the map.
void SetPriceBaseMultiplier(Price price, int factor)
Change a price base by the given factor.
void ResetPriceBaseMultipliers()
Reset changes to the price base multipliers.
Price
Enumeration of all base prices for use with Prices.
void SetYearEngineAgingStops()
Compute the value for _year_engine_aging_stops.
const uint8_t _engine_counts[4]
Number of engines of each vehicle type in original engine data.
void SetupEngines()
Initialise the engine pool with the data from the original vehicles.
const uint8_t _engine_offsets[4]
Offset of the first engine of each vehicle type in original engine data.
@ HasVariants
Set if engine has variants.
@ IsFolded
Set if display of variants should be folded (hidden).
Functions related to engines.
ExtraEngineFlags
Extra engine flags for NewGRF features.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
EngineClass
Type of rail engine.
@ EC_DIESEL
Diesel rail engine.
@ EC_STEAM
Steam rail engine.
@ EC_MAGLEV
Maglev engine.
@ EC_ELECTRIC
Electric rail engine.
@ EC_MONORAIL
Mono rail engine.
@ EF_USES_2CC
Vehicle uses two company colours.
@ EF_ROAD_TRAM
Road vehicle is a tram/light rail vehicle.
@ RAILVEH_SINGLEHEAD
indicates a "standalone" locomotive
@ RAILVEH_WAGON
simple wagon, not motorized
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
Functions related to errors.
Error reporting related functions.
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
Check whether the given file exists.
Functions for Standard In/Out file operations.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Declarations for savegames operations.
Functions to read fonts from files and cache them.
void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite)
Map a SpriteID to the font size and key.
bool _generating_world
Whether we are generating the map or not.
Functions related to world/map generation.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
FontSize
Available font sizes.
uint32_t PaletteID
The number of the palette.
void SetSnowLine(uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
Set a variable snow line, as loaded from a newgrf file.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
bool IsSnowLineSet()
Has a snow line table already been loaded.
void ClearSnowLine()
Clear the variable snow line table and free the memory.
static const HouseID NUM_HOUSES
Total number of houses.
static const HouseID NEW_HOUSE_OFFSET
Offset for new houses.
static const HouseID NUM_HOUSES_PER_GRF
Number of supported houses per NewGRF.
static const uint HOUSE_ORIGINAL_NUM_ACCEPTS
Original number of accepted cargo types.
@ HZ_ZONALL
1F This is just to englobe all above types at once
@ HZ_CLIMALL
Bitmask of all climate bits.
@ HZ_SUBARTC_ABOVE
11 800 can appear in sub-arctic climate above the snow line
@ HZ_ZON1
0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb
void ResetIndustries()
This function initialize the spec arrays of both industry and industry tiles.
void SortIndustryTypes()
Initialize the list of sorted industry types.
Accessors for industries.
@ GFX_WATERTILE_SPECIALCHECK
not really a tile, but rather a very special check
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
static const IndustryType NEW_INDUSTRYOFFSET
original number of industry types
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF; limited to 255 to allow extending Action3 with an extend...
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
static const int INDUSTRY_ORIGINAL_NUM_OUTPUTS
Original number of produced cargo types.
static const IndustryType NUM_INDUSTRYTYPES_PER_GRF
maximum number of industry types per NewGRF; limited to 128 because bit 7 has a special meaning in so...
IndustryLifeType
Available types of industry lifetimes.
@ CHECK_NOTHING
Always succeeds.
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
IndustryBehaviour
Various industry behaviours mostly to represent original TTD specialities.
IndustryTileSpecialFlags
Flags for miscellaneous industry tile specialities.
Functions related to OTTD's landscape.
static const uint SNOW_LINE_DAYS
Number of days in each month in the snow line table.
static const uint SNOW_LINE_MONTHS
Number of months in the snow line table.
Information about languages and their files.
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
const LanguageMetadata * GetLanguage(uint8_t newgrflangid)
Get the language with the given NewGRF language ID.
static const uint8_t MAX_NUM_CASES
Maximum number of supported cases.
LiveryScheme
List of different livery schemes.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
void MemSetT(T *ptr, uint8_t value, size_t num=1)
Type-safe version of memset().
static constexpr CargoID SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoID SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoID SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
bool _networking
are we in networking mode?
static void FinaliseObjectsArray()
Add all new objects to the object array.
static void FinalisePriceBaseMultipliers()
Decide whether price base multipliers of grfs shall apply globally or only to the grf specifying them...
std::span< const Action5Type > GetAction5Types()
Get list of all action 5 types.
static void ResetCustomStations()
Reset and clear all NewGRF stations.
static void SkipAct12(ByteReader &buf)
Action 0x12 (SKIP)
static std::vector< GRFTempEngineData > _gted
Temporary engine data used during NewGRF loading.
static CargoLabel GetActiveCargoLabel(const std::initializer_list< CargoLabel > &labels)
Find first cargo label that exists and is active from a list of cargo labels.
bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
Reads a variable common to VarAction2 and Action7/9/D.
static bool ChangeGRFParamType(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'TYPE' to set the typeof a parameter.
bool(* BranchHandler)(ByteReader &)
Type of callback function for branch nodes.
StringID MapGRFStringID(uint32_t grfid, StringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
static uint16_t SanitizeSpriteOffset(uint16_t &num, uint16_t offset, int max_sprites, const std::string_view name)
Sanitize incoming sprite offsets for Action 5 graphics replacements.
static void FinaliseIndustriesArray()
Add all new industries to the industry array.
static bool ChangeGRFParamLimits(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'LIMI' to set the min/max value of a parameter.
static void AddStringForMapping(StringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
std::span< const CargoLabel > GetCargoTranslationTable(const GRFFile &grffile)
Get the cargo translation table to use for the given GRF file.
static bool ChangeGRFNumUsedParams(size_t len, ByteReader &buf)
Callback function for 'INFO'->'NPAR' to set the number of valid parameters.
void ResetPersistentNewGRFData()
Reset NewGRF data which is stored persistently in savegames.
static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, ByteReader &buf)
Define properties for stations.
static uint32_t _grm_cargoes[NUM_CARGO *2]
Contains the GRF ID of the owner of a cargo if it has been reserved.
static bool ChangeGRFURL(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'URL_' to set the newgrf url.
static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for road vehicles.
bool(* DataHandler)(size_t, ByteReader &)
Type of callback function for binary nodes.
static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, ByteReader &buf)
Define properties common to all vehicles.
static void FinaliseAirportsArray()
Add all new airports to the airport array.
static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, ByteReader &buf)
Define properties for airports.
static GRFFile * GetFileByFilename(const std::string &filename)
Obtain a NewGRF file by its filename.
static bool ChangeGRFParamDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter.
static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for water features.
static void InitNewGRFFile(const GRFConfig *config)
Prepare loading a NewGRF file with its config.
static bool ChangeGRFMinVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'MINV' to the minimum compatible version of the NewGRF.
static bool IsHouseSpecValid(HouseSpec *hs, const HouseSpec *next1, const HouseSpec *next2, const HouseSpec *next3, const std::string &filename)
Check if a given housespec is valid and disable it if it's not.
static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, ByteReader &buf)
Define properties for global variables.
AllowedSubtags _tags_root[]
Action14 root tags.
static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteReader &buf)
Define properties for cargoes.
static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteReader &buf)
Define properties for bridges.
static void TranslateGRFStrings(ByteReader &buf)
Action 0x13.
static void GRFUnsafe(ByteReader &)
Set the current NewGRF as unsafe for static use.
static void DefineGotoLabel(ByteReader &buf)
Action 0x10 - Define goto label.
static void ActivateOldShore()
Relocates the old shore sprites at new positions.
static void EnsureEarlyHouse(HouseZones bitmask)
Make sure there is at least one house available in the year 0 for the given climate / housezone combi...
static const uint NUM_STATIONS_PER_GRF
The maximum amount of stations a single GRF is allowed to add.
static void ParamSet(ByteReader &buf)
Action 0x0D: Set parameter.
static bool ChangeGRFParamValueNames(ByteReader &buf)
Callback function for 'INFO'->'PARA'->param_num->'VALU' to set the names of some parameter values (ty...
static GRFFile * GetCurrentGRFOverride()
Get overridden GRF for current GRF if present.
static void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file)
Load a particular NewGRF from a SpriteFile.
static void FinaliseEngineArray()
Check for invalid engines.
static const SpriteGroup * CreateGroupFromGroupID(uint8_t feature, uint8_t setid, uint8_t type, uint16_t spriteid)
Helper function to either create a callback or a result sprite group.
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader &buf, TGetTableFunc gettable, std::string_view name)
Load a cargo- or railtype-translation table.
static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader &buf)
Define properties for industry tiles.
static bool HandleParameterInfo(ByteReader &buf)
Callback function for 'INFO'->'PARA' to set extra information about the parameters.
static void ReadSpriteLayoutRegisters(ByteReader &buf, TileLayoutFlags flags, bool is_parent, NewGRFSpriteLayout *dts, uint index)
Preprocess the TileLayoutFlags and read register modifiers from the GRF.
static GRFParameterInfo * _cur_parameter
The parameter which info is currently changed by the newgrf.
static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for aircraft.
static uint32_t _grm_engines[256]
Contains the GRF ID of the owner of a vehicle if it has been reserved.
static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, AllowedSubtags subtags[])
Handle the nodes of an Action14.
static void ResetNewGRFErrors()
Clear all NewGRF errors.
uint8_t _misc_grf_features
Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E.
AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for ships.
static void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid)
Set the override for a NewGRF.
static bool ChangeGRFName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'NAME' to add a translation to the newgrf name.
static std::vector< StringIDMapping > _string_to_grf_mapping
Strings to be mapped during load.
static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf, RoadTramType rtt)
Define properties for roadtypes.
static void LoadGRFSound(size_t offs, SoundEntry *sound)
Load a sound from a file.
static StringID TTDPStringIDToOTTDStringIDMapping(StringID str)
Perform a mapping from TTDPatch's string IDs to OpenTTD's string IDs, but only for the ones we are aw...
bool(* TextHandler)(uint8_t, std::string_view str)
Type of callback function for text nodes.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
static const uint MAX_SPRITEGROUP
Maximum GRF-local ID for a spritegroup.
void LoadNewGRF(SpriteID load_index, uint num_baseset)
Load all the NewGRFs.
static void InitializeGRFSpecial()
Initialize the TTDPatch flags.
static std::string ReadDWordAsString(ByteReader &reader)
Helper to read a DWord worth of bytes from the reader and to return it as a valid string.
static void ClearTemporaryNewGRFData(GRFFile *gf)
Reset all NewGRFData that was used only while processing data.
static void FinaliseCanals()
Set to use the correct action0 properties for each canal feature.
AllowedSubtags _tags_parameters[]
Action14 parameter tags.
static bool IsValidNewGRFImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular NewGRF vehicle.
static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for railtypes.
void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
Load a particular NewGRF.
static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
Ignore properties for objects.
void ResetNewGRFData()
Reset all NewGRF loaded data.
static bool IsGRMReservedSprite(SpriteID first_sprite, uint16_t num_sprites)
Check if a sprite ID range is within the GRM reversed range for the currently loading NewGRF.
static void CalculateRefitMasks()
Precalculate refit masks from cargo classes for all vehicles.
void FinaliseCargoArray()
Check for invalid cargoes.
static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for rail vehicles.
static CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
static GRFFile * GetFileByGRFID(uint32_t grfid)
Obtain a NewGRF file by its grfID.
static ChangeInfoResult IgnoreRoadStopProperty(uint prop, ByteReader &buf)
Ignore properties for roadstops.
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader &buf)
Ignore an industry property.
static void BuildCargoTranslationMap()
Construct the Cargo Mapping.
static bool ChangeGRFParamMask(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'MASK' to set the parameter and bits to use.
static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader &buf)
Define properties for industries.
static void ImportGRFSound(SoundEntry *sound)
Process a sound import from another GRF file.
static bool SkipUnknownInfo(ByteReader &buf, uint8_t type)
Try to skip the current node and all subnodes (if it's a branch node).
static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader &buf)
Ignore a house property.
static bool ReadSpriteLayout(ByteReader &buf, uint num_building_sprites, bool use_cur_spritesets, uint8_t feature, bool allow_var10, bool no_z_position, NewGRFSpriteLayout *dts)
Read a spritelayout from the GRF.
void GrfMsgI(int severity, const std::string &msg)
Debug() function dedicated to newGRF debugging messages Function is essentially the same as Debug(grf...
static void ResetCustomHouses()
Reset and clear all NewGRF houses.
EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal_id)
Return the ID of a new engine.
static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
static void LoadFontGlyph(ByteReader &buf)
Action 0x12.
static void ResetCustomIndustries()
Reset and clear all NewGRF industries.
static std::vector< GRFFile * > _grf_files
List of all loaded GRF files.
static void ResetCustomObjects()
Reset and clear all NewObjects.
static void ConvertTTDBasePrice(uint32_t base_pointer, const char *error_location, Price *index)
Converts TTD(P) Base Price pointers into the enum used by OTTD See http://wiki.ttdpatch....
static void FinaliseHouseArray()
Add all new houses to the house array.
static bool ChangeGRFPalette(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PALS' to set the number of valid parameters.
static constexpr auto _action5_types
The information about action 5 types.
static bool ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
ChangeInfoResult
Possible return values for the FeatureChangeInfo functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_DISABLED
GRF was disabled due to error.
@ CIR_UNKNOWN
Variable is unknown.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
Validate the industry layout; e.g.
static TileLayoutFlags ReadSpriteLayoutSprite(ByteReader &buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, int feature, PalSpriteID *grf_sprite, uint16_t *max_sprite_offset=nullptr, uint16_t *max_palette_offset=nullptr)
Read a sprite and a palette from the GRF and convert them into a format suitable to OpenTTD.
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
static void ActivateOldTramDepot()
Replocate the old tram depot sprites to the new position, if no new ones were loaded.
static uint32_t _ttdpatch_flags[8]
32 * 8 = 256 flags.
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
static Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access=false)
Returns the engine associated to a certain internal_id, resp.
static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite)
Map the colour modifiers of TTDPatch to those that Open is using.
static void AfterLoadGRFs()
Finish loading NewGRFs and execute needed post-processing.
static bool ChangeGRFParamName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter.
static void ResetNewGRF()
Reset and clear all NewGRFs.
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, ByteReader &buf)
Define properties for sound effects.
static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
Callback function for 'INFO'->'BLTR' to set the blitter info.
static GRFError * DisableGrf(StringID message=STR_NULL, GRFConfig *config=nullptr)
Disable a GRF.
static void FeatureTownName(ByteReader &buf)
Action 0x0F - Define Town names.
static void ResetCustomAirports()
Reset and clear all NewGRF airports.
static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for objects.
static std::vector< CachedCallback > _cached_callback_groups
Sorted list of cached callback result spritegroups.
static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader &buf)
Define properties for houses.
@ GMB_TRAIN_WIDTH_32_PIXELS
Use 32 pixels per train vehicle in depot gui and vehicle details. Never set in the global variable;.
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
@ TRAMWAY_REPLACE_DEPOT_NO_TRACK
Electrified depot graphics without tram track were loaded.
@ TRAMWAY_REPLACE_DEPOT_NONE
No tram depot graphics were loaded.
@ SHORE_REPLACE_ACTION_A
Shore sprites were replaced by ActionA (using grass tiles for the corner-shores).
@ SHORE_REPLACE_NONE
No shore sprites were replaced.
@ SHORE_REPLACE_ONLY_NEW
Only corner-shores were loaded by Action5 (openttd(w/d).grf only).
@ SHORE_REPLACE_ACTION_5
Shore sprites were replaced by Action5.
Information about NewGRF Action 5.
@ A5BLOCK_ALLOW_OFFSET
Allow replacing any subset by specifiing an offset.
@ A5BLOCK_INVALID
unknown/not-implemented type
@ A5BLOCK_FIXED
Only allow replacing a whole block of sprites. (TTDP compatible)
void BindAirportSpecs()
Tie all airportspecs to their class.
NewGRF handling of airports.
TTDPAirportType
Allow incrementing of AirportClassID variables.
NewGRF handling of airport tiles.
static const uint8_t ANIM_STATUS_NO_ANIMATION
There is no animation.
@ CBID_VEHICLE_CUSTOM_REFIT
Called to get custom engine refit mask.
@ CBM_VEHICLE_CUSTOM_REFIT
Custom refit mask.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
WaterFeature _water_feature[CF_END]
Table of canal 'feature' sprite groups.
Handling of NewGRF canals.
CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoID.
Cargo support for NewGRFs.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
static const uint TLR_MAX_VAR10
Maximum value for var 10.
TileLayoutFlags
Flags to enable register usage in sprite layouts.
@ TLF_BB_Z_OFFSET
Add signed offset to bounding box Z positions from register TileLayoutRegisters::delta....
@ TLF_CUSTOM_PALETTE
Palette is from Action 1 (moved to SPRITE_MODIFIER_CUSTOM_SPRITE in palette during loading).
@ TLF_SPRITE
Add signed offset to sprite from register TileLayoutRegisters::sprite.
@ TLF_CHILD_X_OFFSET
Add signed offset to child sprite X positions from register TileLayoutRegisters::delta....
@ TLF_DRAWING_FLAGS
Flags which are still required after loading the GRF.
@ TLF_DODRAW
Only draw sprite if value of register TileLayoutRegisters::dodraw is non-zero.
@ TLF_PALETTE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the palette, even if it is no action-1 palet...
@ TLF_NON_GROUND_FLAGS
Flags which do not work for the (first) ground sprite.
@ TLF_BB_XY_OFFSET
Add signed offset to bounding box X and Y positions from register TileLayoutRegisters::delta....
@ TLF_SPRITE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the sprite, even if it is no action-1 sprite...
@ TLF_PALETTE_VAR10
Resolve palette with a specific value in variable 10.
@ TLF_SPRITE_VAR10
Resolve sprite with a specific value in variable 10.
@ TLF_KNOWN_FLAGS
Known flags. Any unknown set flag will disable the GRF.
@ TLF_PALETTE
Add signed offset to palette from register TileLayoutRegisters::palette.
@ TLF_CHILD_Y_OFFSET
Add signed offset to child sprite Y positions from register TileLayoutRegisters::delta....
GRFConfig * _grfconfig
First item in list of current GRF set up.
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
GRFPalette
Information that can/has to be stored about a GRF's palette.
@ GRFP_GRF_UNSET
The NewGRF provided no information.
@ GRFP_BLT_UNSET
The NewGRF provided no information or doesn't care about a 32 bpp blitter.
@ GRFP_GRF_WINDOWS
The NewGRF says the Windows palette can be used.
@ GRFP_GRF_DOS
The NewGRF says the DOS palette can be used.
@ GRFP_GRF_ANY
The NewGRF says any palette can be used.
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
@ GRFP_USE_MASK
Bitmask to get only the use palette use states.
@ GCF_INIT_ONLY
GRF file is processed up to GLS_INIT.
@ GCF_INVALID
GRF is unusable with this version of OpenTTD.
@ GCF_STATIC
GRF file is used statically (can be used in any MP game)
@ GCF_UNSAFE
GRF file is unsafe for static usage.
@ GCF_RESERVED
GRF file passed GLS_RESERVE stage.
@ GCF_SYSTEM
GRF file is an openttd-internal system grf.
@ GCS_INITIALISED
GRF file has been initialised.
@ GCS_DISABLED
GRF file is disabled.
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
@ GCS_UNKNOWN
The status of this grf file is unknown.
@ GCS_ACTIVATED
GRF file has been activated.
GRFParameterType
The possible types of a newgrf parameter.
@ PTYPE_UINT_ENUM
The parameter allows a range of numbers, each of which can have a special name.
@ PTYPE_END
Invalid parameter type.
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.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
void CommitVehicleListOrderChanges()
Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
void AlterVehicleListOrder(EngineID engine, uint16_t target)
Record a vehicle ListOrderChange.
Functions for NewGRF engines.
void AddGenericCallback(uint8_t feature, const GRFFile *file, const SpriteGroup *group)
Add a generic feature callback sprite group to the appropriate feature list.
void ResetGenericCallbacks()
Reset all generic feature callback sprite groups.
Functions related to NewGRF houses.
IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32_t grf_id)
Map the GRF local type to an industry type.
Functions for NewGRF industries.
void ResetObjects()
This function initialize the spec arrays of objects.
Functions related to NewGRF objects.
static const uint8_t OBJECT_SIZE_1X1
The value of a NewGRF's size property when the object is 1x1 tiles: low nibble for X,...
ObjectFlags
Various object behaviours.
@ OBJECT_FLAG_2CC_COLOUR
Object wants 2CC colour mapping.
@ PROP_AIRCRAFT_PASSENGER_CAPACITY
Passenger Capacity.
@ PROP_ROADVEH_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_TRAIN_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_TRAIN_CURVE_SPEED_MOD
Modifier to maximum speed in curves.
@ PROP_ROADVEH_WEIGHT
Weight in 1/4 t.
@ PROP_TRAIN_COST_FACTOR
Purchase cost (if dualheaded: sum of both vehicles)
@ PROP_TRAIN_USER_DATA
User defined data for vehicle variable 0x42.
@ PROP_TRAIN_WEIGHT
Weight in t (if dualheaded: for each single vehicle)
@ PROP_AIRCRAFT_RANGE
Aircraft range.
@ PROP_TRAIN_CARGO_CAPACITY
Capacity (if dualheaded: for each single vehicle)
@ PROP_AIRCRAFT_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_VEHICLE_LOAD_AMOUNT
Loading speed.
@ PROP_ROADVEH_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_TRAIN_TRACTIVE_EFFORT
Tractive effort coefficient in 1/256.
@ PROP_SHIP_CARGO_CAPACITY
Capacity.
@ PROP_ROADVEH_TRACTIVE_EFFORT
Tractive effort coefficient in 1/256.
@ PROP_SHIP_COST_FACTOR
Purchase cost.
@ PROP_ROADVEH_CARGO_CAPACITY
Capacity.
@ PROP_AIRCRAFT_SPEED
Max. speed: 1 unit = 8 mph = 12.8 km-ish/h.
@ PROP_AIRCRAFT_MAIL_CAPACITY
Mail Capacity.
@ PROP_SHIP_SPEED
Max. speed: 1 unit = 1/3.2 mph = 0.5 km-ish/h.
@ PROP_SHIP_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_TRAIN_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_ROADVEH_COST_FACTOR
Purchase cost.
@ PROP_ROADVEH_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_ROADVEH_POWER
Power in 10 HP.
@ PROP_SHIP_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_AIRCRAFT_COST_FACTOR
Purchase cost.
@ PROP_TRAIN_RUNNING_COST_FACTOR
Yearly runningcost (if dualheaded: sum of both vehicles)
@ PROP_AIRCRAFT_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_TRAIN_POWER
Power in hp (if dualheaded: sum of both vehicles)
@ PROP_TRAIN_SPEED
Max. speed: 1 unit = 1/1.6 mph = 1 km-ish/h.
@ PROP_ROADVEH_SPEED
Max. speed: 1 unit = 1/0.8 mph = 2 km-ish/h.
NewGRF definitions and structures for road stops.
RoadStopDrawMode
Different draw modes to disallow rendering of some parts of the stop or road.
RoadStopAvailabilityType
Various different options for availability, restricting the roadstop to be only for busses or for tru...
static const int NUM_ROADSTOPS_PER_GRF
The maximum amount of roadstops a single GRF is allowed to add.
SoundEntry * AllocateSound(uint num)
Allocate sound slots.
SoundID GetNewGRFSoundID(const GRFFile *file, SoundID sound_id)
Resolve NewGRF sound ID.
Functions related to NewGRF provided sounds.
DeterministicSpriteGroupAdjustOperation
@ VSG_SCOPE_SELF
Resolved object itself.
@ VSG_SCOPE_PARENT
Related object of the resolved one.
@ VSG_SCOPE_RELATIVE
Relative position (vehicles only)
Header file for NewGRF stations.
uint16_t GetStationLayoutKey(uint8_t platforms, uint8_t length)
Get the station layout key for a given station layout size.
void CleanUpStrings()
House cleaning.
static void AddGRFTextToList(GRFTextList &list, uint8_t langid, std::string_view text_to_add)
Add a new text to a GRFText list.
std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool allow_newlines, std::string_view str, StringControlCode byte80)
Translate TTDPatch string codes into something OpenTTD can handle (better).
StringID AddGRFString(uint32_t grfid, uint16_t stringid, uint8_t langid_to_add, bool new_scheme, bool allow_newlines, std::string_view text_to_add, StringID def_string)
Add the new read string into our structure.
StringID GetGRFStringID(uint32_t grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
std::vector< GRFText > GRFTextList
A GRF text with a list of translations.
static const char32_t NFO_UTF8_IDENTIFIER
This character (thorn) indicates a unicode string to NFO.
Header of Action 0F "universal holder" structure and functions.
static const ObjectType NUM_OBJECTS_PER_GRF
Number of supported objects per NewGRF.
RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
Get the rail type for a given label.
RailType AllocateRailType(RailTypeLabel label)
Allocate a new rail type label.
void InitRailTypes()
Resolve sprites of custom rail types.
void ResetRailTypes()
Reset all rail type information to its default values.
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
RailTypeFlags
Railtype flags.
RailType
Enumeration for all possible railtypes.
@ RAILTYPE_END
Used for iterations.
@ INVALID_RAILTYPE
Flag for invalid railtype.
@ RAILTYPE_ELECTRIC
Electric rails.
@ RAILTYPE_RAIL
Standard non-electric rails.
declaration of OTTD revision dependent variables
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
Get the road type for a given label.
void ResetRoadTypes()
Reset all road type information to its default values.
void InitRoadTypes()
Resolve sprites of custom road types.
RoadTypeFlags
Roadtype flags.
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
Allocate a new road type label.
RoadType
The different roadtypes we support.
@ INVALID_ROADTYPE
flag for invalid roadtype
@ ROADTYPE_ROAD
Basic road type.
@ ROADTYPE_END
Used for iterations.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
@ SP_CUSTOM
No profile, special "custom" highscore.
Slope
Enumeration for the slope-type.
void BuildLinkStatsLegend()
Populate legend table for the link stat view.
void BuildIndustriesLegend()
Fills an array for the industries legends.
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
SpriteFile & OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap)
Open/get the SpriteFile that is cached for use in the sprite cache.
bool LoadNextSprite(SpriteID load_index, SpriteFile &file, uint file_sprite_id)
Load a real or recolour sprite.
size_t GetGRFSpriteOffset(uint32_t id)
Get the file offset for a specific sprite in the sprite section of a GRF.
bool SkipSpriteData(SpriteFile &file, uint8_t type, uint16_t num)
Skip the given amount of sprite graphics data.
void ReadGRFSpriteOffsets(SpriteFile &file)
Parse the sprite section of GRFs.
static constexpr uint8_t SPRITE_MODIFIER_OPAQUE
Set when a sprite must not ever be displayed transparently.
static const SpriteID SPR_AQUEDUCT_BASE
Sprites for the Aqueduct.
static const SpriteID SPR_OPENTTD_BASE
Extra graphic spritenumbers.
static const SpriteID SPR_TRACKS_FOR_SLOPES_BASE
Sprites for 'highlighting' tracks on sloped land.
static const SpriteID SPR_ROAD_WAYPOINTS_BASE
Road waypoint sprites.
static constexpr uint8_t PALETTE_MODIFIER_TRANSPARENT
when a sprite is to be displayed transparently, this bit needs to be set.
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
static const SpriteID SPR_AIRPORT_PREVIEW_BASE
Airport preview sprites.
static constexpr uint8_t PALETTE_MODIFIER_COLOUR
this bit is set when a recolouring process is in action
static const SpriteID SPR_ONEWAY_BASE
One way road sprites.
static const SpriteID SPR_SHORE_BASE
shore tiles - action 05-0D
static constexpr uint MAX_CATCHMENT
Maximum catchment for airports with "modified catchment" enabled.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Functions related to low-level strings.
size_t ttd_strnlen(const char *str, size_t maxlen)
Get the length of a string, within a limited buffer.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const uint MAX_LANG
Maximum number of languages supported by the game, and the NewGRF specs.
Information about a single action 5 type.
Action5BlockType block_type
How is this Action5 type processed?
uint16_t max_sprites
If the Action5 contains more sprites, only the first max_sprites sprites will be used.
uint16_t min_sprites
If the Action5 contains less sprites, the whole block will be ignored.
SpriteID sprite_base
Load the sprites starting from this sprite.
const std::string_view name
Name for error messages.
Information about a aircraft vehicle.
uint16_t max_speed
Maximum speed (1 unit = 8 mph = 12.8 km-ish/h)
uint8_t mail_capacity
Mail capacity (bags).
uint8_t subtype
Type of aircraft.
uint16_t passenger_capacity
Passenger capacity (persons).
uint16_t max_range
Maximum range of this aircraft.
Defines the data structure for an airport.
static void ResetAirports()
This function initializes the airportspec array.
struct GRFFileProps grf_prop
Properties related to the grf file.
static AirportSpec * GetWithoutOverride(uint8_t type)
Retrieve airport spec for the given airport.
bool enabled
Entity still available (by default true). Newgrf can disable it, though.
Defines the data structure of each individual tile of an airport.
static const AirportTileSpec * Get(StationGfx gfx)
Retrieve airport tile spec for the given airport tile.
GRFFileProps grf_prop
properties related the the grf file
static void ResetAirportTiles()
This function initializes the tile array of AirportTileSpec.
uint8_t frames
The number of frames.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Struct containing information about a single bridge type.
uint16_t price
the price multiplier
uint8_t min_length
the minimum length (not counting start and end tile)
StringID material
the string that contains the bridge description
TimerGameCalendar::Year avail_year
the year where it becomes available
PalSpriteID ** sprite_table
table of sprites for drawing the bridge
StringID transport_name[2]
description of the bridge, when built for road or rail
uint8_t flags
bit 0 set: disable drawing of far pillars.
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
uint16_t max_length
the maximum length (not counting start and end tile)
Canal properties local to the NewGRF.
uint8_t callback_mask
Bitmask of canal callbacks that have to be called.
uint8_t flags
Flags controlling display.
Specification of a cargo type.
int32_t initial_payment
Initial payment rate before inflation is applied.
CargoClasses classes
Classes of this cargo type.
uint16_t multiplier
Capacity multiplier for vehicles. (8 fractional bits)
StringID units_volume
Name of a single unit of cargo of this type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
StringID abbrev
Two letter abbreviation for this cargo type.
uint8_t bitnum
Cargo bit number, is INVALID_CARGO_BITNUM for a non-used spec.
StringID quantifier
Text for multiple units of cargo of this type.
SpriteID sprite
Icon to display this cargo type, may be 0xFFF (which means to resolve an action123 chain).
bool is_freight
Cargo type is considered to be freight (affects train freight multiplier).
uint8_t weight
Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
CargoLabel label
Unique label of the cargo type.
const struct GRFFile * grffile
NewGRF where group belongs to.
static IterateWrapper Iterate(size_t from=0)
Returns an iterable ensemble of all valid CargoSpec.
static CargoSpec array[NUM_CARGO]
Array holding all CargoSpecs.
uint8_t callback_mask
Bitmask of cargo callbacks that have to be called.
StringID name
Name of this type of cargo.
TownProductionEffect town_production_effect
The effect on town cargo production.
TownAcceptanceEffect town_acceptance_effect
The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
uint16_t town_production_multiplier
Town production multipler, if commanded by TownProductionEffect.
bool IsValid() const
Tests for validity of this cargospec.
StringID name_single
Name of a single entity of this type of cargo.
bool build_on_slopes
allow building on slopes
uint16_t max_bridge_length
maximum length of bridges
uint8_t map_height_limit
the maximum allowed heightlevel
uint8_t train_signal_side
show signals on left / driving / right side
uint8_t parameter
Used for variables between 0x60 and 0x7F inclusive.
A tile child sprite and palette to draw for stations etc, with 3D bounding box.
int8_t delta_z
0x80 identifies child sprites
bool IsParentSprite() const
Check whether this is a parent sprite with a boundingbox.
bool IsTerminator() const
Check whether this is a sequence terminator.
int8_t delta_x
0x80 is sequence terminator
Ground palette sprite of a tile, together with its sprite layout.
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
PalSpriteID ground
Palette and sprite for the ground.
bool inflation
disable inflation
bool allow_town_roads
towns are allowed to build roads (always allowed when generating world / in SE)
bool station_noise_level
build new airports when the town noise level is still within accepted limits
Information about a vehicle.
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
TimerGameCalendar::Year base_life
Basic duration of engine availability (without random parts). 0xFF means infinite life.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
uint8_t misc_flags
Miscellaneous flags.
StringID string_id
Default name of engine.
uint8_t climates
Climates supported by the engine.
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
uint16_t callback_mask
Bitmask of vehicle callbacks that have to be called.
int8_t retire_early
Number of years early to retire vehicle.
TimerGameCalendar::Year lifelength
Lifetime of a single vehicle.
void ResetToDefaultMapping()
Initializes the EngineOverrideManager with the default engines.
EngineID UseUnreservedID(VehicleType type, uint16_t grf_local_id, uint32_t grfid, bool static_access)
Look for an unreserved EngineID matching the local id, and reserve it if found.
EngineID GetID(VehicleType type, uint16_t grf_local_id, uint32_t grfid)
Looks up an EngineID in the EngineOverrideManager.
GRFFilePropsBase< NUM_CARGO+2 > grf_prop
Properties related the the grf file.
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Information about GRF, used in the game and (part of it) in savegames.
GRFTextWrapper url
NOSAVE: URL belonging to this GRF.
uint8_t palette
GRFPalette, bitset.
uint8_t flags
NOSAVE: GCF_Flags, bitset.
GRFTextWrapper info
NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
std::vector< std::optional< GRFParameterInfo > > param_info
NOSAVE: extra information about the parameters.
uint32_t version
NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown.
std::vector< uint32_t > param
GRF parameters.
bool has_param_defaults
NOSAVE: did this newgrf specify any defaults for it's parameters.
GRFTextWrapper name
NOSAVE: GRF name (Action 0x08)
struct GRFConfig * next
NOSAVE: Next item in the linked list.
GRFStatus status
NOSAVE: GRFStatus, enum.
std::optional< GRFError > error
NOSAVE: Error/Warning during GRF loading (Action 0x0B)
uint8_t num_valid_params
NOSAVE: Number of valid parameters (action 0x14)
std::string filename
Filename - either with or without full path.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
const char * GetName() const
Get the name of this grf.
uint32_t min_loadable_version
NOSAVE: Minimum compatible version a NewGRF can define.
Information about why GRF had problems during initialisation.
std::array< uint32_t, 2 > param_value
Values of GRF parameters to show for message and custom_message.
StringID message
Default message.
std::string custom_message
Custom message (if present)
std::string data
Additional data for message and custom_message.
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
const struct GRFFile * grffile
grf file that introduced this entity
std::array< const struct SpriteGroup *, Tcnt > spritegroup
pointers to the different sprites of the entity
Dynamic data of a loaded NewGRF.
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoID -> local ID)
std::vector< RailTypeLabel > railtype_list
Railtype translation table.
uint32_t GetParam(uint number) const
Get GRF Parameter with range checking.
CanalProperties canal_local_properties[CF_END]
Canal properties as set by this NewGRF.
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
uint32_t grf_features
Bitset of GrfSpecFeature the grf uses.
GRFFile(const struct GRFConfig *config)
Constructor for GRFFile.
std::vector< RoadTypeLabel > tramtype_list
Roadtype translation table (tram)
std::vector< CargoLabel > cargo_list
Cargo translation table (local ID -> label)
uint traininfo_vehicle_width
Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details.
int traininfo_vehicle_pitch
Vertical offset for drawing train images in depot GUI and vehicle details.
std::unordered_map< uint8_t, LanguageMap > language_map
Mappings related to the languages.
std::vector< GRFLabel > labels
List of labels.
PriceMultipliers price_base_multipliers
Price base multipliers as set by the grf.
uint32_t grfid
GRF ID (defined by Action 0x08)
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
ShoreReplacement shore
In which way shore sprites were replaced.
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
TramReplacement tram
In which way tram depots were replaced.
Information about one grf parameter.
std::map< uint32_t, GRFTextList > value_names
Names for each value.
uint8_t param_nr
GRF parameter to store content in.
uint32_t min_value
The minimal value this parameter can have.
uint8_t num_bit
Number of bits to use for this parameter.
uint8_t first_bit
First bit to use in the GRF parameter.
uint32_t max_value
The maximal value of this parameter.
GRFParameterType type
The type of this parameter.
uint32_t def_value
Default value of this parameter.
GRFTextList name
The name of this parameter.
GRFTextList desc
The description of this parameter.
Temporary engine data used when loading only.
CargoTypes ctt_exclude_mask
Cargo types always excluded from the refit mask.
Refittability refittability
Did the newgrf set any refittability property? If not, default refittability will be applied.
CargoClasses cargo_disallowed
Bitmask of cargo classes that are disallowed as a refit.
CargoTypes ctt_include_mask
Cargo types always included in the refit mask.
Refittability
Summary state of refittability properties.
@ UNSET
No properties assigned. Default refit masks shall be activated.
@ EMPTY
GRF defined vehicle as not-refittable. The vehicle shall only carry the default cargo.
@ NONEMPTY
GRF defined the vehicle as refittable. If the refitmask is empty after translation (cargotypes not av...
uint8_t rv_max_speed
Temporary storage of RV prop 15, maximum speed in mph/0.8.
CargoClasses cargo_allowed
Bitmask of cargo classes that are allowed as a refit.
void UpdateRefittability(bool non_empty)
Update the summary refittability on setting a refittability property.
CargoClasses cargo_allowed_required
Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
const GRFFile * defaultcargo_grf
GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
std::vector< NamePartList > partlists[MAX_LISTS]
Lists of town name parts.
static const uint MAX_LISTS
Maximum number of town name lists that can be defined per GRF.
std::vector< TownNameStyle > styles
Style names defined by the Town Name NewGRF.
uint8_t landscape
the landscape we're currently in
TimerGameCalendar::Year starting_year
starting date
uint32_t generation_seed
noise seed for world generation
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
StationSettings station
settings related to station management
VehicleSettings vehicle
options for vehicles
OrderSettings order
settings related to orders
Definition of a single Action1 spriteset.
uint num_sprites
Number of sprites in the set.
SpriteID sprite
SpriteID of the first sprite of the set.
Temporary data during loading of GRFs.
SpriteFile * file
File of currently processed GRF file.
GRFFile * grffile
Currently processed GRF file.
void AddSpriteSets(uint8_t feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents)
Records new spritesets.
uint32_t nfo_line
Currently processed pseudo sprite number in the GRF.
SpriteID spriteid
First available SpriteID for loading realsprites.
GRFConfig * grfconfig
Config of the currently processed GRF file.
SpriteID GetSprite(uint8_t feature, uint set) const
Returns the first sprite of a spriteset.
bool IsValidSpriteSet(uint8_t feature, uint set) const
Check whether a specific set is defined.
uint GetNumEnts(uint8_t feature, uint set) const
Returns the number of sprites in a spriteset.
bool HasValidSpriteSets(uint8_t feature) const
Check whether there are any valid spritesets for a feature.
std::map< uint, SpriteSet > spritesets[GSF_END]
Currently referenceable spritesets.
void ClearDataForNextFile()
Clear temporary data before processing the next file in the current loading stage.
GrfLoadingStage stage
Current loading stage.
int skip_sprites
Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file)
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]
input cargo slots
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
CargoLabel accepts_cargo_label[HOUSE_ORIGINAL_NUM_ACCEPTS]
input landscape cargo slots
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
BuildingFlags building_flags
some flags that describe the house (size, stadium etc...)
uint8_t population
population (Zero on other tiles in multi tile house.)
uint8_t cargo_acceptance[HOUSE_NUM_ACCEPTS]
acceptance level for the cargo slots
TimerGameCalendar::Year min_year
introduction year of the house
GRFFileProps grf_prop
Properties related the the grf file.
HouseZones building_availability
where can it be built (climates, zones)
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
uint16_t add_output[INDUSTRY_NUM_OUTPUTS]
Add this much output cargo when successful (unsigned, is indirect in cb version 1+)
CargoID cargo_input[INDUSTRY_NUM_INPUTS]
Which input cargoes to take from (only cb version 2)
uint8_t num_input
How many subtract_input values are valid.
int16_t subtract_input[INDUSTRY_NUM_INPUTS]
Take this much of the input cargo (can be negative, is indirect in cb version 1+)
uint8_t version
Production callback version used, or 0xFF if marked invalid.
uint8_t num_output
How many add_output values are valid.
CargoID cargo_output[INDUSTRY_NUM_OUTPUTS]
Which output cargoes to add to (only cb version 2)
Defines the data structure for constructing industry.
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
StringID production_up_text
Message appearing when the industry's production is increasing.
StringID name
Displayed name of the industry.
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industries.
IndustryType conflicting[3]
Industries this industry cannot be close to.
GRFFileProps grf_prop
properties related to the grf file
StringID production_down_text
Message appearing when the industry's production is decreasing.
StringID station_name
Default name for nearby station.
StringID closure_text
Message appearing when the industry closes.
StringID new_industry_text
Message appearing when the industry is built.
bool enabled
entity still available (by default true).newgrf can disable it, though
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_OUTPUTS > produced_cargo_label
Cargo labels of produced cargo for default industries.
Definition of one tile in an industry tile layout.
Defines the data structure of each individual tile of an industry.
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
GRFFileProps grf_prop
properties related to the grf file
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industry tiles.
Mapping between NewGRF and OpenTTD IDs.
uint8_t newgrf_id
NewGRF's internal ID for a case/gender.
uint8_t openttd_id
OpenTTD's internal ID for a case/gender.
Mapping of language data between a NewGRF and OpenTTD.
static const LanguageMap * GetLanguageMap(uint32_t grfid, uint8_t language_id)
Get the language map associated with a given NewGRF and language.
static debug_inline uint LogX()
Logarithm of the map size along the X side.
static uint LogY()
Logarithm of the map size along the y side.
uint8_t bitcount
Number of bits of random seed to use.
uint16_t maxprob
Total probability of all parts.
std::vector< NamePart > parts
List of parts to choose from.
uint8_t bitstart
Start of random seed bits to use.
uint8_t prob
The relative probability of the following name to appear in the bottom 7 bits.
uint8_t id
If probability bit 7 is set.
std::string text
If probability bit 7 is clear.
NewGRF supplied spritelayout.
void Allocate(uint num_sprites)
Allocate a spritelayout for num_sprites building sprites.
uint consistent_max_offset
Number of sprites in all referenced spritesets.
void Clone(const DrawTileSeqStruct *source)
Clone the building sprites of a spritelayout.
void AllocateRegisters()
Allocate memory for register modifiers.
Allow incrementing of ObjectClassID variables.
GRFFilePropsBase< 2 > grf_prop
Properties related the the grf file.
static void BindToClasses()
Tie all ObjectSpecs to their class.
bool improved_load
improved loading algorithm
bool gradual_loading
load vehicles gradually
Combination of a palette sprite and a 'real' sprite.
SpriteID sprite
The 'real' sprite.
PaletteID pal
The palette (use PAL_NONE) if not needed)
static size_t GetPoolSize()
Returns first unused index.
Tindex index
Index of this pool item.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
void CleanPool() override
Virtual method that deletes all items in the pool.
Describes properties of price bases.
Price fallback_price
Fallback price multiplier for new prices but old grfs.
uint grf_feature
GRF Feature that decides whether price multipliers apply locally or globally, GSF_END if none.
Information about a rail vehicle.
uint16_t power
Power of engine (hp); For multiheaded engines the sum of both engine powers.
uint8_t user_def_data
Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles.
uint8_t running_cost
Running cost of engine; For multiheaded engines the sum of both running costs.
uint8_t cost_factor
Purchase cost factor; For multiheaded engines the sum of both engine prices.
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
RailType intended_railtype
Intended railtype, regardless of elrail being enabled or disabled.
uint16_t pow_wag_power
Extra power applied to consist if wagon should be powered.
uint16_t max_speed
Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
int16_t curve_speed_mod
Modifier to maximum speed in curves (fixed-point binary with 8 fractional bits)
uint16_t weight
Weight of vehicle (tons); For multiheaded engines the weight of each single engine.
uint8_t capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
uint8_t air_drag
Coefficient of air drag.
EngineClass engclass
Class of engine for this vehicle.
uint8_t ai_passenger_only
Bit value to tell AI that this engine is for passenger use only.
RailType railtype
Railtype, mangled if elrail is disabled.
uint8_t tractive_effort
Tractive effort coefficient.
uint8_t pow_wag_weight
Extra weight applied to consist if wagon should be powered.
uint8_t lowest_randbit
Look for this in the per-object randomized bitmask:
VarSpriteGroupScope var_scope
Take this object:
std::vector< const SpriteGroup * > groups
Take the group with appropriate index:
RandomizedSpriteGroupCompareMode cmp_mode
Check for these triggers:
std::vector< const SpriteGroup * > loaded
List of loaded groups (can be SpriteIDs or Callback results)
std::vector< const SpriteGroup * > loading
List of loading groups (can be SpriteIDs or Callback results)
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
Information about a road vehicle.
uint8_t tractive_effort
Coefficient of tractive effort.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
uint8_t air_drag
Coefficient of air drag.
uint8_t power
Power in 10hp units.
RoadType roadtype
Road type.
uint8_t weight
Weight in 1/4t units.
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Iterable ensemble of each set bit in a value.
Information about a ship vehicle.
bool old_refittable
Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask.
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
uint8_t grf_container_ver
NewGRF container version if the sound is from a NewGRF.
bool never_expire_airports
never expire airports
std::unordered_map< uint16_t, std::vector< uint8_t > > layouts
Custom platform layouts, keyed by platform and length combined.
@ NoWires
Tile should NOT contain catenary wires.
@ Pylons
Tile should contain catenary pylons.
@ Blocked
Tile is blocked to vehicles.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
CargoTypes cargo_triggers
Bitmask of cargo types which cause trigger re-randomizing.
std::vector< NewGRFSpriteLayout > renderdata
Number of tile layouts.
Information for mapping static StringIDs.
uint32_t grfid
Source NewGRF.
StringID source
Source StringID (GRF local).
std::function< void(StringID)> func
Function for mapping result.
Templated helper to make a type-safe 'typedef' representing a single POD value.
int16_t x
The x value of the coordinate.
int16_t y
The y value of the coordinate.
Additional modifiers for items in sprite layouts.
uint8_t parent[3]
Registers for signed offsets for the bounding box position of parent sprites.
TileLayoutFlags flags
Flags defining which members are valid and to be used.
uint8_t dodraw
Register deciding whether the sprite shall be drawn at all. Non-zero means drawing.
uint16_t max_sprite_offset
Maximum offset to add to the sprite. (limited by size of the spriteset)
uint8_t palette
Register specifying a signed offset for the palette.
uint8_t sprite_var10
Value for variable 10 when resolving the sprite.
uint16_t max_palette_offset
Maximum offset to add to the palette. (limited by size of the spriteset)
uint8_t palette_var10
Value for variable 10 when resolving the palette.
uint8_t child[2]
Registers for signed offsets for the position of child sprites.
uint8_t sprite
Register specifying a signed offset for the sprite.
Action 2 sprite layout for houses, industry tiles, objects and airport tiles.
uint8_t road_side
the side of the road vehicles drive on
bool wagon_speed_limits
enable wagon speed limits
bool dynamic_engines
enable dynamic allocation of engine data
uint8_t freight_trains
value to multiply the weight of cargo by
uint8_t plane_speed
divisor for speed of aircraft
bool never_expire_vehicles
never expire vehicles
bool disable_elrails
when true, the elrails are disabled
uint8_t callback_mask
Bitmask of canal callbacks that have to be called.
const SpriteGroup * group
Sprite group to start resolving.
const GRFFile * grffile
NewGRF where 'group' belongs to.
uint8_t flags
Flags controlling display.
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.
uint8_t _display_opt
What do we want to draw/do?
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
Determines the LiveryScheme for a vehicle.
Base class for all vehicles.
@ VE_TYPE_COUNT
Number of bits used for the effect type.
@ VE_TYPE_START
First bit used for the type of effect.
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
Functions related to vehicles.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.