From 868d84bbfc8d2c1471ef713854dd05ebc872615a Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 10 Jan 2021 14:37:40 +0100 Subject: [PATCH] Add: [NewGRF] vehicle variable 63 to test the tracktype of the current tile against a given tracktype. --- src/newgrf_engine.cpp | 30 ++++++++++++++++++++++++++++++ src/newgrf_railtype.cpp | 22 ++++++++++++++++++++++ src/newgrf_railtype.h | 1 + src/newgrf_roadtype.cpp | 31 +++++++++++++++++++++++++++++++ src/newgrf_roadtype.h | 1 + src/table/newgrf_debug_data.h | 3 ++- 6 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 8066ea4324..e3dc059ff5 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -702,6 +702,36 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, return ret; } + case 0x63: + /* Tile compatibility wrt. arbitrary track-type + * Format: + * bit 0: Type 'parameter' is known. + * bit 1: Engines with type 'parameter' are compatible with this tile. + * bit 2: Engines with type 'parameter' are powered on this tile. + * bit 3: This tile has type 'parameter' or it is considered equivalent (alternate labels). + */ + switch (v->type) { + case VEH_TRAIN: { + RailType param_type = GetRailTypeTranslation(parameter, object->ro.grffile); + if (param_type == INVALID_RAILTYPE) return 0x00; + RailType tile_type = GetTileRailType(v->tile); + if (tile_type == param_type) return 0x0F; + return (HasPowerOnRail(param_type, tile_type) ? 0x04 : 0x00) | + (IsCompatibleRail(param_type, tile_type) ? 0x02 : 0x00) | + 0x01; + } + case VEH_ROAD: { + RoadTramType rtt = GetRoadTramType(RoadVehicle::From(v)->roadtype); + RoadType param_type = GetRoadTypeTranslation(rtt, parameter, object->ro.grffile); + if (param_type == INVALID_ROADTYPE) return 0x00; + RoadType tile_type = GetRoadType(v->tile, rtt); + if (tile_type == param_type) return 0x0F; + return (HasPowerOnRoad(param_type, tile_type) ? 0x06 : 0x00) | + 0x01; + } + default: return 0x00; + } + case 0xFE: case 0xFF: { uint16 modflags = 0; diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 2a98948e7b..326ee80baf 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -138,6 +138,28 @@ SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalTy return group->GetResult(); } +/** + * Translate an index to the GRF-local railtype-translation table into a RailType. + * @param railtype Index into GRF-local translation table. + * @param grffile Originating GRF file. + * @return RailType or INVALID_RAILTYPE if the railtype is unknown. + */ +RailType GetRailTypeTranslation(uint8 railtype, const GRFFile *grffile) +{ + if (grffile == nullptr || grffile->railtype_list.size() == 0) { + /* No railtype table present. Return railtype as-is (if valid), so it works for original railtypes. */ + if (railtype >= RAILTYPE_END || GetRailTypeInfo(static_cast(railtype))->label == 0) return INVALID_RAILTYPE; + + return static_cast(railtype); + } else { + /* Railtype table present, but invalid index, return invalid type. */ + if (railtype >= grffile->railtype_list.size()) return INVALID_RAILTYPE; + + /* Look up railtype including alternate labels. */ + return GetRailTypeByLabel(grffile->railtype_list[railtype]); + } +} + /** * Perform a reverse railtype lookup to get the GRF internal ID. * @param railtype The global (OpenTTD) railtype. diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index 1e0ff01d82..c382117385 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -58,6 +58,7 @@ struct RailTypeResolverObject : public ResolverObject { SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL, uint *num_results = nullptr); SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui = false); +RailType GetRailTypeTranslation(uint8 railtype, const GRFFile *grffile); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); #endif /* NEWGRF_RAILTYPE_H */ diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 3f6150cd36..025d03bb6a 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -132,6 +132,37 @@ SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSp return group->GetResult(); } +/** + * Translate an index to the GRF-local road/tramtype-translation table into a RoadType. + * @param rtt Whether to index the road- or tramtype-table. + * @param tracktype Index into GRF-local translation table. + * @param grffile Originating GRF file. + * @return RoadType or INVALID_ROADTYPE if the roadtype is unknown. + */ +RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8 tracktype, const GRFFile *grffile) +{ + /* Because OpenTTD mixes RoadTypes and TramTypes into the same type, + * the mapping of the original road- and tramtypes does not match the default GRF-local mapping. + * So, this function cannot provide any similar behavior to GetCargoTranslation() and GetRailTypeTranslation() + * when the GRF defines no translation table. + * But since there is only one default road/tram-type, this makes little sense anyway. + * So for GRF without translation table, we always return INVALID_ROADTYPE. + */ + + if (grffile == nullptr) return INVALID_ROADTYPE; + + const auto &list = rtt == RTT_TRAM ? grffile->tramtype_list : grffile->roadtype_list; + if (tracktype >= list.size()) return INVALID_ROADTYPE; + + /* Look up roadtype including alternate labels. */ + RoadType result = GetRoadTypeByLabel(list[tracktype]); + + /* Check whether the result is actually the wanted road/tram-type */ + if (result != INVALID_ROADTYPE && GetRoadTramType(result) != rtt) return INVALID_ROADTYPE; + + return result; +} + /** * Perform a reverse roadtype lookup to get the GRF internal ID. * @param roadtype The global (OpenTTD) roadtype. diff --git a/src/newgrf_roadtype.h b/src/newgrf_roadtype.h index 07451f6566..0e08697932 100644 --- a/src/newgrf_roadtype.h +++ b/src/newgrf_roadtype.h @@ -48,6 +48,7 @@ struct RoadTypeResolverObject : public ResolverObject { SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL, uint *num_results = nullptr); +RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8 tracktype, const GRFFile *grffile); uint8 GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile); #endif /* NEWGRF_ROADTYPE_H */ diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index 4e5abaff5b..d69c2d5cc3 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -63,7 +63,8 @@ static const NIVariable _niv_vehicles[] = { NIV(0x4D, "position in articulated vehicle"), NIV(0x60, "count vehicle id occurrences"), // 0x61 not useful, since it requires register 0x10F - NIV(0x62, "Curvature/position difference to other vehicle"), + NIV(0x62, "curvature/position difference to other vehicle"), + NIV(0x63, "tile compatibility wrt. track-type"), NIV_END() };