# HG changeset patch # User frosch # Date 2021-01-10 13:37:40 # Node ID c539e338e87fa0c9876d2ccd61811809039a09b5 # Parent dc757f98ef7c0afe7fc3101faee47f11dfb9ec80 Add: [NewGRF] vehicle variable 63 to test the tracktype of the current tile against a given tracktype. diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -702,6 +702,36 @@ static uint32 VehicleGetVariable(Vehicle 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 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -139,6 +139,28 @@ SpriteID GetCustomSignalSprite(const Rai } /** + * 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. * @param grffile The GRF to do the lookup for. diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -58,6 +58,7 @@ struct RailTypeResolverObject : public R 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 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -133,6 +133,37 @@ SpriteID GetCustomRoadSprite(const RoadT } /** + * 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. * @param grffile The GRF to do the lookup for. diff --git a/src/newgrf_roadtype.h b/src/newgrf_roadtype.h --- a/src/newgrf_roadtype.h +++ b/src/newgrf_roadtype.h @@ -48,6 +48,7 @@ struct RoadTypeResolverObject : public R 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 --- 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() };