From 74a275f37ba5e66f593791a81ddf6d9d5f07d267 Mon Sep 17 00:00:00 2001 From: frosch Date: Sat, 3 May 2025 17:50:20 +0200 Subject: [PATCH] Add: [NewGRF] Add purchase list Action3 CID for houses, industries, industry tiles, airports and airport tiles. (#14121) --- src/newgrf/newgrf_act3.cpp | 160 ++++++++++++++++++++++------------- src/newgrf_airport.cpp | 2 +- src/newgrf_airporttiles.cpp | 2 +- src/newgrf_commons.h | 13 +-- src/newgrf_house.cpp | 2 +- src/newgrf_industries.cpp | 2 +- src/newgrf_industrytiles.cpp | 2 +- 7 files changed, 106 insertions(+), 77 deletions(-) diff --git a/src/newgrf/newgrf_act3.cpp b/src/newgrf/newgrf_act3.cpp index 2a405ac838..0ba810cc37 100644 --- a/src/newgrf/newgrf_act3.cpp +++ b/src/newgrf/newgrf_act3.cpp @@ -251,23 +251,31 @@ static void TownHouseMapSpriteGroup(ByteReader &buf, uint8_t idcount) houses.push_back(buf.ReadExtendedByte()); } - /* Skip the cargo type section, we only care about the default group */ - uint8_t cidcount = buf.ReadByte(); - buf.Skip(cidcount * 3); + auto set_sprite_group = [&houses](StandardSpriteGroup key, uint16_t groupid) { + if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return; - uint16_t groupid = buf.ReadWord(); - if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return; + for (auto &house : houses) { + HouseSpec *hs = house >= _cur_gps.grffile->housespec.size() ? nullptr : _cur_gps.grffile->housespec[house].get(); + if (hs == nullptr) { + GrfMsg(1, "TownHouseMapSpriteGroup: House {} undefined, skipping.", house); + continue; + } - for (auto &house : houses) { - HouseSpec *hs = house >= _cur_gps.grffile->housespec.size() ? nullptr : _cur_gps.grffile->housespec[house].get(); - - if (hs == nullptr) { - GrfMsg(1, "TownHouseMapSpriteGroup: House {} undefined, skipping.", house); - continue; + hs->grf_prop.SetSpriteGroup(key, _cur_gps.spritegroups[groupid]); } + }; - hs->grf_prop.SetSpriteGroup(_cur_gps.spritegroups[groupid]); + uint8_t cidcount = buf.ReadByte(); + for (uint c = 0; c < cidcount; c++) { + uint8_t ctype = buf.ReadByte(); + uint16_t groupid = buf.ReadWord(); + if (ctype == 0xFF) { + set_sprite_group(StandardSpriteGroup::Purchase, groupid); + } else { + GrfMsg(1, "TownHouseMapSpriteGroup: Invalid cargo bitnum {} for houses, skipping.", ctype); + } } + set_sprite_group(StandardSpriteGroup::Default, buf.ReadWord()); } static void IndustryMapSpriteGroup(ByteReader &buf, uint8_t idcount) @@ -283,23 +291,31 @@ static void IndustryMapSpriteGroup(ByteReader &buf, uint8_t idcount) industries.push_back(buf.ReadExtendedByte()); } - /* Skip the cargo type section, we only care about the default group */ - uint8_t cidcount = buf.ReadByte(); - buf.Skip(cidcount * 3); + auto set_sprite_group = [&industries](StandardSpriteGroup key, uint16_t groupid) { + if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return; - uint16_t groupid = buf.ReadWord(); - if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return; + for (auto &industry : industries) { + IndustrySpec *indsp = industry >= _cur_gps.grffile->industryspec.size() ? nullptr : _cur_gps.grffile->industryspec[industry].get(); + if (indsp == nullptr) { + GrfMsg(1, "IndustryMapSpriteGroup: Industry {} undefined, skipping", industry); + continue; + } - for (auto &industry : industries) { - IndustrySpec *indsp = industry >= _cur_gps.grffile->industryspec.size() ? nullptr : _cur_gps.grffile->industryspec[industry].get(); - - if (indsp == nullptr) { - GrfMsg(1, "IndustryMapSpriteGroup: Industry {} undefined, skipping", industry); - continue; + indsp->grf_prop.SetSpriteGroup(key, _cur_gps.spritegroups[groupid]); } + }; - indsp->grf_prop.SetSpriteGroup(_cur_gps.spritegroups[groupid]); + uint8_t cidcount = buf.ReadByte(); + for (uint c = 0; c < cidcount; c++) { + uint8_t ctype = buf.ReadByte(); + uint16_t groupid = buf.ReadWord(); + if (ctype == 0xFF) { + set_sprite_group(StandardSpriteGroup::Purchase, groupid); + } else { + GrfMsg(1, "IndustryMapSpriteGroup: Invalid cargo bitnum {} for industries, skipping.", ctype); + } } + set_sprite_group(StandardSpriteGroup::Default, buf.ReadWord()); } static void IndustrytileMapSpriteGroup(ByteReader &buf, uint8_t idcount) @@ -315,23 +331,31 @@ static void IndustrytileMapSpriteGroup(ByteReader &buf, uint8_t idcount) indtiles.push_back(buf.ReadExtendedByte()); } - /* Skip the cargo type section, we only care about the default group */ - uint8_t cidcount = buf.ReadByte(); - buf.Skip(cidcount * 3); + auto set_sprite_group = [&indtiles](StandardSpriteGroup key, uint16_t groupid) { + if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return; - uint16_t groupid = buf.ReadWord(); - if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return; + for (auto &indtile : indtiles) { + IndustryTileSpec *indtsp = indtile >= _cur_gps.grffile->indtspec.size() ? nullptr : _cur_gps.grffile->indtspec[indtile].get(); + if (indtsp == nullptr) { + GrfMsg(1, "IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile); + continue; + } - for (auto &indtile : indtiles) { - IndustryTileSpec *indtsp = indtile >= _cur_gps.grffile->indtspec.size() ? nullptr : _cur_gps.grffile->indtspec[indtile].get(); - - if (indtsp == nullptr) { - GrfMsg(1, "IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile); - continue; + indtsp->grf_prop.SetSpriteGroup(key, _cur_gps.spritegroups[groupid]); } + }; - indtsp->grf_prop.SetSpriteGroup(_cur_gps.spritegroups[groupid]); + uint8_t cidcount = buf.ReadByte(); + for (uint c = 0; c < cidcount; c++) { + uint8_t ctype = buf.ReadByte(); + uint16_t groupid = buf.ReadWord(); + if (ctype == 0xFF) { + set_sprite_group(StandardSpriteGroup::Purchase, groupid); + } else { + GrfMsg(1, "IndustrytileMapSpriteGroup: Invalid cargo bitnum {} for industry tiles, skipping.", ctype); + } } + set_sprite_group(StandardSpriteGroup::Default, buf.ReadWord()); } static void CargoMapSpriteGroup(ByteReader &buf, uint8_t idcount) @@ -499,23 +523,31 @@ static void AirportMapSpriteGroup(ByteReader &buf, uint8_t idcount) airports.push_back(buf.ReadExtendedByte()); } - /* Skip the cargo type section, we only care about the default group */ - uint8_t cidcount = buf.ReadByte(); - buf.Skip(cidcount * 3); + auto set_sprite_group = [&airports](StandardSpriteGroup key, uint16_t groupid) { + if (!IsValidGroupID(groupid, "AirportMapSpriteGroup")) return; - uint16_t groupid = buf.ReadWord(); - if (!IsValidGroupID(groupid, "AirportMapSpriteGroup")) return; + for (auto &airport : airports) { + AirportSpec *as = airport >= _cur_gps.grffile->airportspec.size() ? nullptr : _cur_gps.grffile->airportspec[airport].get(); + if (as == nullptr) { + GrfMsg(1, "AirportMapSpriteGroup: Airport {} undefined, skipping", airport); + continue; + } - for (auto &airport : airports) { - AirportSpec *as = airport >= _cur_gps.grffile->airportspec.size() ? nullptr : _cur_gps.grffile->airportspec[airport].get(); - - if (as == nullptr) { - GrfMsg(1, "AirportMapSpriteGroup: Airport {} undefined, skipping", airport); - continue; + as->grf_prop.SetSpriteGroup(key, _cur_gps.spritegroups[groupid]); } + }; - as->grf_prop.SetSpriteGroup(_cur_gps.spritegroups[groupid]); + uint8_t cidcount = buf.ReadByte(); + for (uint c = 0; c < cidcount; c++) { + uint8_t ctype = buf.ReadByte(); + uint16_t groupid = buf.ReadWord(); + if (ctype == 0xFF) { + set_sprite_group(StandardSpriteGroup::Purchase, groupid); + } else { + GrfMsg(1, "AirportMapSpriteGroup: Invalid cargo bitnum {} for airports, skipping.", ctype); + } } + set_sprite_group(StandardSpriteGroup::Default, buf.ReadWord()); } static void AirportTileMapSpriteGroup(ByteReader &buf, uint8_t idcount) @@ -531,23 +563,31 @@ static void AirportTileMapSpriteGroup(ByteReader &buf, uint8_t idcount) airptiles.push_back(buf.ReadExtendedByte()); } - /* Skip the cargo type section, we only care about the default group */ - uint8_t cidcount = buf.ReadByte(); - buf.Skip(cidcount * 3); + auto set_sprite_group = [&airptiles](StandardSpriteGroup key, uint16_t groupid) { + if (!IsValidGroupID(groupid, "AirportTileMapSpriteGroup")) return; - uint16_t groupid = buf.ReadWord(); - if (!IsValidGroupID(groupid, "AirportTileMapSpriteGroup")) return; + for (auto &airptile : airptiles) { + AirportTileSpec *airtsp = airptile >= _cur_gps.grffile->airtspec.size() ? nullptr : _cur_gps.grffile->airtspec[airptile].get(); + if (airtsp == nullptr) { + GrfMsg(1, "AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile); + continue; + } - for (auto &airptile : airptiles) { - AirportTileSpec *airtsp = airptile >= _cur_gps.grffile->airtspec.size() ? nullptr : _cur_gps.grffile->airtspec[airptile].get(); - - if (airtsp == nullptr) { - GrfMsg(1, "AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile); - continue; + airtsp->grf_prop.SetSpriteGroup(key, _cur_gps.spritegroups[groupid]); } + }; - airtsp->grf_prop.SetSpriteGroup(_cur_gps.spritegroups[groupid]); + uint8_t cidcount = buf.ReadByte(); + for (uint c = 0; c < cidcount; c++) { + uint8_t ctype = buf.ReadByte(); + uint16_t groupid = buf.ReadWord(); + if (ctype == 0xFF) { + set_sprite_group(StandardSpriteGroup::Purchase, groupid); + } else { + GrfMsg(1, "AirportTileMapSpriteGroup: Invalid cargo bitnum {} for airport tiles, skipping.", ctype); + } } + set_sprite_group(StandardSpriteGroup::Default, buf.ReadWord()); } static void RoadStopMapSpriteGroup(ByteReader &buf, uint8_t idcount) diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index b716bf029b..18d6984f27 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -252,7 +252,7 @@ AirportResolverObject::AirportResolverObject(TileIndex tile, Station *st, const CallbackID callback, uint32_t param1, uint32_t param2) : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, spec, layout) { - this->root_spritegroup = spec->grf_prop.GetSpriteGroup(); + this->root_spritegroup = spec->grf_prop.GetSpriteGroup(st != nullptr); } SpriteID GetCustomAirportSprite(const AirportSpec *as, uint8_t layout) diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index 2fe3cfe1bc..9872675e54 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -222,7 +222,7 @@ AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats, tiles_scope(*this, ats, tile, st), airport_scope(*this, tile, st, st != nullptr ? AirportSpec::Get(st->airport.type) : nullptr, st != nullptr ? st->airport.layout : 0) { - this->root_spritegroup = ats->grf_prop.GetSpriteGroup(); + this->root_spritegroup = ats->grf_prop.GetSpriteGroup(st != nullptr); } GrfSpecFeature AirportTileResolverObject::GetFeature() const diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index c53d064fff..8272f22583 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -342,17 +342,6 @@ struct FixedGRFFileProps : GRFFilePropsBase { void SetSpriteGroup(Tkey index, const struct SpriteGroup *spritegroup) { this->spritegroups[static_cast(index)] = spritegroup; } }; -/** - * Entities with single sprite group. - */ -struct SingleGRFFileProps : GRFFilePropsBase { - const struct SpriteGroup *spritegroup; - - bool HasSpriteGroups() const { return this->spritegroup != nullptr; } - const struct SpriteGroup *GetSpriteGroup() const { return this->spritegroup; } - void SetSpriteGroup(const struct SpriteGroup *spritegroup) { this->spritegroup = spritegroup; } -}; - /** * Standard sprite groups. */ @@ -450,7 +439,7 @@ struct CargoGRFFileProps : VariableGRFFileProps { /** * NewGRF entities which can replace default entities. */ -struct SubstituteGRFFileProps : SingleGRFFileProps { +struct SubstituteGRFFileProps : StandardGRFFileProps { /** Set all default data constructor for the props. */ constexpr SubstituteGRFFileProps(uint16_t subst_id = 0) : subst_id(subst_id), override_id(subst_id) {} diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index 6ad8c0f3ad..06c2df614a 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -114,7 +114,7 @@ HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town /* Tile must be valid and a house tile, unless not yet constructed in which case it may also be INVALID_TILE. */ assert((IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE))) || (not_yet_constructed && tile == INVALID_TILE)); - this->root_spritegroup = HouseSpec::Get(house_id)->grf_prop.GetSpriteGroup(); + this->root_spritegroup = HouseSpec::Get(house_id)->grf_prop.GetSpriteGroup(!not_yet_constructed); } GrfSpecFeature HouseResolverObject::GetFeature() const diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 3386af5ee6..61b3e65e6f 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -481,7 +481,7 @@ IndustriesResolverObject::IndustriesResolverObject(TileIndex tile, Industry *ind : ResolverObject(GetGrffile(type), callback, callback_param1, callback_param2), industries_scope(*this, tile, indus, type, random_bits) { - this->root_spritegroup = GetIndustrySpec(type)->grf_prop.GetSpriteGroup(); + this->root_spritegroup = GetIndustrySpec(type)->grf_prop.GetSpriteGroup(indus != nullptr && indus->index != IndustryID::Invalid()); } /** diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index c631080cc4..eaa4afbde7 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -145,7 +145,7 @@ IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileInde ind_scope(*this, tile, indus, indus->type), gfx(gfx) { - this->root_spritegroup = GetIndustryTileSpec(gfx)->grf_prop.GetSpriteGroup(); + this->root_spritegroup = GetIndustryTileSpec(gfx)->grf_prop.GetSpriteGroup(indus->index != IndustryID::Invalid()); } GrfSpecFeature IndustryTileResolverObject::GetFeature() const