diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 8c4b5b8a1d..f455904506 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -11,6 +11,7 @@ #include "core/container_func.hpp" #include "debug.h" #include "newgrf_railtype.h" +#include "newgrf_roadtype.h" #include "timer/timer_game_calendar.h" #include "depot_base.h" #include "town.h" @@ -33,6 +34,12 @@ case 0x42: return 0; case 0x43: return TimerGameCalendar::date.base(); case 0x44: return HZB_TOWN_EDGE; + case 0x45: { + auto rt = GetRailTypeInfoIndex(this->rti); + uint8_t local = GetReverseRailTypeTranslation(rt, this->ro.grffile); + if (local == 0xFF) local = 0xFE; + return 0xFFFF | local << 16; + } } } @@ -52,6 +59,8 @@ } return t != nullptr ? GetTownRadiusGroup(t, this->tile) : HZB_TOWN_EDGE; } + case 0x45: + return GetTrackTypes(this->tile, ro.grffile); } Debug(grf, 1, "Unhandled rail type tile variable 0x{:X}", variable); diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index a4ffa8f948..4498cc0507 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -11,6 +11,7 @@ #include "core/container_func.hpp" #include "debug.h" #include "newgrf_roadtype.h" +#include "newgrf_railtype.h" #include "timer/timer_game_calendar.h" #include "depot_base.h" #include "town.h" @@ -18,6 +19,40 @@ #include "safeguards.h" +/** + * Variable 0x45 of road-/tram-/rail-types to query track types on a tile. + * + * Format: __RRttrr + * - rr: Translated roadtype. + * - tt: Translated tramtype. + * - RR: Translated railtype. + * + * Special values for rr, tt, RR: + * - 0xFF: Track not present on tile. + * - 0xFE: Track present, but no matching entry in translation table. + */ +uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile) +{ + uint8_t road = 0xFF; + uint8_t tram = 0xFF; + if (MayHaveRoad(tile)) { + if (auto tt = GetRoadTypeRoad(tile); tt != INVALID_ROADTYPE) { + road = GetReverseRoadTypeTranslation(tt, grffile); + if (road == 0xFF) road = 0xFE; + } + if (auto tt = GetRoadTypeTram(tile); tt != INVALID_ROADTYPE) { + tram = GetReverseRoadTypeTranslation(tt, grffile); + if (tram == 0xFF) tram = 0xFE; + } + } + uint8_t rail = 0xFF; + if (auto tt = GetTileRailType(tile); tt != INVALID_RAILTYPE) { + rail = GetReverseRailTypeTranslation(tt, grffile); + if (rail == 0xFF) rail = 0xFE; + } + return road | tram << 8 | rail << 16; +} + /* virtual */ uint32_t RoadTypeScopeResolver::GetRandomBits() const { uint tmp = CountBits(this->tile.base() + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE); @@ -33,6 +68,16 @@ case 0x42: return 0; case 0x43: return TimerGameCalendar::date.base(); case 0x44: return HZB_TOWN_EDGE; + case 0x45: { + auto rt = GetRoadTypeInfoIndex(this->rti); + uint8_t local = GetReverseRoadTypeTranslation(rt, this->ro.grffile); + if (local == 0xFF) local = 0xFE; + if (RoadTypeIsRoad(rt)) { + return 0xFFFF00 | local; + } else { + return 0xFF00FF | local << 8; + } + } } } @@ -52,6 +97,8 @@ } return t != nullptr ? GetTownRadiusGroup(t, this->tile) : HZB_TOWN_EDGE; } + case 0x45: + return GetTrackTypes(this->tile, ro.grffile); } Debug(grf, 1, "Unhandled road type tile variable 0x{:X}", variable); diff --git a/src/newgrf_roadtype.h b/src/newgrf_roadtype.h index 3fef3bd112..e0fc039856 100644 --- a/src/newgrf_roadtype.h +++ b/src/newgrf_roadtype.h @@ -59,6 +59,8 @@ SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSp RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8_t tracktype, const GRFFile *grffile); uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile); +uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile); + void ConvertRoadTypes(); void SetCurrentRoadTypeLabelList(); void ClearRoadTypeLabelList(); diff --git a/src/rail.h b/src/rail.h index 5b896f8e9f..323dd00c24 100644 --- a/src/rail.h +++ b/src/rail.h @@ -304,6 +304,19 @@ inline const RailTypeInfo *GetRailTypeInfo(RailType railtype) return &_railtypes[railtype]; } +/** + * Returns the railtype for a Railtype information. + * @param rti Pointer to static RailTypeInfo + * @return Railtype in static railtype definitions + */ +inline RailType GetRailTypeInfoIndex(const RailTypeInfo *rti) +{ + extern RailTypeInfo _railtypes[RAILTYPE_END]; + size_t index = rti - _railtypes; + assert(index < RAILTYPE_END && rti == _railtypes + index); + return static_cast(index); +} + /** * Checks if an engine of the given RailType can drive on a tile with a given * RailType. This would normally just be an equality check, but for electric diff --git a/src/road.h b/src/road.h index 07da18d97e..68c1aefdcf 100644 --- a/src/road.h +++ b/src/road.h @@ -234,6 +234,19 @@ inline const RoadTypeInfo *GetRoadTypeInfo(RoadType roadtype) return &_roadtypes[roadtype]; } +/** + * Returns the railtype for a Railtype information. + * @param rti Pointer to static RailTypeInfo + * @return Railtype in static railtype definitions + */ +inline RoadType GetRoadTypeInfoIndex(const RoadTypeInfo *rti) +{ + extern RoadTypeInfo _roadtypes[ROADTYPE_END]; + size_t index = rti - _roadtypes; + assert(index < ROADTYPE_END && rti == _roadtypes + index); + return static_cast(index); +} + /** * Checks if an engine of the given RoadType got power on a tile with a given * RoadType. This would normally just be an equality check, but for electrified diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index b083758506..0d0da8254a 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -451,6 +451,7 @@ static const NIVariable _niv_railtypes[] = { NIV(0x42, "level crossing status"), NIV(0x43, "construction date"), NIV(0x44, "town zone"), + NIV(0x45, "track types"), }; class NIHRailType : public NIHelper { @@ -620,6 +621,7 @@ static const NIVariable _niv_roadtypes[] = { NIV(0x42, "level crossing status"), NIV(0x43, "construction date"), NIV(0x44, "town zone"), + NIV(0x45, "track types"), }; template