58#include "table/strings.h"
75const std::vector<GRFFile *> &GetAllGRFFiles()
118 std::array<const SpriteGroup *, MAX_SPRITEGROUP + 1> spritegroups{};
124 this->skip_sprites = 0;
126 for (uint i = 0; i < GSF_END; i++) {
127 this->spritesets[i].clear();
130 this->spritegroups = {};
143 assert(feature < GSF_END);
144 for (uint i = 0; i < numsets; i++) {
145 SpriteSet &set = this->spritesets[feature][first_set + i];
146 set.
sprite = first_sprite + i * numents;
159 assert(feature < GSF_END);
160 return !this->spritesets[feature].empty();
172 assert(feature < GSF_END);
173 return this->spritesets[feature].find(set) != this->spritesets[feature].end();
185 return this->spritesets[feature].find(set)->second.sprite;
197 return this->spritesets[feature].find(set)->second.num_sprites;
210template <VehicleType T>
213 return image_index == 0xFD || IsValidImageIndex<T>(image_index);
225 ByteReader(uint8_t *data, uint8_t *end) : data(data), end(end) { }
227 inline uint8_t *ReadBytes(
size_t size)
229 if (data + size >= end) {
240 inline uint8_t ReadByte()
242 if (data < end)
return *(data)++;
248 uint16_t val = ReadByte();
249 return val | (ReadByte() << 8);
252 uint16_t ReadExtendedByte()
254 uint16_t val = ReadByte();
255 return val == 0xFF ? ReadWord() : val;
260 uint32_t val = ReadWord();
261 return val | (ReadWord() << 16);
267 return this->ReadDWord();
270 uint32_t ReadVarSize(uint8_t size)
273 case 1:
return ReadByte();
274 case 2:
return ReadWord();
275 case 4:
return ReadDWord();
282 std::string_view ReadString()
284 char *
string =
reinterpret_cast<char *
>(data);
285 size_t string_length =
ttd_strnlen(
string, Remaining());
288 Skip(std::min(string_length + 1, Remaining()));
290 return std::string_view(
string, string_length);
293 inline size_t Remaining()
const
298 inline bool HasData(
size_t count = 1)
const
300 return data + count <= end;
303 inline void Skip(
size_t len)
312typedef void (*SpecialSpriteHandler)(
ByteReader &buf);
329 RailTypeLabel railtypelabel;
330 uint8_t roadtramtype;
345 }
else if (this->refittability ==
UNSET) {
346 this->refittability =
EMPTY;
366 GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
370 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
375 return this->grfid == other.grfid && this->nfoline == other.nfoline;
379static std::map<GRFLocation, std::pair<SpriteID, uint16_t>> _grm_sprites;
380typedef std::map<GRFLocation, std::vector<uint8_t>> GRFLineToSpriteOverride;
381static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
393void GrfMsgI(
int severity,
const std::string &msg)
406 if (file->grfid == grfid)
return file;
419 if (file->filename == filename)
return file;
439 if (config !=
nullptr) {
450 if (message == STR_NULL)
return nullptr;
452 config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
454 return &config->error.value();
502 static const StringID units_volume[] = {
503 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
504 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
505 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
506 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
507 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
508 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
509 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
510 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
514 assert(!
IsInsideMM(str.base(), 0xD000, 0xD7FF));
516#define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
517 static_assert(stringend - stringid == end - begin); \
518 if (str.base() >= begin && str.base() <= end) return StringID{str.base() + (stringid - begin)}
521 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
522 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
523 if (str.base() >= 0x004E && str.base() <= 0x006D)
return units_volume[str.base() - 0x004E];
524 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
525 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
526 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
531 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
532 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
533 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
536 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
537 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
538 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
539 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
540 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
542 switch (str.base()) {
543 case 0x4830:
return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
544 case 0x4831:
return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
545 case 0x483B:
return STR_ERROR_CAN_ONLY_BE_POSITIONED;
547#undef TEXTID_TO_STRINGID
549 if (str.base() == 0)
return STR_EMPTY;
551 Debug(grf, 0,
"Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
565 if (
IsInsideMM(str.base(), 0xD800, 0x10000)) {
572 }
else if (
IsInsideMM(str.base(), 0xD000, 0xD800)) {
590static std::map<uint32_t, uint32_t> _grf_id_overrides;
599 if (target_grfid == 0) {
600 _grf_id_overrides.erase(source_grfid);
601 GrfMsg(5,
"SetNewGRFOverride: Removed override of 0x{:X}", std::byteswap(source_grfid));
603 _grf_id_overrides[source_grfid] = target_grfid;
604 GrfMsg(5,
"SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}", std::byteswap(source_grfid), std::byteswap(target_grfid));
614 auto found = _grf_id_overrides.find(_cur.
grffile->grfid);
615 if (found != std::end(_grf_id_overrides)) {
617 if (grffile !=
nullptr)
return grffile;
634 uint32_t scope_grfid = INVALID_GRFID;
637 scope_grfid = file->grfid;
638 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
639 scope_grfid = it->second;
641 if (grf_match ==
nullptr) {
642 GrfMsg(5,
"Tried mapping from GRFID {:x} to {:x} but target is not loaded", std::byteswap(file->grfid), std::byteswap(scope_grfid));
644 GrfMsg(5,
"Mapping from GRFID {:x} to {:x}", std::byteswap(file->grfid), std::byteswap(scope_grfid));
649 EngineID engine = _engine_mngr.
GetID(type, internal_id, scope_grfid);
650 if (engine != EngineID::Invalid()) {
661 if (engine != EngineID::Invalid()) {
666 GrfMsg(5,
"Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->
index, std::byteswap(file->grfid), type, internal_id);
672 if (static_access)
return nullptr;
675 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, std::byteswap(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);
906 seq->delta_x = buf.ReadByte();
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.empty()) {
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();
1058 uint16_t count = buf.ReadWord();
1059 while (count-- > 0) {
1072 uint16_t count = buf.ReadWord();
1074 std::vector<BadgeID> badges;
1075 badges.reserve(count);
1077 while (count-- > 0) {
1078 uint16_t local_index = buf.ReadWord();
1080 GrfMsg(1,
"ReadBadgeList: Badge label {} out of range (max {}), skipping.", local_index, std::size(_cur.
grffile->
badge_list) - 1);
1087 if (std::ranges::find(badges, index) != std::end(badges))
continue;
1089 badges.push_back(index);
1108 for (uint
id = first;
id < last; ++id) {
1117 uint8_t tracktype = buf.ReadByte();
1119 if (tracktype < _cur.grffile->railtype_list.size()) {
1124 switch (tracktype) {
1125 case 0:
_gted[e->
index].railtypelabel = rvi->
engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL;
break;
1126 case 1:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MONO;
break;
1127 case 2:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MAGLEV;
break;
1129 GrfMsg(1,
"RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1142 uint16_t speed = buf.ReadWord();
1143 if (speed == 0xFFFF) speed = 0;
1150 rvi->
power = buf.ReadWord();
1153 if (rvi->
power != 0) {
1171 uint8_t spriteid = buf.ReadByte();
1172 uint8_t orig_spriteid = spriteid;
1176 if (spriteid < 0xFD) spriteid >>= 1;
1178 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1179 rvi->image_index = spriteid;
1181 GrfMsg(1,
"RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1182 rvi->image_index = 0;
1188 uint8_t dual = buf.ReadByte();
1193 rvi->railveh_type = rvi->
power == 0 ?
1205 uint8_t ctype = buf.ReadByte();
1207 if (ctype == 0xFF) {
1209 ei->cargo_type = INVALID_CARGO;
1213 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1220 SB(rvi->
weight, 0, 8, buf.ReadByte());
1228 GrfMsg(2,
"RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1240 uint8_t traction = buf.ReadByte();
1243 if (traction <= 0x07) {
1245 }
else if (traction <= 0x27) {
1247 }
else if (traction <= 0x31) {
1249 }
else if (traction <= 0x37) {
1251 }
else if (traction <= 0x41) {
1277 ei->refit_cost = buf.ReadByte();
1281 uint32_t mask = buf.ReadDWord();
1282 _gted[e->
index].UpdateRefittability(mask != 0);
1290 SB(mask, 0, 8, buf.ReadByte());
1322 uint8_t weight = buf.ReadByte();
1325 GrfMsg(2,
"RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1357 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1366 uint8_t count = buf.ReadByte();
1367 _gted[e->
index].UpdateRefittability(prop == 0x2C && count != 0);
1369 CargoTypes &ctt = prop == 0x2C ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1392 SB(mask, 8, 8, buf.ReadByte());
1426 for (uint
id = first;
id < last; ++id) {
1437 _gted[e->
index].roadtramtype = buf.ReadByte() + 1;
1445 rvi->running_cost = buf.ReadByte();
1453 uint8_t spriteid = buf.ReadByte();
1454 uint8_t orig_spriteid = spriteid;
1457 if (spriteid == 0xFF) spriteid = 0xFD;
1459 if (spriteid < 0xFD) spriteid >>= 1;
1461 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1462 rvi->image_index = spriteid;
1464 GrfMsg(1,
"RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1465 rvi->image_index = 0;
1471 rvi->capacity = buf.ReadByte();
1476 uint8_t ctype = buf.ReadByte();
1478 if (ctype == 0xFF) {
1480 ei->cargo_type = INVALID_CARGO;
1484 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1491 rvi->cost_factor = buf.ReadByte();
1499 rvi->
power = buf.ReadByte();
1503 rvi->
weight = buf.ReadByte();
1507 _gted[e->
index].rv_max_speed = buf.ReadByte();
1511 uint32_t mask = buf.ReadDWord();
1512 _gted[e->
index].UpdateRefittability(mask != 0);
1520 SB(mask, 0, 8, buf.ReadByte());
1534 ei->refit_cost = buf.ReadByte();
1558 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1585 uint8_t count = buf.ReadByte();
1586 _gted[e->
index].UpdateRefittability(prop == 0x24 && count != 0);
1588 CargoTypes &ctt = prop == 0x24 ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1607 SB(mask, 8, 8, buf.ReadByte());
1641 for (uint
id = first;
id < last; ++id) {
1650 uint8_t spriteid = buf.ReadByte();
1651 uint8_t orig_spriteid = spriteid;
1654 if (spriteid == 0xFF) spriteid = 0xFD;
1656 if (spriteid < 0xFD) spriteid >>= 1;
1658 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1659 svi->image_index = spriteid;
1661 GrfMsg(1,
"ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1662 svi->image_index = 0;
1672 svi->cost_factor = buf.ReadByte();
1681 uint8_t ctype = buf.ReadByte();
1683 if (ctype == 0xFF) {
1685 ei->cargo_type = INVALID_CARGO;
1689 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1696 svi->capacity = buf.ReadWord();
1700 svi->running_cost = buf.ReadByte();
1708 uint32_t mask = buf.ReadDWord();
1709 _gted[e->
index].UpdateRefittability(mask != 0);
1717 SB(mask, 0, 8, buf.ReadByte());
1723 ei->refit_cost = buf.ReadByte();
1755 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1778 uint8_t count = buf.ReadByte();
1779 _gted[e->
index].UpdateRefittability(prop == 0x1E && count != 0);
1781 CargoTypes &ctt = prop == 0x1E ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1800 SB(mask, 8, 8, buf.ReadByte());
1810 svi->
acceleration = std::max<uint8_t>(1, buf.ReadByte());
1842 for (uint
id = first;
id < last; ++id) {
1851 uint8_t spriteid = buf.ReadByte();
1852 uint8_t orig_spriteid = spriteid;
1855 if (spriteid == 0xFF) spriteid = 0xFD;
1857 if (spriteid < 0xFD) spriteid >>= 1;
1859 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1860 avi->image_index = spriteid;
1862 GrfMsg(1,
"AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1863 avi->image_index = 0;
1869 if (buf.ReadByte() == 0) {
1881 avi->cost_factor = buf.ReadByte();
1885 avi->
max_speed = (buf.ReadByte() * 128) / 10;
1889 avi->acceleration = buf.ReadByte();
1893 avi->running_cost = buf.ReadByte();
1909 uint32_t mask = buf.ReadDWord();
1910 _gted[e->
index].UpdateRefittability(mask != 0);
1918 SB(mask, 0, 8, buf.ReadByte());
1924 ei->refit_cost = buf.ReadByte();
1948 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1961 uint8_t count = buf.ReadByte();
1962 _gted[e->
index].UpdateRefittability(prop == 0x1D && count != 0);
1964 CargoTypes &ctt = prop == 0x1D ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1987 SB(mask, 8, 8, buf.ReadByte());
2022 GrfMsg(1,
"StationChangeInfo: Station {} is invalid, max {}, ignoring", last,
NUM_STATIONS_PER_GRF);
2027 if (_cur.
grffile->stations.size() < last) _cur.
grffile->stations.resize(last);
2029 for (uint
id = first;
id < last; ++id) {
2030 auto &statspec = _cur.
grffile->stations[id];
2033 if (statspec ==
nullptr && prop != 0x08) {
2034 GrfMsg(2,
"StationChangeInfo: Attempt to modify undefined station {}, ignoring",
id);
2041 if (statspec ==
nullptr) {
2042 statspec = std::make_unique<StationSpec>();
2046 uint32_t classid = buf.ReadDWord();
2052 uint16_t tiles = buf.ReadExtendedByte();
2053 statspec->renderdata.clear();
2054 statspec->renderdata.reserve(tiles);
2056 for (uint t = 0; t < tiles; t++) {
2060 if (buf.HasData(4) && buf.PeekDWord() == 0) {
2065 dts->seq.insert(dts->seq.end(), dtss.GetSequence().begin(), dtss.GetSequence().end());
2073 std::vector<DrawTileSeqStruct> tmp_layout;
2075 uint8_t delta_x = buf.ReadByte();
2076 if (delta_x == 0x80)
break;
2080 dtss.delta_x = delta_x;
2081 dtss.delta_y = buf.ReadByte();
2082 dtss.
delta_z = buf.ReadByte();
2083 dtss.size_x = buf.ReadByte();
2084 dtss.size_y = buf.ReadByte();
2085 dtss.size_z = buf.ReadByte();
2091 dts->seq = std::move(tmp_layout);
2095 if (statspec->renderdata.size() & 1) {
2096 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item",
id);
2097 statspec->renderdata.pop_back();
2103 uint16_t srcid = buf.ReadExtendedByte();
2104 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2106 if (srcstatspec ==
nullptr) {
2107 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid,
id);
2111 statspec->renderdata.clear();
2112 statspec->renderdata.reserve(srcstatspec->
renderdata.size());
2114 for (
const auto &it : srcstatspec->
renderdata) {
2115 statspec->renderdata.emplace_back(it);
2125 statspec->disallowed_platforms = buf.ReadByte();
2129 statspec->disallowed_lengths = buf.ReadByte();
2133 while (buf.HasData()) {
2134 uint8_t length = buf.ReadByte();
2135 uint8_t number = buf.ReadByte();
2137 if (length == 0 || number == 0)
break;
2139 const uint8_t *buf_layout = buf.ReadBytes(length * number);
2143 layout.assign(buf_layout, buf_layout + length * number);
2146 for (
auto &tile : layout) {
2147 if ((tile & ~1U) != tile) {
2148 GrfMsg(1,
"StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2156 uint16_t srcid = buf.ReadExtendedByte();
2157 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2159 if (srcstatspec ==
nullptr) {
2160 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid,
id);
2164 statspec->layouts = srcstatspec->
layouts;
2169 statspec->cargo_threshold = buf.ReadWord();
2173 uint8_t pylons = buf.ReadByte();
2174 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2175 for (
int j = 0; j < 8; ++j) {
2186 if (_cur.
grffile->grf_version >= 7) {
2189 statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2198 uint8_t wires = buf.ReadByte();
2199 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2200 for (
int j = 0; j < 8; ++j) {
2211 uint8_t blocked = buf.ReadByte();
2212 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2213 for (
int j = 0; j < 8; ++j) {
2214 if (
HasBit(blocked, j)) {
2224 statspec->animation.frames = buf.ReadByte();
2225 statspec->animation.status = buf.ReadByte();
2229 statspec->animation.speed = buf.ReadByte();
2233 statspec->animation.triggers = buf.ReadWord();
2239 uint16_t tiles = buf.ReadExtendedByte();
2240 statspec->renderdata.clear();
2241 statspec->renderdata.reserve(tiles);
2243 for (uint t = 0; t < tiles; t++) {
2245 uint num_building_sprites = buf.ReadByte();
2251 if (statspec->renderdata.size() & 1) {
2252 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item",
id);
2253 statspec->renderdata.pop_back();
2274 uint16_t tiles = buf.ReadExtendedByte();
2276 statspec->tileflags.assign(flags, flags + tiles);
2305 if (last > CF_END) {
2306 GrfMsg(1,
"CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring", last, CF_END);
2310 for (uint
id = first;
id < last; ++id) {
2319 cp->
flags = buf.ReadByte();
2344 GrfMsg(1,
"BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", last,
MAX_BRIDGES);
2348 for (uint
id = first;
id < last; ++id) {
2354 uint8_t year = buf.ReadByte();
2369 bridge->
price = buf.ReadByte();
2373 bridge->
speed = buf.ReadWord();
2374 if (bridge->
speed == 0) bridge->
speed = UINT16_MAX;
2378 uint8_t tableid = buf.ReadByte();
2379 uint8_t numtables = buf.ReadByte();
2380 size_t size = tableid + numtables;
2384 bridge->
sprite_table.resize(std::min<size_t>(size, NUM_BRIDGE_PIECES));
2387 for (; numtables-- != 0; tableid++) {
2388 if (tableid >= NUM_BRIDGE_PIECES) {
2389 GrfMsg(1,
"BridgeChangeInfo: Table {} >= {}, skipping", tableid, NUM_BRIDGE_PIECES);
2412 bridge->
flags = buf.ReadByte();
2432 bridge->
price = buf.ReadWord();
2489 for (uint j = 0; j < 4; j++) buf.ReadByte();
2493 uint8_t count = buf.ReadByte();
2494 for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2499 buf.Skip(buf.ReadByte() * 2);
2522 GrfMsg(1,
"TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", last,
NUM_HOUSES_PER_GRF);
2527 if (_cur.
grffile->housespec.size() < last) _cur.
grffile->housespec.resize(last);
2529 for (uint
id = first;
id < last; ++id) {
2530 auto &housespec = _cur.
grffile->housespec[id];
2532 if (prop != 0x08 && housespec ==
nullptr) {
2535 if (cir > ret) ret = cir;
2541 uint8_t subs_id = buf.ReadByte();
2542 if (subs_id == 0xFF) {
2549 GrfMsg(2,
"TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id,
id);
2554 if (housespec ==
nullptr) {
2556 housespec = std::make_unique<HouseSpec>(*
HouseSpec::Get(subs_id));
2558 housespec->enabled =
true;
2559 housespec->grf_prop.local_id = id;
2560 housespec->grf_prop.subst_id = subs_id;
2561 housespec->grf_prop.SetGRFFile(_cur.
grffile);
2563 housespec->random_colour[0] = COLOUR_RED;
2564 housespec->random_colour[1] = COLOUR_BLUE;
2565 housespec->random_colour[2] = COLOUR_ORANGE;
2566 housespec->random_colour[3] = COLOUR_GREEN;
2569 housespec->building_flags.Reset(BuildingFlag::IsChurch).Reset(BuildingFlag::IsStadium);
2575 CargoType cargo_type = housespec->accepts_cargo[2];
2576 if (!
IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(housespec->accepts_cargo_label[2]);
2578 housespec->cargo_acceptance[2] = 0;
2589 uint16_t years = buf.ReadWord();
2596 housespec->population = buf.ReadByte();
2600 housespec->mail_generation = buf.ReadByte();
2605 housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2609 int8_t goods = buf.ReadByte();
2619 housespec->accepts_cargo[2] = cargo_type;
2620 housespec->accepts_cargo_label[2] =
CT_INVALID;
2621 housespec->cargo_acceptance[2] =
abs(goods);
2626 housespec->remove_rating_decrease = buf.ReadWord();
2630 housespec->removal_cost = buf.ReadByte();
2638 housespec->building_availability = (
HouseZones)buf.ReadWord();
2642 auto mask = housespec->callback_mask.base();
2643 SB(mask, 0, 8, buf.ReadByte());
2649 uint8_t
override = buf.ReadByte();
2653 GrfMsg(2,
"TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.",
override,
id);
2657 _house_mngr.
Add(
id, _cur.
grffile->grfid,
override);
2662 housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2666 for (uint j = 0; j < 4; j++) housespec->random_colour[j] =
static_cast<Colours
>(
GB(buf.ReadByte(), 0, 4));
2670 housespec->probability = buf.ReadByte();
2674 housespec->extra_flags =
static_cast<HouseExtraFlags>(buf.ReadByte());
2678 housespec->animation.frames = buf.ReadByte();
2679 housespec->animation.status =
GB(housespec->animation.frames, 7, 1);
2680 SB(housespec->animation.frames, 7, 1, 0);
2684 housespec->animation.speed =
Clamp(buf.ReadByte(), 2, 16);
2688 housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.
grffile->grfid);
2692 auto mask = housespec->callback_mask.base();
2693 SB(mask, 8, 8, buf.ReadByte());
2699 uint32_t cargotypes = buf.ReadDWord();
2702 if (cargotypes == 0xFFFFFFFF)
break;
2706 uint8_t cargo_part =
GB(cargotypes, 8 * j, 8);
2711 housespec->cargo_acceptance[j] = 0;
2713 housespec->accepts_cargo[j] = cargo;
2715 housespec->accepts_cargo_label[j] =
CT_INVALID;
2721 housespec->minimum_life = buf.ReadByte();
2725 uint8_t count = buf.ReadByte();
2726 for (uint8_t j = 0; j < count; j++) {
2743 uint count = buf.ReadByte();
2744 if (count >
lengthof(housespec->accepts_cargo)) {
2752 for (uint i = 0; i <
lengthof(housespec->accepts_cargo); i++) {
2755 housespec->cargo_acceptance[i] = buf.ReadByte();
2757 housespec->accepts_cargo[i] = INVALID_CARGO;
2758 housespec->cargo_acceptance[i] = 0;
2760 if (i < std::size(housespec->accepts_cargo_label)) housespec->accepts_cargo_label[i] =
CT_INVALID;
2788 if (grffile ==
nullptr)
return nullptr;
2791 if (it == std::end(grffile->
language_map))
return nullptr;
2805template <
typename T,
typename TGetTableFunc>
2809 GrfMsg(1,
"LoadTranslationTable: {} translation table must start at zero", name);
2813 std::vector<T> &translation_table = gettable(*_cur.
grffile);
2814 translation_table.clear();
2815 translation_table.reserve(last);
2816 for (uint
id = first;
id < last; ++id) {
2817 translation_table.push_back(T(std::byteswap(buf.ReadDWord())));
2821 if (grf_override !=
nullptr) {
2823 GrfMsg(1,
"LoadTranslationTable: Copying {} translation table to override GRFID '{}'", name, std::byteswap(grf_override->grfid));
2824 std::vector<T> &override_table = gettable(*grf_override);
2825 override_table = translation_table;
2831static ChangeInfoResult LoadBadgeTranslationTable(uint first, uint last,
ByteReader &buf, std::vector<BadgeID> &translation_table,
const char *name)
2833 if (first != 0 && first != std::size(translation_table)) {
2834 GrfMsg(1,
"LoadBadgeTranslationTable: {} translation table must start at zero or {}", name, std::size(translation_table));
2838 if (first == 0) translation_table.clear();
2839 translation_table.reserve(last);
2840 for (uint
id = first;
id < last; ++id) {
2841 std::string_view label = buf.ReadString();
2857 for (
int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2874 return LoadTranslationTable<CargoLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
2877 return LoadTranslationTable<RailTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
2880 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
2883 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
2886 return LoadBadgeTranslationTable(first, last, buf, _cur.
grffile->
badge_list,
"Badge");
2894 for (uint
id = first;
id < last; ++id) {
2897 int factor = buf.ReadByte();
2902 GrfMsg(1,
"GlobalVarChangeInfo: Price {} out of range, ignoring",
id);
2922 uint32_t rate = buf.ReadDWord();
2930 GrfMsg(1,
"GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2937 uint16_t options = buf.ReadWord();
2946 GrfMsg(1,
"GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2958 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2970 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2982 GrfMsg(1,
"GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2989 GrfMsg(1,
"GlobalVarChangeInfo: The snowline can only be set once ({})", last);
2991 GrfMsg(1,
"GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2993 auto snow_line = std::make_unique<SnowLine>();
2997 uint8_t &level = snow_line->table[i][j];
2998 level = buf.ReadByte();
2999 if (_cur.
grffile->grf_version >= 8) {
3010 snow_line->highest_value = std::max(snow_line->highest_value, level);
3011 snow_line->lowest_value = std::min(snow_line->lowest_value, level);
3029 if (lang ==
nullptr) {
3030 GrfMsg(1,
"GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
3035 while (buf.ReadByte() != 0) {
3043 uint plural_form = buf.ReadByte();
3044 if (plural_form >= LANGUAGE_MAX_PLURAL) {
3045 GrfMsg(1,
"GlobalVarChanceInfo: Plural form {} is out of range, ignoring", plural_form);
3052 uint8_t newgrf_id = buf.ReadByte();
3053 while (newgrf_id != 0) {
3054 std::string_view name = buf.ReadString();
3069 GrfMsg(1,
"GlobalVarChangeInfo: Gender name {} is not known, ignoring",
StrMakeValid(name));
3076 GrfMsg(1,
"GlobalVarChangeInfo: Case name {} is not known, ignoring",
StrMakeValid(name));
3081 newgrf_id = buf.ReadByte();
3100 return LoadTranslationTable<CargoLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
3103 return LoadTranslationTable<RailTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
3106 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
3109 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
3112 return LoadBadgeTranslationTable(first, last, buf, _cur.
grffile->
badge_list,
"Badge");
3121 for (uint
id = first;
id < last; ++id) {
3145 uint32_t s = buf.ReadDWord();
3146 uint32_t t = buf.ReadDWord();
3153 while (buf.ReadByte() != 0) {
3181 GrfMsg(2,
"CargoChangeInfo: Cargo type {} out of range (max {})", last,
NUM_CARGO - 1);
3185 for (uint
id = first;
id < last; ++id) {
3190 cs->
bitnum = buf.ReadByte();
3229 cs->
sprite = buf.ReadWord();
3233 cs->
weight = buf.ReadByte();
3237 cs->transit_periods[0] = buf.ReadByte();
3241 cs->transit_periods[1] = buf.ReadByte();
3249 cs->rating_colour = buf.ReadByte();
3253 cs->legend_colour = buf.ReadByte();
3270 uint8_t substitute_type = buf.ReadByte();
3272 switch (substitute_type) {
3279 GrfMsg(1,
"CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3295 cs->
multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3299 uint8_t substitute_type = buf.ReadByte();
3301 switch (substitute_type) {
3305 GrfMsg(1,
"CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3338 if (_cur.
grffile->sound_offset == 0) {
3339 GrfMsg(1,
"SoundEffectChangeInfo: No effects defined, skipping");
3344 GrfMsg(1,
"SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", last,
ORIGINAL_SAMPLE_COUNT + _cur.
grffile->num_sounds);
3348 for (uint
id = first;
id < last; ++id) {
3353 sound->volume =
Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3357 sound->priority = buf.ReadByte();
3361 SoundID orig_sound = buf.ReadByte();
3364 GrfMsg(1,
"SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound,
ORIGINAL_SAMPLE_COUNT);
3366 SoundEntry *old_sound = GetSound(orig_sound);
3369 *old_sound = *sound;
3411 buf.Skip(buf.ReadByte() * 2);
3434 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTILES_PER_GRF);
3439 if (_cur.
grffile->indtspec.size() < last) _cur.
grffile->indtspec.resize(last);
3441 for (uint
id = first;
id < last; ++id) {
3442 auto &tsp = _cur.
grffile->indtspec[id];
3444 if (prop != 0x08 && tsp ==
nullptr) {
3446 if (cir > ret) ret = cir;
3452 uint8_t subs_id = buf.ReadByte();
3455 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id,
id);
3460 if (tsp ==
nullptr) {
3461 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3463 tsp->enabled =
true;
3471 tsp->grf_prop.local_id = id;
3472 tsp->grf_prop.subst_id = subs_id;
3473 tsp->grf_prop.SetGRFFile(_cur.
grffile);
3480 uint8_t ovrid = buf.ReadByte();
3484 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid,
id);
3488 _industile_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
3495 uint16_t acctp = buf.ReadWord();
3497 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
3498 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
3503 tsp->slopes_refused = (
Slope)buf.ReadByte();
3511 tsp->animation.frames = buf.ReadByte();
3512 tsp->animation.status = buf.ReadByte();
3516 tsp->animation.speed = buf.ReadByte();
3520 tsp->animation.triggers = buf.ReadByte();
3528 uint8_t num_cargoes = buf.ReadByte();
3529 if (num_cargoes > std::size(tsp->acceptance)) {
3534 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3535 if (i < num_cargoes) {
3538 tsp->acceptance[i] = (int8_t)buf.ReadByte();
3540 tsp->accepts_cargo[i] = INVALID_CARGO;
3541 tsp->acceptance[i] = 0;
3543 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
3607 uint8_t num_table = buf.ReadByte();
3608 for (uint8_t j = 0; j < num_table; j++) {
3609 for (uint k = 0;; k++) {
3610 uint8_t x = buf.ReadByte();
3611 if (x == 0xFE && k == 0) {
3617 uint8_t y = buf.ReadByte();
3618 if (x == 0 && y == 0x80)
break;
3620 uint8_t gfx = buf.ReadByte();
3621 if (gfx == 0xFE) buf.ReadWord();
3635 buf.Skip(buf.ReadByte());
3639 int num_inputs = buf.ReadByte();
3640 int num_outputs = buf.ReadByte();
3641 buf.Skip(num_inputs * num_outputs * 2);
3663 const size_t size = layout.size();
3664 if (size == 0)
return false;
3666 for (
size_t i = 0; i < size - 1; i++) {
3667 for (
size_t j = i + 1; j < size; j++) {
3668 if (layout[i].ti.x == layout[j].ti.x &&
3669 layout[i].ti.y == layout[j].ti.y) {
3675 bool have_regular_tile =
false;
3676 for (
const auto &tilelayout : layout) {
3678 have_regular_tile =
true;
3683 return have_regular_tile;
3699 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTYPES_PER_GRF);
3704 if (_cur.
grffile->industryspec.size() < last) _cur.
grffile->industryspec.resize(last);
3706 for (uint
id = first;
id < last; ++id) {
3707 auto &indsp = _cur.
grffile->industryspec[id];
3709 if (prop != 0x08 && indsp ==
nullptr) {
3711 if (cir > ret) ret = cir;
3717 uint8_t subs_id = buf.ReadByte();
3718 if (subs_id == 0xFF) {
3721 _industry_specs[id].
enabled =
false;
3725 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id,
id);
3732 if (indsp ==
nullptr) {
3733 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3735 indsp->enabled =
true;
3736 indsp->grf_prop.local_id = id;
3737 indsp->grf_prop.subst_id = subs_id;
3738 indsp->grf_prop.SetGRFFile(_cur.
grffile);
3747 uint8_t ovrid = buf.ReadByte();
3751 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid,
id);
3754 indsp->grf_prop.override = ovrid;
3755 _industry_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
3760 uint8_t new_num_layouts = buf.ReadByte();
3761 uint32_t definition_size = buf.ReadDWord();
3762 uint32_t bytes_read = 0;
3763 std::vector<IndustryTileLayout> new_layouts;
3766 for (uint8_t j = 0; j < new_num_layouts; j++) {
3768 layout.reserve(new_num_layouts);
3770 for (uint k = 0;; k++) {
3771 if (bytes_read >= definition_size) {
3772 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.",
id);
3774 definition_size = UINT32_MAX;
3779 it.ti.
x = buf.ReadByte();
3782 if (it.ti.
x == 0xFE && k == 0) {
3784 IndustryType type = buf.ReadByte();
3785 uint8_t laynbr = buf.ReadByte();
3788 if (type >=
lengthof(_origin_industry_specs)) {
3789 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}",
id);
3793 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3794 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}",
id);
3798 layout = _origin_industry_specs[type].layouts[laynbr];
3802 it.ti.
y = buf.ReadByte();
3805 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
3811 it.gfx = buf.ReadByte();
3814 if (it.gfx == 0xFE) {
3816 int local_tile_id = buf.ReadWord();
3820 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3823 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id,
id);
3829 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
3830 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
3839 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
3845 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring",
id);
3849 new_layouts.push_back(layout);
3854 indsp->layouts = new_layouts;
3875 indsp->cost_multiplier = buf.ReadByte();
3895 indsp->production_rate[prop - 0x12] = buf.ReadByte();
3899 indsp->minimal_cargo = buf.ReadByte();
3903 uint8_t num_sounds = buf.ReadByte();
3905 std::vector<uint8_t> sounds;
3906 sounds.reserve(num_sounds);
3907 for (uint8_t j = 0; j < num_sounds; ++j) {
3908 sounds.push_back(buf.ReadByte());
3911 indsp->random_sounds = std::move(sounds);
3916 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3928 indsp->map_colour = buf.ReadByte();
3942 uint32_t multiples = buf.ReadDWord();
3943 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
3944 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
3953 indsp->prospecting_chance = buf.ReadDWord();
3958 auto mask = indsp->callback_mask.base();
3959 SB(mask, (prop - 0x21) * 8, 8, buf.ReadByte());
3965 indsp->removal_cost_multiplier = buf.ReadDWord();
3971 indsp->station_name = STR_NULL;
3979 uint8_t num_cargoes = buf.ReadByte();
3980 if (num_cargoes > std::size(indsp->produced_cargo)) {
3985 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3986 if (i < num_cargoes) {
3988 indsp->produced_cargo[i] = cargo;
3990 indsp->produced_cargo[i] = INVALID_CARGO;
3992 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
3998 uint8_t num_cargoes = buf.ReadByte();
3999 if (num_cargoes > std::size(indsp->accepts_cargo)) {
4004 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
4005 if (i < num_cargoes) {
4007 indsp->accepts_cargo[i] = cargo;
4009 indsp->accepts_cargo[i] = INVALID_CARGO;
4011 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
4017 uint8_t num_cargoes = buf.ReadByte();
4018 if (num_cargoes >
lengthof(indsp->production_rate)) {
4023 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
4024 if (i < num_cargoes) {
4025 indsp->production_rate[i] = buf.ReadByte();
4027 indsp->production_rate[i] = 0;
4034 uint8_t num_inputs = buf.ReadByte();
4035 uint8_t num_outputs = buf.ReadByte();
4036 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
4041 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
4042 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
4044 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
4045 indsp->input_cargo_multiplier[i][j] = mult;
4077 GrfMsg(1,
"AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", last,
NUM_AIRPORTS_PER_GRF);
4082 if (_cur.
grffile->airportspec.size() < last) _cur.
grffile->airportspec.resize(last);
4084 for (uint
id = first;
id < last; ++id) {
4085 auto &as = _cur.
grffile->airportspec[id];
4087 if (as ==
nullptr && prop != 0x08 && prop != 0x09) {
4088 GrfMsg(2,
"AirportChangeInfo: Attempt to modify undefined airport {}, ignoring",
id);
4094 uint8_t subs_id = buf.ReadByte();
4095 if (subs_id == 0xFF) {
4102 GrfMsg(2,
"AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id,
id);
4109 if (as ==
nullptr) {
4113 as->grf_prop.local_id = id;
4114 as->grf_prop.subst_id = subs_id;
4115 as->grf_prop.SetGRFFile(_cur.
grffile);
4117 _airport_mngr.
Add(
id, _cur.
grffile->grfid, subs_id);
4123 uint8_t num_layouts = buf.ReadByte();
4128 std::vector<AirportTileLayout> layouts;
4129 layouts.reserve(num_layouts);
4131 for (uint8_t j = 0; j != num_layouts; ++j) {
4132 auto &layout = layouts.emplace_back();
4133 layout.rotation =
static_cast<Direction>(buf.ReadByte() & 6);
4136 auto &tile = layout.tiles.emplace_back();
4137 tile.ti.x = buf.ReadByte();
4138 tile.ti.y = buf.ReadByte();
4139 if (tile.ti.x == 0 && tile.ti.y == 0x80) {
4147 tile.gfx = buf.ReadByte();
4149 if (tile.gfx == 0xFE) {
4151 int local_tile_id = buf.ReadWord();
4154 uint16_t tempid = _airporttile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
4157 GrfMsg(2,
"AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id,
id);
4162 }
else if (tile.gfx == 0xFF) {
4163 tile.ti.x =
static_cast<int8_t
>(
GB(tile.ti.x, 0, 8));
4164 tile.ti.y =
static_cast<int8_t
>(
GB(tile.ti.y, 0, 8));
4168 if (layout.rotation ==
DIR_E || layout.rotation ==
DIR_W) {
4169 size_x = std::max<uint8_t>(size_x, tile.ti.y + 1);
4170 size_y = std::max<uint8_t>(size_y, tile.ti.x + 1);
4172 size_x = std::max<uint8_t>(size_x, tile.ti.x + 1);
4173 size_y = std::max<uint8_t>(size_y, tile.ti.y + 1);
4177 as->layouts = std::move(layouts);
4178 as->size_x = size_x;
4179 as->size_y = size_y;
4198 as->noise_level = buf.ReadByte();
4206 as->maintenance_cost = buf.ReadWord();
4284 GrfMsg(1,
"ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.", last,
NUM_OBJECTS_PER_GRF);
4289 if (_cur.
grffile->objectspec.size() < last) _cur.
grffile->objectspec.resize(last);
4291 for (uint
id = first;
id < last; ++id) {
4292 auto &spec = _cur.
grffile->objectspec[id];
4294 if (prop != 0x08 && spec ==
nullptr) {
4297 if (cir > ret) ret = cir;
4304 if (spec ==
nullptr) {
4305 spec = std::make_unique<ObjectSpec>();
4311 uint32_t classid = buf.ReadDWord();
4330 spec->size = buf.ReadByte();
4331 if (
GB(spec->size, 0, 4) == 0 ||
GB(spec->size, 4, 4) == 0) {
4332 GrfMsg(0,
"ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size,
id);
4338 spec->build_cost_multiplier = buf.ReadByte();
4339 spec->clear_cost_multiplier = spec->build_cost_multiplier;
4343 spec->introduction_date = TimerGameCalendar::Date(buf.ReadDWord());
4347 spec->end_of_life_date = TimerGameCalendar::Date(buf.ReadDWord());
4356 spec->animation.frames = buf.ReadByte();
4357 spec->animation.status = buf.ReadByte();
4361 spec->animation.speed = buf.ReadByte();
4365 spec->animation.triggers = buf.ReadWord();
4369 spec->clear_cost_multiplier = buf.ReadByte();
4377 spec->height = buf.ReadByte();
4381 spec->views = buf.ReadByte();
4382 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
4383 GrfMsg(2,
"ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views,
id);
4389 spec->generate_amount = buf.ReadByte();
4420 GrfMsg(1,
"RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring", last,
RAILTYPE_END);
4424 for (uint
id = first;
id < last; ++id) {
4439 if (_cur.
grffile->grf_version < 8) {
4469 int n = buf.ReadByte();
4470 for (
int j = 0; j != n; j++) {
4471 RailTypeLabel label = buf.ReadDWord();
4531 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4554 GrfMsg(1,
"RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring", last,
RAILTYPE_END);
4558 for (uint
id = first;
id < last; ++id) {
4562 RailTypeLabel rtl = buf.ReadDWord();
4571 _cur.
grffile->railtype_map[id] = rt;
4589 int n = buf.ReadByte();
4590 for (
int j = 0; j != n; j++) {
4595 GrfMsg(1,
"RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set",
id);
4602 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4645 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.
grffile->roadtype_map;
4648 GrfMsg(1,
"RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring", last,
ROADTYPE_END);
4652 for (uint
id = first;
id < last; ++id) {
4690 int n = buf.ReadByte();
4691 for (
int j = 0; j != n; j++) {
4692 RoadTypeLabel label = buf.ReadDWord();
4697 if (GetRoadTramType(resolved_rt) == rtt) {
4700 GrfMsg(1,
"RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4745 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4777 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
4780 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring", last,
ROADTYPE_END);
4784 for (uint
id = first;
id < last; ++id) {
4787 RoadTypeLabel rtl = buf.ReadDWord();
4794 }
else if (GetRoadTramType(rt) != rtt) {
4795 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring",
id);
4816 int n = buf.ReadByte();
4817 for (
int j = 0; j != n; j++) {
4818 _roadtypes[type_map[id]].
alternate_labels.push_back(std::byteswap(buf.ReadDWord()));
4822 GrfMsg(1,
"RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set",
id);
4828 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4856 return RoadTypeReserveInfo(first, last, prop, buf, RTT_ROAD);
4861 return RoadTypeReserveInfo(first, last, prop, buf, RTT_TRAM);
4869 GrfMsg(1,
"AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", last,
NUM_AIRPORTTILES_PER_GRF);
4874 if (_cur.
grffile->airtspec.size() < last) _cur.
grffile->airtspec.resize(last);
4876 for (uint
id = first;
id < last; ++id) {
4877 auto &tsp = _cur.
grffile->airtspec[id];
4879 if (prop != 0x08 && tsp ==
nullptr) {
4880 GrfMsg(2,
"AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.",
id);
4886 uint8_t subs_id = buf.ReadByte();
4889 GrfMsg(2,
"AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id,
id);
4894 if (tsp ==
nullptr) {
4897 tsp->enabled =
true;
4901 tsp->grf_prop.local_id = id;
4902 tsp->grf_prop.subst_id = subs_id;
4903 tsp->grf_prop.SetGRFFile(_cur.
grffile);
4910 uint8_t
override = buf.ReadByte();
4914 GrfMsg(2,
"AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.",
override,
id);
4918 _airporttile_mngr.
Add(
id, _cur.
grffile->grfid,
override);
4927 tsp->animation.frames = buf.ReadByte();
4928 tsp->animation.status = buf.ReadByte();
4932 tsp->animation.speed = buf.ReadByte();
4936 tsp->animation.triggers = buf.ReadByte();
5000 if (last >= UINT16_MAX) {
5001 GrfMsg(1,
"BadgeChangeInfo: Tag {} is invalid, max {}, ignoring", last, UINT16_MAX - 1);
5005 for (uint
id = first;
id < last; ++id) {
5006 auto it = _cur.
grffile->badge_map.find(
id);
5007 if (prop != 0x08 && it == std::end(_cur.
grffile->badge_map)) {
5008 GrfMsg(1,
"BadgeChangeInfo: Attempt to modify undefined tag {}, ignoring",
id);
5012 Badge *badge =
nullptr;
5013 if (prop != 0x08) badge =
GetBadge(it->second);
5017 std::string_view label = buf.ReadString();
5040 GrfMsg(1,
"RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring", last,
NUM_ROADSTOPS_PER_GRF);
5044 if (_cur.
grffile->roadstops.size() < last) _cur.
grffile->roadstops.resize(last);
5046 for (uint
id = first;
id < last; ++id) {
5047 auto &rs = _cur.
grffile->roadstops[id];
5049 if (rs ==
nullptr && prop != 0x08) {
5050 GrfMsg(1,
"RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring",
id);
5052 if (cir > ret) ret = cir;
5058 if (rs ==
nullptr) {
5059 rs = std::make_unique<RoadStopSpec>();
5062 uint32_t classid = buf.ReadDWord();
5088 rs->animation.frames = buf.ReadByte();
5089 rs->animation.status = buf.ReadByte();
5093 rs->animation.speed = buf.ReadByte();
5097 rs->animation.triggers = buf.ReadWord();
5109 rs->build_cost_multiplier = buf.ReadByte();
5110 rs->clear_cost_multiplier = buf.ReadByte();
5126static bool HandleChangeInfoResult(
const char *caller,
ChangeInfoResult cir, uint8_t feature, uint8_t property)
5129 default: NOT_REACHED();
5139 GrfMsg(1,
"{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
5143 GrfMsg(0,
"{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
5156static void FeatureChangeInfo(
ByteReader &buf)
5169 static ChangeInfoHandler *
const handler[] = {
5187 AirportTilesChangeInfo,
5193 static_assert(GSF_END == std::size(handler));
5195 uint8_t feature = buf.ReadByte();
5196 uint8_t numprops = buf.ReadByte();
5197 uint numinfo = buf.ReadByte();
5198 uint engine = buf.ReadExtendedByte();
5200 if (feature >= GSF_END) {
5201 GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
5205 GrfMsg(6,
"FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
5206 feature, numprops, engine, numinfo);
5208 if (handler[feature] ==
nullptr) {
5209 if (feature != GSF_CARGOES) GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
5216 while (numprops-- && buf.HasData()) {
5217 uint8_t prop = buf.ReadByte();
5219 ChangeInfoResult cir = handler[feature](engine, engine + numinfo, prop, buf);
5220 if (HandleChangeInfoResult(
"FeatureChangeInfo", cir, feature, prop))
return;
5227 uint8_t feature = buf.ReadByte();
5228 uint8_t numprops = buf.ReadByte();
5229 uint numinfo = buf.ReadByte();
5230 buf.ReadExtendedByte();
5232 if (feature == GSF_BRIDGES && numprops == 1) {
5233 uint8_t prop = buf.ReadByte();
5236 if (prop == 0x0D)
return;
5237 }
else if (feature == GSF_GLOBALVAR && numprops == 1) {
5238 uint8_t prop = buf.ReadByte();
5241 bool is_safe =
true;
5242 for (uint i = 0; i < numinfo; i++) {
5243 uint32_t s = buf.ReadDWord();
5251 if (is_safe)
return;
5262static void ReserveChangeInfo(
ByteReader &buf)
5264 uint8_t feature = buf.ReadByte();
5266 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES)
return;
5268 uint8_t numprops = buf.ReadByte();
5269 uint8_t numinfo = buf.ReadByte();
5270 uint16_t index = buf.ReadExtendedByte();
5272 while (numprops-- && buf.HasData()) {
5273 uint8_t prop = buf.ReadByte();
5277 default: NOT_REACHED();
5283 cir = GlobalVarReserveInfo(index, index + numinfo, prop, buf);
5287 cir = RailTypeReserveInfo(index, index + numinfo, prop, buf);
5291 cir = RoadTypeReserveInfo(index, index + numinfo, prop, buf);
5295 cir = TramTypeReserveInfo(index, index + numinfo, prop, buf);
5299 if (HandleChangeInfoResult(
"ReserveChangeInfo", cir, feature, prop))
return;
5320 uint8_t feature = buf.ReadByte();
5321 uint16_t num_sets = buf.ReadByte();
5322 uint16_t first_set = 0;
5324 if (num_sets == 0 && buf.HasData(3)) {
5327 first_set = buf.ReadExtendedByte();
5328 num_sets = buf.ReadExtendedByte();
5330 uint16_t num_ents = buf.ReadExtendedByte();
5332 if (feature >= GSF_END) {
5334 GrfMsg(1,
"NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.
skip_sprites);
5340 GrfMsg(7,
"New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
5341 _cur.
spriteid, feature, num_sets, num_ents, num_sets * num_ents
5344 for (
int i = 0; i < num_sets * num_ents; i++) {
5354 uint16_t num_sets = buf.ReadByte();
5356 if (num_sets == 0 && buf.HasData(3)) {
5359 buf.ReadExtendedByte();
5360 num_sets = buf.ReadExtendedByte();
5362 uint16_t num_ents = buf.ReadExtendedByte();
5366 GrfMsg(3,
"SkipAct1: Skipping {} sprites", _cur.
skip_sprites);
5369using CachedCallback = std::pair<uint16_t, SpriteGroupID>;
5372static const SpriteGroup *GetCallbackResultGroup(uint16_t value)
5376 if (_cur.
grffile->grf_version < 8 &&
GB(value, 8, 8) == 0xFF) {
5395static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5397 if (
HasBit(groupid, 15))
return GetCallbackResultGroup(groupid);
5399 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5400 GrfMsg(1,
"GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
5404 return _cur.spritegroups[groupid];
5417 if (
HasBit(spriteid, 15))
return GetCallbackResultGroup(spriteid);
5420 GrfMsg(1,
"CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5425 uint num_sprites = _cur.
GetNumEnts(feature, spriteid);
5428 assert(spriteset_start + num_sprites <= _cur.
spriteid);
5449 uint8_t feature = buf.ReadByte();
5450 if (feature >= GSF_END) {
5451 GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5455 uint8_t setid = buf.ReadByte();
5456 uint8_t type = buf.ReadByte();
5480 switch (
GB(type, 2, 2)) {
5481 default: NOT_REACHED();
5482 case 0: group->size = DSG_SIZE_BYTE; varsize = 1;
break;
5483 case 1: group->size = DSG_SIZE_WORD; varsize = 2;
break;
5484 case 2: group->size = DSG_SIZE_DWORD; varsize = 4;
break;
5494 adjust.variable = buf.ReadByte();
5495 if (adjust.variable == 0x7E) {
5497 adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5502 varadjust = buf.ReadByte();
5503 adjust.shift_num =
GB(varadjust, 0, 5);
5504 adjust.type = (DeterministicSpriteGroupAdjustType)
GB(varadjust, 6, 2);
5505 adjust.and_mask = buf.ReadVarSize(varsize);
5507 if (adjust.type != DSGA_TYPE_NONE) {
5508 adjust.add_val = buf.ReadVarSize(varsize);
5509 adjust.divmod_val = buf.ReadVarSize(varsize);
5510 if (adjust.divmod_val == 0) adjust.divmod_val = 1;
5513 adjust.divmod_val = 0;
5517 }
while (
HasBit(varadjust, 5));
5519 std::vector<DeterministicSpriteGroupRange> ranges;
5520 ranges.resize(buf.ReadByte());
5521 for (
auto &range : ranges) {
5522 range.group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5523 range.low = buf.ReadVarSize(varsize);
5524 range.high = buf.ReadVarSize(varsize);
5527 group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5528 group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5530 group->calculated_result = ranges.empty();
5533 std::vector<uint32_t> bounds;
5534 bounds.reserve(ranges.size());
5535 for (
const auto &range : ranges) {
5536 bounds.push_back(range.low);
5537 if (range.high != UINT32_MAX) bounds.push_back(range.high + 1);
5539 std::sort(bounds.begin(), bounds.end());
5540 bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5542 std::vector<const SpriteGroup *> target;
5543 target.reserve(bounds.size());
5544 for (
const auto &bound : bounds) {
5546 for (
const auto &range : ranges) {
5547 if (range.low <= bound && bound <= range.high) {
5552 target.push_back(t);
5554 assert(target.size() == bounds.size());
5556 for (uint j = 0; j < bounds.size(); ) {
5557 if (target[j] != group->default_group) {
5559 r.group = target[j];
5561 while (j < bounds.size() && target[j] == r.group) {
5564 r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5586 group->count = buf.ReadByte();
5589 uint8_t triggers = buf.ReadByte();
5590 group->triggers =
GB(triggers, 0, 7);
5591 group->
cmp_mode =
HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
5594 uint8_t num_groups = buf.ReadByte();
5596 GrfMsg(1,
"NewSpriteGroup: Random Action 2 nrand should be power of 2");
5599 group->
groups.reserve(num_groups);
5600 for (uint i = 0; i < num_groups; i++) {
5601 group->
groups.push_back(GetGroupFromGroupID(setid, type, buf.ReadWord()));
5612 case GSF_ROADVEHICLES:
5624 uint8_t num_loaded = type;
5625 uint8_t num_loading = buf.ReadByte();
5628 GrfMsg(0,
"NewSpriteGroup: No sprite set to work on! Skipping");
5632 GrfMsg(6,
"NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5633 setid, num_loaded, num_loading);
5635 if (num_loaded + num_loading == 0) {
5636 GrfMsg(1,
"NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5640 if (num_loaded + num_loading == 1) {
5642 uint16_t spriteid = buf.ReadWord();
5644 GrfMsg(8,
"NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5648 std::vector<uint16_t> loaded;
5649 std::vector<uint16_t> loading;
5651 loaded.reserve(num_loaded);
5652 for (uint i = 0; i < num_loaded; i++) {
5653 loaded.push_back(buf.ReadWord());
5654 GrfMsg(8,
"NewSpriteGroup: + rg->loaded[{}] = subset {}", i, loaded[i]);
5657 loading.reserve(num_loading);
5658 for (uint i = 0; i < num_loading; i++) {
5659 loading.push_back(buf.ReadWord());
5660 GrfMsg(8,
"NewSpriteGroup: + rg->loading[{}] = subset {}", i, loading[i]);
5663 bool loaded_same = !loaded.empty() && std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end();
5664 bool loading_same = !loading.empty() && std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end();
5665 if (loaded_same && loading_same && loaded[0] == loading[0]) {
5668 GrfMsg(8,
"NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5677 if (loaded_same && loaded.size() > 1) loaded.resize(1);
5678 group->
loaded.reserve(loaded.size());
5679 for (uint16_t spriteid : loaded) {
5681 group->
loaded.push_back(t);
5684 if (loading_same && loading.size() > 1) loading.resize(1);
5685 group->
loading.reserve(loading.size());
5686 for (uint16_t spriteid : loading) {
5695 case GSF_AIRPORTTILES:
5697 case GSF_INDUSTRYTILES:
5698 case GSF_ROADSTOPS: {
5699 uint8_t num_building_sprites = std::max((uint8_t)1, type);
5707 if (
ReadSpriteLayout(buf, num_building_sprites,
true, feature,
false, type == 0, &group->dts))
return;
5711 case GSF_INDUSTRIES: {
5713 GrfMsg(1,
"NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5731 group->again = buf.ReadByte();
5732 }
else if (type == 1) {
5741 group->again = buf.ReadByte();
5742 }
else if (type == 2) {
5746 error->
data =
"too many inputs (max 16)";
5749 for (uint i = 0; i < group->
num_input; i++) {
5750 uint8_t rawcargo = buf.ReadByte();
5757 }
else if (
auto v = group->
cargo_input | std::views::take(i); std::ranges::find(v, cargo) != v.end()) {
5759 error->
data =
"duplicate input cargo";
5768 error->
data =
"too many outputs (max 16)";
5771 for (uint i = 0; i < group->
num_output; i++) {
5772 uint8_t rawcargo = buf.ReadByte();
5777 }
else if (
auto v = group->
cargo_output | std::views::take(i); std::ranges::find(v, cargo) != v.end()) {
5779 error->
data =
"duplicate output cargo";
5785 group->again = buf.ReadByte();
5793 default: GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5798 _cur.spritegroups[setid] = act_group;
5818static CargoType TranslateCargo(uint8_t feature, uint8_t ctype)
5827 if (ctype >= cargo_list.size()) {
5828 GrfMsg(1,
"TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (
unsigned int)_cur.
grffile->
cargo_list.size() - 1);
5829 return INVALID_CARGO;
5835 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5836 return INVALID_CARGO;
5839 CargoType cargo_type = GetCargoTypeByLabel(cl);
5841 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));
5842 return INVALID_CARGO;
5845 GrfMsg(6,
"TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' mapped to cargo type {}.",
GB(cl.base(), 24, 8),
GB(cl.base(), 16, 8),
GB(cl.base(), 8, 8),
GB(cl.base(), 0, 8), cargo_type);
5850static bool IsValidGroupID(uint16_t groupid,
const char *function)
5852 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5853 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
5860static void VehicleMapSpriteGroup(
ByteReader &buf, uint8_t feature, uint8_t idcount)
5862 static std::vector<EngineID> last_engines;
5863 bool wagover =
false;
5866 if (
HasBit(idcount, 7)) {
5869 idcount =
GB(idcount, 0, 7);
5871 if (last_engines.empty()) {
5872 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5876 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5878 last_engines.resize(idcount);
5881 std::vector<EngineID> engines;
5882 engines.reserve(idcount);
5883 for (uint i = 0; i < idcount; i++) {
5889 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, 0, 0);
5893 engines.push_back(e->
index);
5894 if (!wagover) last_engines[i] = engines[i];
5897 uint8_t cidcount = buf.ReadByte();
5898 for (uint c = 0; c < cidcount; c++) {
5899 uint8_t ctype = buf.ReadByte();
5900 uint16_t groupid = buf.ReadWord();
5901 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
5903 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5905 CargoType cargo_type = TranslateCargo(feature, ctype);
5908 for (uint i = 0; i < idcount; i++) {
5911 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5914 SetWagonOverrideSprites(engine, cargo_type, _cur.spritegroups[groupid], last_engines);
5916 SetCustomEngineSprites(engine, cargo_type, _cur.spritegroups[groupid]);
5921 uint16_t groupid = buf.ReadWord();
5922 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
5924 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
5926 for (uint i = 0; i < idcount; i++) {
5939static void CanalMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5941 std::vector<uint16_t> cfs;
5942 cfs.reserve(idcount);
5943 for (uint i = 0; i < idcount; i++) {
5944 cfs.push_back(buf.ReadExtendedByte());
5947 uint8_t cidcount = buf.ReadByte();
5948 buf.Skip(cidcount * 3);
5950 uint16_t groupid = buf.ReadWord();
5951 if (!IsValidGroupID(groupid,
"CanalMapSpriteGroup"))
return;
5953 for (
auto &cf : cfs) {
5955 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5965static void StationMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5967 if (_cur.
grffile->stations.empty()) {
5968 GrfMsg(1,
"StationMapSpriteGroup: No stations defined, skipping");
5972 std::vector<uint16_t> stations;
5973 stations.reserve(idcount);
5974 for (uint i = 0; i < idcount; i++) {
5975 stations.push_back(buf.ReadExtendedByte());
5978 uint8_t cidcount = buf.ReadByte();
5979 for (uint c = 0; c < cidcount; c++) {
5980 uint8_t ctype = buf.ReadByte();
5981 uint16_t groupid = buf.ReadWord();
5982 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
continue;
5984 ctype = TranslateCargo(GSF_STATIONS, ctype);
5987 for (
auto &station : stations) {
5990 if (statspec ==
nullptr) {
5991 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5999 uint16_t groupid = buf.ReadWord();
6000 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
return;
6002 for (
auto &station : stations) {
6005 if (statspec ==
nullptr) {
6006 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
6011 GrfMsg(1,
"StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
6023static void TownHouseMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6025 if (_cur.
grffile->housespec.empty()) {
6026 GrfMsg(1,
"TownHouseMapSpriteGroup: No houses defined, skipping");
6030 std::vector<uint16_t> houses;
6031 houses.reserve(idcount);
6032 for (uint i = 0; i < idcount; i++) {
6033 houses.push_back(buf.ReadExtendedByte());
6037 uint8_t cidcount = buf.ReadByte();
6038 buf.Skip(cidcount * 3);
6040 uint16_t groupid = buf.ReadWord();
6041 if (!IsValidGroupID(groupid,
"TownHouseMapSpriteGroup"))
return;
6043 for (
auto &house : houses) {
6046 if (hs ==
nullptr) {
6047 GrfMsg(1,
"TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
6055static void IndustryMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6057 if (_cur.
grffile->industryspec.empty()) {
6058 GrfMsg(1,
"IndustryMapSpriteGroup: No industries defined, skipping");
6062 std::vector<uint16_t> industries;
6063 industries.reserve(idcount);
6064 for (uint i = 0; i < idcount; i++) {
6065 industries.push_back(buf.ReadExtendedByte());
6069 uint8_t cidcount = buf.ReadByte();
6070 buf.Skip(cidcount * 3);
6072 uint16_t groupid = buf.ReadWord();
6073 if (!IsValidGroupID(groupid,
"IndustryMapSpriteGroup"))
return;
6075 for (
auto &industry : industries) {
6078 if (indsp ==
nullptr) {
6079 GrfMsg(1,
"IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
6087static void IndustrytileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6089 if (_cur.
grffile->indtspec.empty()) {
6090 GrfMsg(1,
"IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
6094 std::vector<uint16_t> indtiles;
6095 indtiles.reserve(idcount);
6096 for (uint i = 0; i < idcount; i++) {
6097 indtiles.push_back(buf.ReadExtendedByte());
6101 uint8_t cidcount = buf.ReadByte();
6102 buf.Skip(cidcount * 3);
6104 uint16_t groupid = buf.ReadWord();
6105 if (!IsValidGroupID(groupid,
"IndustrytileMapSpriteGroup"))
return;
6107 for (
auto &indtile : indtiles) {
6110 if (indtsp ==
nullptr) {
6111 GrfMsg(1,
"IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
6119static void CargoMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6121 std::vector<uint16_t> cargoes;
6122 cargoes.reserve(idcount);
6123 for (uint i = 0; i < idcount; i++) {
6124 cargoes.push_back(buf.ReadExtendedByte());
6128 uint8_t cidcount = buf.ReadByte();
6129 buf.Skip(cidcount * 3);
6131 uint16_t groupid = buf.ReadWord();
6132 if (!IsValidGroupID(groupid,
"CargoMapSpriteGroup"))
return;
6134 for (
auto &cargo_type : cargoes) {
6136 GrfMsg(1,
"CargoMapSpriteGroup: Cargo type {} out of range, skipping", cargo_type);
6142 cs->group = _cur.spritegroups[groupid];
6146static void ObjectMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6148 if (_cur.
grffile->objectspec.empty()) {
6149 GrfMsg(1,
"ObjectMapSpriteGroup: No object tiles defined, skipping");
6153 std::vector<uint16_t> objects;
6154 objects.reserve(idcount);
6155 for (uint i = 0; i < idcount; i++) {
6156 objects.push_back(buf.ReadExtendedByte());
6159 uint8_t cidcount = buf.ReadByte();
6160 for (uint c = 0; c < cidcount; c++) {
6161 uint8_t ctype = buf.ReadByte();
6162 uint16_t groupid = buf.ReadWord();
6163 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
continue;
6166 if (ctype != 0xFF) {
6167 GrfMsg(1,
"ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
6171 for (
auto &
object : objects) {
6174 if (spec ==
nullptr) {
6175 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
6183 uint16_t groupid = buf.ReadWord();
6184 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
return;
6186 for (
auto &
object : objects) {
6189 if (spec ==
nullptr) {
6190 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
6195 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} mapped multiple times, skipping",
object);
6205static void RailTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6207 std::vector<uint8_t> railtypes;
6208 railtypes.reserve(idcount);
6209 for (uint i = 0; i < idcount; i++) {
6210 uint16_t
id = buf.ReadExtendedByte();
6211 railtypes.push_back(id < RAILTYPE_END ? _cur.grffile->railtype_map[
id] :
INVALID_RAILTYPE);
6214 uint8_t cidcount = buf.ReadByte();
6215 for (uint c = 0; c < cidcount; c++) {
6216 uint8_t ctype = buf.ReadByte();
6217 uint16_t groupid = buf.ReadWord();
6218 if (!IsValidGroupID(groupid,
"RailTypeMapSpriteGroup"))
continue;
6220 if (ctype >= RTSG_END)
continue;
6223 for (
auto &railtype : railtypes) {
6228 rti->
group[ctype] = _cur.spritegroups[groupid];
6237static void RoadTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount, RoadTramType rtt)
6239 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
6241 std::vector<uint8_t> roadtypes;
6242 roadtypes.reserve(idcount);
6243 for (uint i = 0; i < idcount; i++) {
6244 uint16_t
id = buf.ReadExtendedByte();
6248 uint8_t cidcount = buf.ReadByte();
6249 for (uint c = 0; c < cidcount; c++) {
6250 uint8_t ctype = buf.ReadByte();
6251 uint16_t groupid = buf.ReadWord();
6252 if (!IsValidGroupID(groupid,
"RoadTypeMapSpriteGroup"))
continue;
6254 if (ctype >= ROTSG_END)
continue;
6257 for (
auto &roadtype : roadtypes) {
6262 rti->
group[ctype] = _cur.spritegroups[groupid];
6271static void AirportMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6273 if (_cur.
grffile->airportspec.empty()) {
6274 GrfMsg(1,
"AirportMapSpriteGroup: No airports defined, skipping");
6278 std::vector<uint16_t> airports;
6279 airports.reserve(idcount);
6280 for (uint i = 0; i < idcount; i++) {
6281 airports.push_back(buf.ReadExtendedByte());
6285 uint8_t cidcount = buf.ReadByte();
6286 buf.Skip(cidcount * 3);
6288 uint16_t groupid = buf.ReadWord();
6289 if (!IsValidGroupID(groupid,
"AirportMapSpriteGroup"))
return;
6291 for (
auto &airport : airports) {
6294 if (as ==
nullptr) {
6295 GrfMsg(1,
"AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6303static void AirportTileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6305 if (_cur.
grffile->airtspec.empty()) {
6306 GrfMsg(1,
"AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6310 std::vector<uint16_t> airptiles;
6311 airptiles.reserve(idcount);
6312 for (uint i = 0; i < idcount; i++) {
6313 airptiles.push_back(buf.ReadExtendedByte());
6317 uint8_t cidcount = buf.ReadByte();
6318 buf.Skip(cidcount * 3);
6320 uint16_t groupid = buf.ReadWord();
6321 if (!IsValidGroupID(groupid,
"AirportTileMapSpriteGroup"))
return;
6323 for (
auto &airptile : airptiles) {
6326 if (airtsp ==
nullptr) {
6327 GrfMsg(1,
"AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6335static void RoadStopMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6337 if (_cur.
grffile->roadstops.empty()) {
6338 GrfMsg(1,
"RoadStopMapSpriteGroup: No roadstops defined, skipping");
6342 std::vector<uint16_t> roadstops;
6343 roadstops.reserve(idcount);
6344 for (uint i = 0; i < idcount; i++) {
6345 roadstops.push_back(buf.ReadExtendedByte());
6348 uint8_t cidcount = buf.ReadByte();
6349 for (uint c = 0; c < cidcount; c++) {
6350 uint8_t ctype = buf.ReadByte();
6351 uint16_t groupid = buf.ReadWord();
6352 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
continue;
6354 ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6357 for (
auto &roadstop : roadstops) {
6360 if (roadstopspec ==
nullptr) {
6361 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6369 uint16_t groupid = buf.ReadWord();
6370 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
return;
6372 for (
auto &roadstop : roadstops) {
6375 if (roadstopspec ==
nullptr) {
6376 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6381 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6392static void BadgeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6394 if (_cur.
grffile->badge_map.empty()) {
6395 GrfMsg(1,
"BadgeMapSpriteGroup: No badges defined, skipping");
6399 std::vector<uint16_t> local_ids;
6400 local_ids.reserve(idcount);
6401 for (uint i = 0; i < idcount; i++) {
6402 local_ids.push_back(buf.ReadExtendedByte());
6405 uint8_t cidcount = buf.ReadByte();
6406 for (uint c = 0; c < cidcount; c++) {
6407 uint8_t ctype = buf.ReadByte();
6408 uint16_t groupid = buf.ReadWord();
6409 if (!IsValidGroupID(groupid,
"BadgeMapSpriteGroup"))
continue;
6411 if (ctype >= GSF_END)
continue;
6413 for (
const auto &local_id : local_ids) {
6414 auto found = _cur.
grffile->badge_map.find(local_id);
6415 if (found == std::end(_cur.
grffile->badge_map)) {
6416 GrfMsg(1,
"BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
6420 auto &badge = *
GetBadge(found->second);
6425 uint16_t groupid = buf.ReadWord();
6426 if (!IsValidGroupID(groupid,
"BadgeMapSpriteGroup"))
return;
6428 for (
auto &local_id : local_ids) {
6429 auto found = _cur.
grffile->badge_map.find(local_id);
6430 if (found == std::end(_cur.
grffile->badge_map)) {
6431 GrfMsg(1,
"BadgeMapSpriteGroup: Badge {} undefined, skipping", local_id);
6435 auto &badge = *
GetBadge(found->second);
6443static void FeatureMapSpriteGroup(
ByteReader &buf)
6459 uint8_t feature = buf.ReadByte();
6460 uint8_t idcount = buf.ReadByte();
6462 if (feature >= GSF_END) {
6463 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6471 uint16_t groupid = buf.ReadWord();
6472 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
6474 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6483 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6487 case GSF_ROADVEHICLES:
6490 VehicleMapSpriteGroup(buf, feature, idcount);
6494 CanalMapSpriteGroup(buf, idcount);
6498 StationMapSpriteGroup(buf, idcount);
6502 TownHouseMapSpriteGroup(buf, idcount);
6505 case GSF_INDUSTRIES:
6506 IndustryMapSpriteGroup(buf, idcount);
6509 case GSF_INDUSTRYTILES:
6510 IndustrytileMapSpriteGroup(buf, idcount);
6514 CargoMapSpriteGroup(buf, idcount);
6518 AirportMapSpriteGroup(buf, idcount);
6522 ObjectMapSpriteGroup(buf, idcount);
6526 RailTypeMapSpriteGroup(buf, idcount);
6530 RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6534 RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6537 case GSF_AIRPORTTILES:
6538 AirportTileMapSpriteGroup(buf, idcount);
6542 RoadStopMapSpriteGroup(buf, idcount);
6546 BadgeMapSpriteGroup(buf, idcount);
6550 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6574 bool new_scheme = _cur.
grffile->grf_version >= 7;
6576 uint8_t feature = buf.ReadByte();
6577 if (feature >= GSF_END && feature != 0x48) {
6578 GrfMsg(1,
"FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6582 uint8_t lang = buf.ReadByte();
6583 uint8_t num = buf.ReadByte();
6584 bool generic =
HasBit(lang, 7);
6587 id = buf.ReadWord();
6588 }
else if (feature <= GSF_AIRCRAFT || feature == GSF_BADGES) {
6589 id = buf.ReadExtendedByte();
6591 id = buf.ReadByte();
6596 uint16_t endid =
id + num;
6598 GrfMsg(6,
"FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6599 id, endid, feature, lang);
6602 uint32_t feature_overlay =
generic ? 0 : ((feature + 1) << 16);
6604 for (;
id < endid && buf.HasData();
id++) {
6605 const std::string_view name = buf.ReadString();
6606 GrfMsg(8,
"FeatureNewName: 0x{:04X} <- {}",
id,
StrMakeValid(name));
6610 case GSF_ROADVEHICLES:
6615 if (e ==
nullptr)
break;
6625 auto found = _cur.
grffile->badge_map.find(
id);
6626 if (found == std::end(_cur.
grffile->badge_map)) {
6627 GrfMsg(1,
"FeatureNewName: Attempt to name undefined badge 0x{:X}, ignoring",
id);
6644 switch (
GB(
id, 8, 8)) {
6646 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6647 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6655 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6656 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6663 if (
GB(
id, 0, 8) >= _cur.
grffile->airtspec.size() || _cur.
grffile->airtspec[
GB(
id, 0, 8)] ==
nullptr) {
6664 GrfMsg(1,
"FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring",
GB(
id, 0, 8));
6671 if (
GB(
id, 0, 8) >= _cur.
grffile->housespec.size() || _cur.
grffile->housespec[
GB(
id, 0, 8)] ==
nullptr) {
6672 GrfMsg(1,
"FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.",
GB(
id, 0, 8));
6679 GrfMsg(7,
"FeatureNewName: Unsupported ID (0x{:04X})",
id);
6698 if (offset >= max_sprites) {
6699 GrfMsg(1,
"GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6700 uint orig_num = num;
6705 if (offset + num > max_sprites) {
6706 GrfMsg(4,
"GraphicsNew: {} sprite overflow, truncating...", name);
6707 uint orig_num = num;
6708 num = std::max(max_sprites - offset, 0);
6709 return orig_num - num;
6723 {
A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT,
"Signal graphics" },
6725 {
A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT,
"Foundation graphics" },
6766 uint8_t type = buf.ReadByte();
6767 uint16_t num = buf.ReadExtendedByte();
6768 uint16_t offset =
HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6774 GrfMsg(2,
"GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6791 GrfMsg(2,
"GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6802 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->
name, type);
6809 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->
name, type, action5_type->
min_sprites, num);
6819 GrfMsg(2,
"GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->
name, type, replace);
6831 bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= ONEWAY_SLOPE_N_OFFSET));
6833 for (; num > 0; num--) {
6837 if (dup_oneway_sprites) {
6838 DupSprite(load_index, load_index + ONEWAY_SLOPE_N_OFFSET);
6839 DupSprite(load_index, load_index + ONEWAY_SLOPE_S_OFFSET);
6855 GrfMsg(3,
"SkipAct5: Skipping {} sprites", _cur.
skip_sprites);
6908 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6938 *value = _game_mode;
6972 *value =
Clamp(snowline * (grffile->grf_version >= 8 ? 1 :
TILE_HEIGHT), 0, 0xFE);
6981 *value = _openttd_newgrf_version;
6996 default:
return false;
7000static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
7019 if (cond_val ==
nullptr) {
7023 uint32_t index = *cond_val / 0x20;
7039 GrfMsg(1,
"Unsupported in-game variable 0x{:02X}", param);
7060 size_t pos = file.
GetPos();
7066 GrfMsg(2,
"CfgApply: Ignoring (next sprite is real, unsupported)");
7069 file.
SeekTo(pos, SEEK_SET);
7075 std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
7078 if (preload_sprite.empty()) {
7079 preload_sprite.resize(num);
7080 file.
ReadBlock(preload_sprite.data(), num);
7084 file.
SeekTo(pos, SEEK_SET);
7095 param_num = buf.ReadByte();
7096 if (param_num == 0xFF)
break;
7100 param_size = buf.ReadByte();
7104 add_value =
HasBit(param_size, 7);
7105 param_size =
GB(param_size, 0, 7);
7108 offset = buf.ReadExtendedByte();
7112 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= std::size(_cur.
grffile->param)) {
7113 GrfMsg(2,
"CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
7117 GrfMsg(8,
"CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
7120 for (i = 0; i < param_size && offset + i < num; i++) {
7121 uint32_t value = GetParamVal(param_num + i / 4,
nullptr);
7124 if (i % 4 == 0) carry =
false;
7127 uint new_value = preload_sprite[offset + i] +
GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
7128 preload_sprite[offset + i] =
GB(new_value, 0, 8);
7130 carry = new_value >= 256;
7132 preload_sprite[offset + i] =
GB(value, (i % 4) * 8, 8);
7164 uint32_t cond_val = 0;
7168 uint8_t param = buf.ReadByte();
7169 uint8_t paramsize = buf.ReadByte();
7170 uint8_t condtype = buf.ReadByte();
7177 switch (paramsize) {
7178 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord();
break;
7179 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF;
break;
7180 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF;
break;
7181 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF;
break;
7185 if (param < 0x80 && std::size(_cur.
grffile->param) <= param) {
7186 GrfMsg(7,
"SkipIf: Param {} undefined, skipping test", param);
7190 GrfMsg(7,
"SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
7195 if (condtype >= 0x0B) {
7226 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
7228 }
else if (param == 0x88) {
7238 if (condtype != 10 && c ==
nullptr) {
7239 GrfMsg(7,
"SkipIf: GRFID 0x{:08X} unknown, skipping test", std::byteswap(cond_val));
7266 default: GrfMsg(1,
"SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype);
return;
7270 uint32_t param_val = GetParamVal(param, &cond_val);
7272 case 0x00: result = !!(param_val & (1 << cond_val));
7274 case 0x01: result = !(param_val & (1 << cond_val));
7276 case 0x02: result = (param_val & mask) == cond_val;
7278 case 0x03: result = (param_val & mask) != cond_val;
7280 case 0x04: result = (param_val & mask) < cond_val;
7282 case 0x05: result = (param_val & mask) > cond_val;
7284 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
7289 GrfMsg(2,
"SkipIf: Not skipping sprites, test was false");
7293 uint8_t numsprites = buf.ReadByte();
7300 for (
const auto &label : _cur.grffile->labels) {
7301 if (label.label != numsprites)
continue;
7304 if (choice ==
nullptr) choice = &label;
7306 if (label.nfo_line > _cur.
nfo_line) {
7312 if (choice !=
nullptr) {
7313 GrfMsg(2,
"SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
7319 GrfMsg(2,
"SkipIf: Skipping {} sprites, test was true", numsprites);
7338 uint8_t grf_version = buf.ReadByte();
7339 uint32_t grfid = buf.ReadDWord();
7340 std::string_view name = buf.ReadString();
7344 if (grf_version < 2 || grf_version > 8) {
7346 Debug(grf, 0,
"{}: NewGRF \"{}\" (GRFID {:08X}) uses GRF version {}, which is incompatible with this version of OpenTTD.", _cur.
grfconfig->
filename,
StrMakeValid(name), std::byteswap(grfid), grf_version);
7354 if (buf.HasData()) {
7355 std::string_view info = buf.ReadString();
7373 uint8_t version = buf.ReadByte();
7374 uint32_t grfid = buf.ReadDWord();
7375 std::string_view name = buf.ReadString();
7378 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7382 if (_cur.
grffile->grfid != grfid) {
7383 Debug(grf, 0,
"GRFInfo: GRFID {:08X} in FILESCAN stage does not match GRFID {:08X} in INIT/RESERVE/ACTIVATION stage", std::byteswap(_cur.
grffile->grfid), std::byteswap(grfid));
7387 _cur.
grffile->grf_version = version;
7402 for (
const auto &grm_sprite : _grm_sprites) {
7403 if (grm_sprite.first.grfid != _cur.
grffile->grfid)
continue;
7404 if (grm_sprite.second.first <= first_sprite && grm_sprite.second.first + grm_sprite.second.second >= first_sprite + num_sprites)
return true;
7420 uint8_t num_sets = buf.ReadByte();
7422 for (uint i = 0; i < num_sets; i++) {
7423 uint8_t num_sprites = buf.ReadByte();
7424 uint16_t first_sprite = buf.ReadWord();
7426 GrfMsg(2,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7427 i, num_sprites, first_sprite
7433 GrfMsg(0,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7442 for (uint j = 0; j < num_sprites; j++) {
7443 SpriteID load_index = first_sprite + j;
7449 if (
IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7459 uint8_t num_sets = buf.ReadByte();
7461 for (uint i = 0; i < num_sets; i++) {
7468 GrfMsg(3,
"SkipActA: Skipping {} sprites", _cur.
skip_sprites);
7490 STR_NEWGRF_ERROR_VERSION_NUMBER,
7491 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
7492 STR_NEWGRF_ERROR_UNSET_SWITCH,
7493 STR_NEWGRF_ERROR_INVALID_PARAMETER,
7494 STR_NEWGRF_ERROR_LOAD_BEFORE,
7495 STR_NEWGRF_ERROR_LOAD_AFTER,
7496 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
7500 STR_NEWGRF_ERROR_MSG_INFO,
7501 STR_NEWGRF_ERROR_MSG_WARNING,
7502 STR_NEWGRF_ERROR_MSG_ERROR,
7503 STR_NEWGRF_ERROR_MSG_FATAL
7506 uint8_t severity = buf.ReadByte();
7507 uint8_t lang = buf.ReadByte();
7508 uint8_t message_id = buf.ReadByte();
7511 if (!CheckGrfLangID(lang, _cur.
grffile->grf_version))
return;
7515 if (!
HasBit(severity, 7) && _cur.
stage == GLS_INIT) {
7516 GrfMsg(7,
"GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.
stage);
7521 if (severity >=
lengthof(sevstr)) {
7522 GrfMsg(7,
"GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7524 }
else if (severity == 3) {
7533 if (message_id >=
lengthof(msgstr) && message_id != 0xFF) {
7534 GrfMsg(7,
"GRFLoadError: Invalid message id.");
7538 if (buf.Remaining() <= 1) {
7539 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7549 if (message_id == 0xFF) {
7551 if (buf.HasData()) {
7552 std::string_view message = buf.ReadString();
7556 GrfMsg(7,
"GRFLoadError: No custom message supplied.");
7560 error->
message = msgstr[message_id];
7563 if (buf.HasData()) {
7564 std::string_view data = buf.ReadString();
7568 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7569 error->
data.clear();
7573 for (uint i = 0; i < error->
param_value.size() && buf.HasData(); i++) {
7574 uint param_number = buf.ReadByte();
7586 if (!buf.HasData())
return;
7588 std::string_view text = buf.ReadString();
7595 uint8_t target = buf.ReadByte();
7598 if (target < 0x80 || target == 0x9E)
return;
7612static uint32_t GetPatchVariable(uint8_t param)
7622 case 0x0F:
return 0;
7638 case 0x11:
return SPR_2CCMAP_BASE;
7652 uint8_t map_bits = 0;
7655 uint8_t max_edge = std::max(log_X, log_Y);
7657 if (log_X == log_Y) {
7660 if (max_edge == log_Y)
SetBit(map_bits, 1);
7663 return (map_bits << 24) | (std::min(log_X, log_Y) << 20) | (max_edge << 16) |
7664 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
7673 return SPR_SLOPES_BASE;
7684 GrfMsg(2,
"ParamSet: Unknown Patch variable 0x{:02X}.", param);
7690static uint32_t PerformGRM(std::span<uint32_t> grm, uint16_t count, uint8_t op, uint8_t target,
const char *type)
7703 for (uint i = start; i < std::size(grm); i++) {
7707 if (op == 2 || op == 3)
break;
7712 if (size == count)
break;
7715 if (size == count) {
7717 if (op == 0 || op == 3) {
7718 GrfMsg(2,
"ParamSet: GRM: Reserving {} {} at {}", count, type, start);
7719 for (uint i = 0; i < count; i++) grm[start + i] = _cur.
grffile->grfid;
7725 if (op != 4 && op != 5) {
7727 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7732 GrfMsg(1,
"ParamSet: GRM: Unable to allocate {} {}", count, type);
7762 uint8_t target = buf.ReadByte();
7763 uint8_t oper = buf.ReadByte();
7764 uint32_t src1 = buf.ReadByte();
7765 uint32_t src2 = buf.ReadByte();
7768 if (buf.Remaining() >= 4) data = buf.ReadDWord();
7777 if (target < 0x80 && target < std::size(_cur.
grffile->param)) {
7778 GrfMsg(7,
"ParamSet: Param {} already defined, skipping", target);
7782 oper =
GB(oper, 0, 7);
7786 if (
GB(data, 0, 8) == 0xFF) {
7787 if (data == 0x0000FFFF) {
7789 src1 = GetPatchVariable(src1);
7793 uint8_t feature =
GB(data, 8, 8);
7794 uint16_t count =
GB(data, 16, 16);
7796 if (_cur.
stage == GLS_RESERVE) {
7797 if (feature == 0x08) {
7801 if (_cur.
spriteid + count >= 16384) {
7802 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7808 GrfMsg(4,
"ParamSet: GRM: Allocated {} sprites at {}", count, _cur.
spriteid);
7815 }
else if (_cur.
stage == GLS_ACTIVATION) {
7844 GrfMsg(4,
"ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7852 GrfMsg(1,
"ParamSet: GRM: Unsupported operation {} for general sprites", op);
7859 src1 = PerformGRM(
_grm_cargoes, count, op, target,
"cargoes");
7863 default: GrfMsg(1,
"ParamSet: GRM: Unsupported feature 0x{:X}", feature);
return;
7880 }
else if (src1 == 0xFE) {
7892 src1 = (src1 == 0xFF) ? data : GetParamVal(src1,
nullptr);
7893 src2 = (src2 == 0xFF) ? data : GetParamVal(src2,
nullptr);
7915 res = (int32_t)src1 * (int32_t)src2;
7919 if ((int32_t)src2 < 0) {
7920 res = src1 >> -(int32_t)src2;
7922 res = src1 << (src2 & 0x1F);
7927 if ((int32_t)src2 < 0) {
7928 res = (int32_t)src1 >> -(int32_t)src2;
7930 res = (int32_t)src1 << (src2 & 0x1F);
7954 res = (int32_t)src1 / (int32_t)src2;
7970 res = (int32_t)src1 % (int32_t)src2;
7974 default: GrfMsg(0,
"ParamSet: Unknown operation {}, skipping", oper);
return;
8003 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
8014 uint32_t safe_bits = 0;
8015 SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
8024 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
8028 if (target < 0x80) {
8030 if (target >= std::size(_cur.
grffile->param)) _cur.
grffile->param.resize(target + 1);
8031 _cur.
grffile->param[target] = res;
8033 GrfMsg(7,
"ParamSet: Skipping unknown target 0x{:02X}", target);
8047 uint8_t num = buf.ReadByte();
8049 for (uint i = 0; i < num; i++) {
8050 uint32_t grfid = buf.ReadDWord();
8072 uint8_t num = buf.ReadByte();
8074 for (uint i = 0; i < num; i++) {
8075 uint32_t grfid = buf.ReadDWord();
8079 if (file !=
nullptr && file != _cur.
grfconfig) {
8080 GrfMsg(2,
"GRFInhibit: Deactivating file '{}'", file->
filename);
8097 uint32_t grfid = _cur.
grffile->grfid;
8101 uint8_t
id = buf.ReadByte();
8102 GrfMsg(6,
"FeatureTownName: definition 0x{:02X}",
id & 0x7F);
8107 bool new_scheme = _cur.
grffile->grf_version >= 7;
8109 uint8_t lang = buf.ReadByte();
8115 std::string_view name = buf.ReadString();
8118 GrfMsg(6,
"FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
8122 lang = buf.ReadByte();
8123 }
while (lang != 0);
8124 townname->
styles.emplace_back(style,
id);
8127 uint8_t parts = buf.ReadByte();
8128 GrfMsg(6,
"FeatureTownName: {} parts", parts);
8131 for (uint partnum = 0; partnum < parts; partnum++) {
8133 uint8_t texts = buf.ReadByte();
8134 partlist.
bitstart = buf.ReadByte();
8135 partlist.
bitcount = buf.ReadByte();
8137 GrfMsg(6,
"FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.
bitstart, partlist.
bitcount);
8139 partlist.
parts.reserve(texts);
8140 for (uint textnum = 0; textnum < texts; textnum++) {
8142 part.
prob = buf.ReadByte();
8145 uint8_t ref_id = buf.ReadByte();
8147 GrfMsg(0,
"FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
8148 DelGRFTownName(grfid);
8153 GrfMsg(6,
"FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.
prob & 0x7F);
8155 std::string_view text = buf.ReadString();
8157 GrfMsg(6,
"FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.
text, part.
prob);
8161 GrfMsg(6,
"FeatureTownName: part {}, total probability {}", partnum, partlist.
maxprob);
8173 uint8_t nfo_label = buf.ReadByte();
8177 GrfMsg(2,
"DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
8191 if (file ==
nullptr || file->sound_offset == 0) {
8192 GrfMsg(1,
"ImportGRFSound: Source file not available");
8196 if (sound_id >= file->num_sounds) {
8197 GrfMsg(1,
"ImportGRFSound: Sound effect {} is invalid", sound_id);
8201 GrfMsg(2,
"ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
8203 *sound = *GetSound(file->sound_offset + sound_id);
8206 sound->volume = SOUND_EFFECT_MAX_VOLUME;
8207 sound->priority = 0;
8218 sound->volume = SOUND_EFFECT_MAX_VOLUME;
8219 sound->priority = 0;
8221 if (offs != SIZE_MAX) {
8223 sound->file = _cur.
file;
8224 sound->file_offset = offs;
8225 sound->source = SoundSource::NewGRF;
8237 uint16_t num = buf.ReadWord();
8238 if (num == 0)
return;
8241 if (_cur.
grffile->sound_offset == 0) {
8242 _cur.
grffile->sound_offset = GetNumSounds();
8243 _cur.
grffile->num_sounds = num;
8246 sound = GetSound(_cur.
grffile->sound_offset);
8251 for (
int i = 0; i < num; i++) {
8256 bool invalid = i >= _cur.
grffile->num_sounds;
8258 size_t offs = file.
GetPos();
8263 if (grf_container_version >= 2 && type == 0xFD) {
8266 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
8268 }
else if (len != 4) {
8269 GrfMsg(1,
"GRFSound: Invalid sprite section import");
8279 GrfMsg(1,
"GRFSound: Unexpected RealSprite found, skipping");
8286 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
8294 if (_cur.
stage == GLS_INIT) {
8295 if (grf_container_version >= 2) {
8296 GrfMsg(1,
"GRFSound: Inline sounds are not supported for container version >= 2");
8305 if (_cur.
stage == GLS_ACTIVATION) {
8308 if (file.
ReadByte() != 0) GrfMsg(1,
"GRFSound: Import type mismatch");
8316 GrfMsg(1,
"GRFSound: Unexpected Action {:x} found, skipping", action);
8332 GrfMsg(3,
"SkipAct11: Skipping {} sprites", _cur.
skip_sprites);
8345 uint8_t num_def = buf.ReadByte();
8347 for (uint i = 0; i < num_def; i++) {
8349 uint8_t num_char = buf.ReadByte();
8350 uint16_t base_char = buf.ReadWord();
8352 if (size >= FS_END) {
8353 GrfMsg(1,
"LoadFontGlyph: Size {} is not supported, ignoring", size);
8356 GrfMsg(7,
"LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8358 for (uint c = 0; c < num_char; c++) {
8376 uint8_t num_def = buf.ReadByte();
8378 for (uint i = 0; i < num_def; i++) {
8389 GrfMsg(3,
"SkipAct12: Skipping {} sprites", _cur.
skip_sprites);
8402 uint32_t grfid = buf.ReadDWord();
8405 GrfMsg(7,
"TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13", std::byteswap(grfid));
8414 error->
data =
GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8424 uint8_t language = _cur.
grffile->grf_version >= 8 ? buf.ReadByte() : 0x7F;
8425 uint8_t num_strings = buf.ReadByte();
8426 uint16_t first_id = buf.ReadWord();
8428 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
8429 GrfMsg(7,
"TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
8433 for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8434 std::string_view
string = buf.ReadString();
8436 if (
string.empty()) {
8437 GrfMsg(7,
"TranslateGRFString: Ignoring empty string.");
8470 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8482 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8485 char data = buf.ReadByte();
8493 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8508 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8511 char data = buf.ReadByte();
8517 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8530 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8543 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8548 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8579 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8586 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8596 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8598 }
else if (len != 8) {
8599 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8602 uint32_t min_value = buf.ReadDWord();
8603 uint32_t max_value = buf.ReadDWord();
8604 if (min_value <= max_value) {
8608 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8617 if (len < 1 || len > 3) {
8618 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
8621 uint8_t param_nr = buf.ReadByte();
8622 if (param_nr >= GRFConfig::MAX_NUM_PARAMS) {
8623 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8639 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8661 using Span = std::pair<const AllowedSubtags *, const AllowedSubtags *>;
8664 std::variant<DataHandler, TextHandler, BranchHandler, Span>
handler;
8678 uint8_t type = buf.ReadByte();
8680 uint32_t
id = buf.ReadDWord();
8682 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8684 type = buf.ReadByte();
8688 uint8_t langid = buf.ReadByte();
8689 std::string_view name_string = buf.ReadString();
8697 type = buf.ReadByte();
8721 uint8_t type = buf.ReadByte();
8723 uint32_t
id = buf.ReadDWord();
8725 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8727 type = buf.ReadByte();
8740 type = buf.ReadByte();
8775 uint8_t new_type = buf.ReadByte();
8776 while (new_type != 0) {
8779 new_type = buf.ReadByte();
8790 uint16_t size = buf.ReadWord();
8813 struct type_visitor {
8814 char operator()(
const DataHandler &) {
return 'B'; }
8815 char operator()(
const TextHandler &) {
return 'T'; }
8821 struct evaluate_visitor {
8826 size_t len = buf.ReadWord();
8827 if (buf.Remaining() < len)
return false;
8828 return handler(len, buf);
8833 uint8_t langid = buf.ReadByte();
8834 return handler(langid, buf.ReadString());
8839 return handler(buf);
8844 return HandleNodes(buf, {subtags.first, subtags.second});
8848 for (
const auto &tag : subtags) {
8849 if (tag.id != std::byteswap(
id) || std::visit(type_visitor{}, tag.handler) != type)
continue;
8850 return std::visit(evaluate_visitor{buf}, tag.handler);
8853 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
8865 uint8_t type = buf.ReadByte();
8867 uint32_t
id = buf.ReadDWord();
8868 if (!
HandleNode(type,
id, buf, subtags))
return false;
8869 type = buf.ReadByte();
8990 file->stations.clear();
8998 file->housespec.clear();
9006 file->airportspec.clear();
9007 file->airtspec.clear();
9015 file->industryspec.clear();
9016 file->indtspec.clear();
9024 file->objectspec.clear();
9028static void ResetCustomRoadStops()
9031 file->roadstops.clear();
9060 CleanUpGRFTownNames();
9122 ResetCustomRoadStops();
9148 _grf_id_overrides.clear();
9150 InitializeSoundPool();
9180 if (!cs->IsValid())
continue;
9195 if (newfile !=
nullptr) {
9201 newfile =
new GRFFile(config);
9237 this->param = config.
param;
9248 CargoType cargo_type = GetCargoTypeByLabel(label);
9249 if (cargo_type != INVALID_CARGO)
return label;
9269 default: NOT_REACHED();
9274 return std::visit(visitor{}, label);
9282 CargoTypes original_known_cargoes = 0;
9290 bool only_defaultcargo;
9298 if (
_gted[engine].defaultcargo_grf ==
nullptr) {
9301 static constexpr LandscapeType T = LandscapeType::Temperate;
9305 static const struct DefaultRefitMasks {
9310 } _default_refit_masks[] = {
9332 switch (label.base()) {
9336 _gted[engine].cargo_disallowed = {};
9341 _gted[engine].cargo_disallowed = {};
9360 _gted[engine].cargo_disallowed = {};
9364 for (
const auto &drm : _default_refit_masks) {
9366 if (drm.cargo_label != label)
continue;
9368 _gted[engine].cargo_allowed = drm.cargo_allowed;
9369 _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9374 _gted[engine].ctt_exclude_mask = original_known_cargoes;
9377 _gted[engine].UpdateRefittability(
_gted[engine].cargo_allowed.Any());
9384 CargoTypes mask = 0;
9385 CargoTypes not_mask = 0;
9386 CargoTypes xor_mask = ei->refit_mask;
9392 if (
_gted[engine].cargo_allowed.Any()) {
9395 if (cs->classes.Any(
_gted[engine].cargo_allowed) && cs->classes.All(
_gted[engine].cargo_allowed_required))
SetBit(mask, cs->Index());
9396 if (cs->classes.Any(
_gted[engine].cargo_disallowed))
SetBit(not_mask, cs->Index());
9400 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) &
_cargo_mask;
9403 ei->refit_mask |=
_gted[engine].ctt_include_mask;
9404 ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
9408 if (file ==
nullptr) file = e->
GetGRF();
9411 uint8_t local_slot = file->
cargo_map[cs->Index()];
9417 case 1:
SetBit(ei->refit_mask, cs->Index());
break;
9418 case 2:
ClrBit(ei->refit_mask, cs->Index());
break;
9432 ei->cargo_type = INVALID_CARGO;
9440 if (file ==
nullptr) file = e->
GetGRF();
9441 if (file !=
nullptr && file->grf_version >= 8 && !file->
cargo_list.empty()) {
9443 uint8_t best_local_slot = UINT8_MAX;
9445 uint8_t local_slot = file->
cargo_map[cargo_type];
9446 if (local_slot < best_local_slot) {
9447 best_local_slot = local_slot;
9448 ei->cargo_type = cargo_type;
9478 for (uint i = 0; i < CF_END; i++) {
9490 if (e->
GetGRF() ==
nullptr) {
9491 auto found = std::ranges::find(_engine_mngr.mappings[e->
type], e->
index, &EngineIDMapping::engine);
9492 if (found == std::end(_engine_mngr.mappings[e->
type]) || found->grfid != INVALID_GRFID || found->internal_id != found->substitute_id) {
9493 e->info.
string_id = STR_NEWGRF_INVALID_ENGINE;
9498 if (e->info.
variant_id != EngineID::Invalid()) {
9532 default: NOT_REACHED();
9542 while (parent != EngineID::Invalid()) {
9544 if (parent != e->
index)
continue;
9549 GrfMsg(1,
"FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", e->
grf_prop.
local_id, e->
GetGRF()->filename);
9553 if (e->info.
variant_id != EngineID::Invalid()) {
9565 switch (cs.label.base()) {
9567 case CT_MAIL.base(): cs.town_production_effect =
TPE_MAIL;
break;
9568 default: cs.town_production_effect =
TPE_NONE;
break;
9571 if (!cs.IsValid()) {
9572 cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO;
9573 cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
9574 cs.abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
9598 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} as multitile, but no suitable tiles follow. Disabling house.", filename, hs->
grf_prop.
local_id);
9608 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);
9616 Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->
grf_prop.
local_id);
9623 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);
9646 if (min_year == 0)
return;
9673 if (file->housespec.empty())
continue;
9675 size_t num_houses = file->housespec.size();
9676 for (
size_t i = 0; i < num_houses; i++) {
9677 HouseSpec *hs = file->housespec[i].get();
9679 if (hs ==
nullptr)
continue;
9681 const HouseSpec *next1 = (i + 1 < num_houses ? file->housespec[i + 1].get() :
nullptr);
9682 const HouseSpec *next2 = (i + 2 < num_houses ? file->housespec[i + 2].get() :
nullptr);
9683 const HouseSpec *next3 = (i + 3 < num_houses ? file->housespec[i + 3].get() :
nullptr);
9742 for (
const auto &indsp : file->industryspec) {
9743 if (indsp ==
nullptr || !indsp->
enabled)
continue;
9748 for (
const auto &indtsp : file->indtspec) {
9749 if (indtsp !=
nullptr) {
9750 _industile_mngr.SetEntitySpec(indtsp.get());
9755 for (
auto &indsp : _industry_specs) {
9762 indsp.
name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9774 for (
auto &indtsp : _industry_tile_specs) {
9790 for (
auto &objectspec : file->objectspec) {
9791 if (objectspec !=
nullptr && objectspec->grf_prop.HasGrfFile() && objectspec->IsEnabled()) {
9808 for (
auto &as : file->airportspec) {
9809 if (as !=
nullptr && as->
enabled) {
9810 _airport_mngr.SetEntitySpec(as.get());
9814 for (
auto &ats : file->airtspec) {
9815 if (ats !=
nullptr && ats->enabled) {
9816 _airporttile_mngr.SetEntitySpec(ats.get());
9828static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9842 static const SpecialSpriteHandler handlers[][GLS_END] = {
9843 {
nullptr, SafeChangeInfo,
nullptr,
nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9844 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9845 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, NewSpriteGroup, },
9846 {
nullptr,
GRFUnsafe,
nullptr,
nullptr,
nullptr, FeatureMapSpriteGroup, },
9847 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, FeatureNewName, },
9848 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9849 {
nullptr,
nullptr,
nullptr, CfgApply, CfgApply, CfgApply, },
9850 {
nullptr,
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, },
9851 { ScanInfo,
nullptr,
nullptr, GRFInfo, GRFInfo, GRFInfo, },
9852 {
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, SkipIf, },
9853 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9854 {
nullptr,
nullptr,
nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9855 {
nullptr,
nullptr,
nullptr, GRFComment,
nullptr, GRFComment, },
9857 {
nullptr, SafeGRFInhibit,
nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9860 { SkipAct11,
GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9863 {
StaticGRFInfo,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, },
9868 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9869 if (it == _grf_line_to_action6_sprite_override.end()) {
9875 buf = _grf_line_to_action6_sprite_override[location].data();
9876 GrfMsg(7,
"DecodeSpecialSprite: Using preloaded pseudo sprite data");
9885 uint8_t action = br.ReadByte();
9887 if (action == 0xFF) {
9888 GrfMsg(2,
"DecodeSpecialSprite: Unexpected data block, skipping");
9889 }
else if (action == 0xFE) {
9890 GrfMsg(2,
"DecodeSpecialSprite: Unexpected import block, skipping");
9891 }
else if (action >=
lengthof(handlers)) {
9892 GrfMsg(7,
"DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
9893 }
else if (handlers[action][stage] ==
nullptr) {
9894 GrfMsg(7,
"DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
9896 GrfMsg(7,
"DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9897 handlers[action][stage](br);
9900 GrfMsg(1,
"DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9916 Debug(grf, 2,
"LoadNewGRFFile: Reading NewGRF-file '{}'", config.
filename);
9919 if (grf_container_version == 0) {
9920 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9924 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9930 if (grf_container_version >= 2) file.
ReadDword();
9933 if (grf_container_version >= 2) {
9935 uint8_t compression = file.
ReadByte();
9936 if (compression != 0) {
9937 Debug(grf, 7,
"LoadNewGRFFile: Unsupported compression format");
9946 if (num == 4 && file.
ReadByte() == 0xFF) {
9949 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9957 while ((num = (grf_container_version >= 2 ? file.
ReadDword() : file.
ReadWord())) != 0) {
9963 DecodeSpecialSprite(buf.
Allocate(num), num, stage);
9974 GrfMsg(0,
"LoadNewGRFFile: Unexpected sprite, disabling");
9975 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9979 if (grf_container_version >= 2 && type == 0xFD) {
10002 const std::string &filename = config.
filename;
10013 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
10015 if (_cur.
grffile ==
nullptr) UserError(
"File '{}' lost in cache.\n", filename);
10022 SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
10076 DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0);
10077 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
10078 DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2);
10079 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
10080 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
10081 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
10092 static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
10096 std::vector<int> grf_overrides(num_grfs, -1);
10097 for (
int i = 0; i < num_grfs; i++) {
10099 auto it = _grf_id_overrides.find(source->grfid);
10100 if (it == std::end(_grf_id_overrides))
continue;
10101 uint32_t
override = it->second;
10104 if (dest ==
nullptr)
continue;
10107 assert(grf_overrides[i] >= 0);
10111 for (
int i = 0; i < num_grfs; i++) {
10112 if (grf_overrides[i] < 0 || grf_overrides[i] >= i)
continue;
10120 for (
Price p = PR_BEGIN; p < PR_END; p++) {
10123 Debug(grf, 3,
"'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
10129 for (
int i = num_grfs - 1; i >= 0; i--) {
10130 if (grf_overrides[i] < 0 || grf_overrides[i] <= i)
continue;
10138 for (
Price p = PR_BEGIN; p < PR_END; p++) {
10141 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
10147 for (
int i = 0; i < num_grfs; i++) {
10148 if (grf_overrides[i] < 0)
continue;
10156 for (
Price p = PR_BEGIN; p < PR_END; p++) {
10157 if (!
HasBit(features, _price_base_specs[p].grf_feature))
continue;
10159 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
10167 if (file->grf_version >= 8)
continue;
10168 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
10169 for (
Price p = PR_BEGIN; p < PR_END; p++) {
10171 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
10174 price_base_multipliers[p] = price_base_multipliers[fallback_price];
10181 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
10182 for (
Price p = PR_BEGIN; p < PR_END; p++) {
10183 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
10185 price_base_multipliers[p] = 0;
10190 Debug(grf, 3,
"'{}' sets global price base multiplier {}", file->
filename, p);
10192 price_base_multipliers[p] = 0;
10194 Debug(grf, 3,
"'{}' sets local price base multiplier {}", file->
filename, p);
10201template <
typename T>
10204 for (
auto &spec : specs) {
10205 if (spec ==
nullptr)
continue;
10206 spec->badges.push_back(badge.
index);
10216 if (badge ==
nullptr)
continue;
10220 e->badges.push_back(badge->
index);
10224 AddBadgeToSpecs(file->stations, GSF_STATIONS, *badge);
10225 AddBadgeToSpecs(file->housespec, GSF_HOUSES, *badge);
10226 AddBadgeToSpecs(file->industryspec, GSF_INDUSTRIES, *badge);
10227 AddBadgeToSpecs(file->indtspec, GSF_INDUSTRYTILES, *badge);
10228 AddBadgeToSpecs(file->objectspec, GSF_OBJECTS, *badge);
10229 AddBadgeToSpecs(file->airportspec, GSF_AIRPORTS, *badge);
10230 AddBadgeToSpecs(file->airtspec, GSF_AIRPORTTILES, *badge);
10231 AddBadgeToSpecs(file->roadstops, GSF_ROADSTOPS, *badge);
10252 _grf_line_to_action6_sprite_override.clear();
10317 if (file ==
nullptr ||
_gted[e->
index].roadtramtype == 0) {
10326 if (
_gted[e->
index].roadtramtype < list->size())
10328 RoadTypeLabel rtl = (*list)[
_gted[e->
index].roadtramtype];
10357 _grm_sprites.clear();
10415 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10422 if (stage == GLS_RESERVE) {
10423 static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10424 { std::byteswap(0x44442202), std::byteswap(0x44440111) },
10425 { std::byteswap(0x6D620402), std::byteswap(0x6D620401) },
10426 { std::byteswap(0x4D656f20), std::byteswap(0x4D656F17) },
10428 for (
const auto &grf_override : default_grf_overrides) {
10434 uint num_non_static = 0;
10436 _cur.
stage = stage;
10443 Debug(grf, 0,
"NewGRF file is missing '{}'; disabling", c->
filename);
10452 Debug(grf, 0,
"'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->
filename);
10454 c->
error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10463 if (stage == GLS_RESERVE) {
10465 }
else if (stage == GLS_ACTIVATION) {
10470 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
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...
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
@ NUM_AIRPORTS_PER_GRF
Maximal number of airports per NewGRF.
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.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr enable_if_t< is_integral_v< T >, T > byteswap(T x) noexcept
Custom implementation of std::byteswap; remove once we build with C++23.
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 CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
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 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.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
std::span< const CargoLabel > GetClimateDependentCargoTranslationTable()
Get default climate-dependent cargo translation table for a NewGRF, used if the NewGRF does not provi...
bool IsDefaultCargo(CargoType cargo_type)
Test if a cargo is a default cargo type.
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 SetupCargoForClimate(LandscapeType l)
Set up the default cargo types for the given landscape type.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
CargoTypes _cargo_mask
Bitmask of cargo types available.
@ Bulk
Bulk cargo (Coal, Grain etc., Ores, Fruit)
@ Liquid
Liquids (Oil, Water, Rubber)
@ Armoured
Armoured cargo (Valuables, Gold, Diamonds)
@ Refrigerated
Refrigerated cargo (Food, Fruit)
@ Express
Express cargo (Goods, Food, Candy, but also possible for passengers)
@ PieceGoods
Piece goods (Livestock, Wood, Steel, Paper)
@ 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.
@ 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.
VariableGRFFileProps grf_prop
Sprite information.
BadgeID index
Index assigned to badge.
BadgeFlags flags
Display flags.
GrfSpecFeatures features
Bitmask of which features use this badge.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
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.
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.
struct RailTypeInfo::@24 strings
Strings associated with the rail type.
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 sort-of mixin that adds 'at(pos)' and 'operator[](pos)' implementations for 'ConvertibleThroughBase...
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.
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.
struct RoadTypeInfo::@27 strings
Strings associated with the 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,...)
Output 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.
@ RoadIsTram
Road vehicle is a tram/light rail vehicle.
@ Uses2CC
Vehicle uses two company colours.
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.
@ RAILVEH_SINGLEHEAD
indicates a "standalone" locomotive
@ RAILVEH_WAGON
simple wagon, not motorized
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
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.
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.
void SetSnowLine(std::unique_ptr< SnowLine > &&snow_line)
Set a variable snow line, as loaded from a newgrf file.
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...
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
@ CHECK_NOTHING
Always succeeds.
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.
LandscapeType
Landscape types.
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 bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
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.
static constexpr CargoType SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoType SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoType SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
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 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.
static ChangeInfoResult RoadVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for road vehicles.
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 std::array< uint32_t, NUM_CARGO *2 > _grm_cargoes
Contains the GRF ID of the owner of a cargo if it has been reserved.
std::span< const CargoLabel > GetCargoTranslationTable(const GRFFile &grffile)
Get the cargo translation table to use for the given GRF file.
static ChangeInfoResult LoadTranslationTable(uint first, uint last, ByteReader &buf, TGetTableFunc gettable, std::string_view name)
Load a cargo- or railtype-translation table.
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 constexpr AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
static bool ChangeGRFURL(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'URL_' to set the newgrf url.
static ChangeInfoResult AirportChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for airports.
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 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 first, uint last, int prop, ByteReader &buf)
Define properties for water features.
static ChangeInfoResult StationChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for stations.
static void SkipBadgeList(ByteReader &buf)
Skip a list of badges.
static ChangeInfoResult SoundEffectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for sound effects.
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 bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
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 std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
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 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 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 bool HandleNodes(ByteReader &buf, std::span< const AllowedSubtags > tags)
Handle the contents of a 'C' choice of an Action14.
static ReferenceThroughBaseContainer< std::vector< GRFTempEngineData > > _gted
Temporary engine data used during NewGRF loading.
static std::array< uint32_t, 256 > _grm_engines
Contains the GRF ID of the owner of a vehicle if it has been reserved.
static void ResetNewGRFErrors()
Clear all NewGRF errors.
uint8_t _misc_grf_features
Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E.
static void LoadNewGRFFileFromFile(GRFConfig &config, GrfLoadingStage stage, SpriteFile &file)
Load a particular NewGRF from a SpriteFile.
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.
StringID MapGRFStringID(uint32_t grfid, GRFStringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
static ChangeInfoResult AircraftVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for aircraft.
static ChangeInfoResult GlobalVarChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for global variables.
static void LoadGRFSound(size_t offs, SoundEntry *sound)
Load a sound from a file.
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.
static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for objects.
void LoadNewGRF(SpriteID load_index, uint num_baseset)
Load all the NewGRFs.
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig &c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
static void InitializeGRFSpecial()
Initialize the TTDPatch flags.
static constexpr AllowedSubtags _tags_root[]
Action14 root tags.
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 ChangeInfoResult CargoChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for cargoes.
static StringID TTDPStringIDToOTTDStringIDMapping(GRFStringID str)
Perform a mapping from TTDPatch's string IDs to OpenTTD's string IDs, but only for the ones we are aw...
static void FinaliseCanals()
Set to use the correct action0 properties for each canal feature.
static bool IsValidNewGRFImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular NewGRF vehicle.
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 CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for ships.
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 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 RailVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for rail vehicles.
static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader &buf)
Ignore a house property.
static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industries.
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 ChangeInfoResult RoadTypeChangeInfo(uint first, uint last, int prop, ByteReader &buf, RoadTramType rtt)
Define properties for roadtypes.
static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
static ChangeInfoResult IndustrytilesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industry tiles.
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 void InitNewGRFFile(const GRFConfig &config)
Prepare loading a NewGRF file with its config.
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 ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
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 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 RailTypeChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for railtypes.
void LoadNewGRFFile(GRFConfig &config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
Load a particular NewGRF.
static void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
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 bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, std::span< const AllowedSubtags > subtags)
Handle the nodes of an Action14.
static void ResetNewGRF()
Reset and clear all NewGRFs.
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
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 BridgeChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for bridges.
static void FinaliseBadges()
Finish up applying badges to things.
static std::vector< CachedCallback > _cached_callback_groups
Sorted list of cached callback result spritegroups.
static ChangeInfoResult TownHouseChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for houses.
static constexpr AllowedSubtags _tags_parameters[]
Action14 parameter tags.
@ 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.
@ 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.
@ GMB_TRAIN_WIDTH_32_PIXELS
Use 32 pixels per train vehicle in depot gui and vehicle details. Never set in the global variable;.
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.
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
void ApplyBadgeFeaturesToClassBadges()
Apply features from all badges to their badge classes.
void MarkBadgeSeen(BadgeID index, GrfSpecFeature feature)
Mark a badge a seen (used) by a feature.
void AppendCopyableBadgeList(std::vector< BadgeID > &dst, std::span< const BadgeID > src, GrfSpecFeature feature)
Append copyable badges from a list onto another.
Badge & GetOrCreateBadge(std::string_view label)
Register a badge label and return its global index.
Badge * GetBadgeByLabel(std::string_view label)
Get a badge by label if it exists.
void ResetBadges()
Reset badges to the default state.
Functions related to NewGRF badges.
Types related to NewGRF badges.
@ CustomRefit
Custom refit mask.
@ CBID_VEHICLE_CUSTOM_REFIT
Called to get custom engine refit mask.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
std::array< WaterFeature, CF_END > _water_feature
Table of canal 'feature' sprite groups.
Handling of NewGRF canals.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
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.
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....
static const uint TLR_MAX_VAR10
Maximum value for var 10.
GRFConfigList _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.
@ 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.
@ InitOnly
GRF file is processed up to GLS_INIT.
@ Reserved
GRF file passed GLS_RESERVE stage.
@ System
GRF file is an openttd-internal system grf.
@ Static
GRF file is used statically (can be used in any MP game)
@ Unsafe
GRF file is unsafe for static usage.
@ Invalid
GRF is unusable with this version of OpenTTD.
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.
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.
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()
Determine 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,...
@ Uses2CC
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 GetGRFStringID(uint32_t grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
StringID AddGRFString(uint32_t grfid, GRFStringID 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.
Header of Action 04 "universal holder" structure and functions.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
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.
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.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
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 constexpr SpriteID SPR_OVERLAY_ROCKS_BASE
Overlay rocks sprites.
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 formatting but no parameters.
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.
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
std::vector< std::vector< PalSpriteID > > sprite_table
table of sprites for drawing the bridge
TimerGameCalendar::Year avail_year
the year where it becomes available
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.
CanalCallbackMasks 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 type.
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.
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.
CargoCallbackMasks callback_mask
Bitmask of cargo callbacks that have to be called.
uint16_t town_production_multiplier
Town production multiplier, 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.
Ground palette sprite of a tile, together with its sprite layout.
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.
LandscapeTypes climates
Climates supported by the engine.
EngineMiscFlags misc_flags
Miscellaneous flags.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
StringID string_id
Default name of engine.
VehicleCallbackMasks callback_mask
Bitmask of vehicle callbacks that have to be called.
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
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.
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.
VariableGRFFileProps grf_prop
Properties related the the grf file.
void SetSpriteGroup(size_t index, const struct SpriteGroup *spritegroup)
Set the SpriteGroup at the specified index.
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.
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)
GRFStatus status
NOSAVE: GRFStatus, enum.
std::optional< GRFError > error
NOSAVE: Error/Warning during GRF loading (Action 0x0B)
GRFConfigFlags flags
NOSAVE: GCF_Flags, bitset.
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.
const struct GRFFile * grffile
grf file that introduced this entity
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
void SetGRFFile(const struct GRFFile *grffile)
Set the NewGRF file, and its grfid, associated with grf props.
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
Dynamic data of a loaded NewGRF.
std::array< CanalProperties, CF_END > canal_local_properties
Canal properties as set by this NewGRF.
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoType -> local ID)
std::vector< RailTypeLabel > railtype_list
Railtype translation table.
uint32_t GetParam(uint number) const
Get GRF Parameter with range checking.
GRFFile(const struct GRFConfig &config)
Constructor for GRFFile.
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
uint32_t grf_features
Bitset of GrfSpecFeature the grf uses.
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.
std::vector< BadgeID > badge_list
Badge translation table (local index -> global index)
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.
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.
std::vector< ValueName > value_names
Names for each value.
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
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...
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.
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.
LandscapeType 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)
CargoType 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.
std::array< uint16_t, INDUSTRY_NUM_OUTPUTS > add_output
Add this much output cargo when successful (unsigned, is indirect in cb version 1+)
std::array< CargoType, INDUSTRY_NUM_OUTPUTS > cargo_output
Which output cargoes to add to (only cb version 2)
std::array< CargoType, INDUSTRY_NUM_INPUTS > cargo_input
Which input cargoes to take from (only cb version 2)
std::array< int16_t, INDUSTRY_NUM_INPUTS > subtract_input
Take this much of the input cargo (can be negative, is indirect in cb version 1+)
uint8_t num_input
How many subtract_input values are valid.
uint8_t version
Production callback version used, or 0xFF if marked invalid.
uint8_t num_output
How many add_output values are valid.
Defines the data structure for constructing industry.
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
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
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.
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.
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
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 AllocateRegisters()
Allocate memory for register modifiers.
Allow incrementing of ObjectClassID variables.
static void BindToClasses()
Tie all ObjectSpecs to their class.
FixedGRFFileProps< 2 > grf_prop
Properties related the the grf file.
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 Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static size_t GetPoolSize()
Returns first unused index.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
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)
VariableGRFFileProps 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
VariableGRFFileProps grf_prop
Properties related the the grf file.
std::unordered_map< uint16_t, std::vector< uint8_t > > layouts
Custom platform layouts, keyed by platform and length combined.
std::vector< NewGRFSpriteLayout > renderdata
Number of tile layouts.
@ NoWires
Tile should NOT contain catenary wires.
@ Pylons
Tile should contain catenary pylons.
@ Blocked
Tile is blocked to vehicles.
Information for mapping static StringIDs.
uint32_t grfid
Source NewGRF.
std::function< void(StringID)> func
Function for mapping result.
GRFStringID source
Source grf-local GRFStringID.
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.
void SetSpriteGroup(size_t index, const struct SpriteGroup *spritegroup)
Set the SpriteGroup at the specified index.
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
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.