diff --git a/docs/newgrf-additions.html b/docs/newgrf-additions.html index ab291e6e5f..9027f6b761 100644 --- a/docs/newgrf-additions.html +++ b/docs/newgrf-additions.html @@ -278,11 +278,42 @@

This is indicated by the feature name: action0_global_extra_station_names, version 1

+

Action 0 - Signals (Feature 0E)

+

Note that Action 0 feature 0E is not supported (does nothing) in standard OpenTTD.

+

This implementation of feature 0E is not the same as that in TTDPatch.

+

Enable custom signal sprites for programmable pre-signals (mappable property: signals_enable_programmable_signals)

+

This enables Action 2/3 Signals (Feature 0E) custom signal sprites for programmable pre-signals for this GRF.
+ Programmable pre-signals have the signal type value: 06.
+ The property length is 1 byte. 0 is disabled (default). 1 is enabled.
+ The Action 0 Id field is not used, the value is ignored. +

+

This is indicated by the feature name: action0_signals_programmable_signals, version 1

+

Enable restricted signal flag for custom signal sprites (mappable property: signals_enable_restricted_signals)

+

This applies to Action 2/3 Signals (Feature 0E) custom signal sprites for this GRF.
+ When enabled, bit 24 of variable 18 (extra callback info) is set if the signal is restricted (has a routing restriction program attached).
+ When enabled, the "Show restricted electric signals using default graphics" client setting and signal post recolouring is not applied.
+ This flag should only be set if the Action 2/3 actually returns a different sprite when bit 24 of variable 18 is set.
+ The property length is 1 byte. 0 is disabled (default). 1 is enabled.
+ The Action 0 Id field is not used, the value is ignored. +

+

This is indicated by the feature name: action0_signals_restricted_signals, version 1

+

Variational Action 2 - Stations

Track type in purchase list (42)

This is indicated by the feature name: varaction2_station_var42, version 1


+

Action 3 - Signals (Feature 0E)

+

Note that Action 3 feature 0E is not supported (does nothing) in standard OpenTTD.

+

This implementation of feature 0E is not the same as that in TTDPatch.

+

Custom signal sprites using Action 2/3 (action 3 ID: 0)

+

This feature allows using Action 3 to assign an Action 2 chain which dynamically resolves signal sprites, in a very similar way to that of Action 2/3 - Railtype custom signal sprites,
+ however, this applies to all signals, not only those of a particular rail type.

+

Variational Action 2 variables 10, 18 and 40 are available and have the same format as in VariationalAction2/Railtypes.

+

Rail type custom signal sprites have a higher priority than custom signal sprites for all signals as set here.

+

Note that this is not a generic callback, the sprite group must be assigned to ID 0 (further IDs may be allocated for other purposes in future).

+

This is indicated by the feature name: action3_signals_custom_signal_sprites, version 1

+

Action 14 - Type ID Mapping for Action 5

See Action 14 Specification and Action 5 Specification for background information.

The action 5 type ID mapping mechanism has the feature name: action5_type_id_mapping, this document describes version 1.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be29ccdd19..8022223ed3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -266,6 +266,8 @@ add_files( newgrf_industries.h newgrf_industrytiles.cpp newgrf_industrytiles.h + newgrf_newsignals.cpp + newgrf_newsignals.h newgrf_object.cpp newgrf_object.h newgrf_profiling.cpp diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 43d14584a3..c7fdb57296 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -33,6 +33,7 @@ #include "newgrf_airporttiles.h" #include "newgrf_airport.h" #include "newgrf_object.h" +#include "newgrf_newsignals.h" #include "rev.h" #include "fios.h" #include "strings_func.h" @@ -4058,6 +4059,39 @@ static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, c return ret; } +/** + * Define properties for signals + * @param id Local ID (unused). + * @param numinfo Number of subsequent IDs to change the property for. + * @param prop The property to change. + * @param buf The property value. + * @return ChangeInfoResult. + */ +static ChangeInfoResult SignalsChangeInfo(uint id, int numinfo, int prop, const GRFFilePropertyRemapEntry *mapping_entry, ByteReader *buf) +{ + /* Properties which are handled per item */ + ChangeInfoResult ret = CIR_SUCCESS; + for (int i = 0; i < numinfo; i++) { + switch (prop) { + case A0RPI_SIGNALS_ENABLE_PROGRAMMABLE_SIGNALS: + if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break; + SB(_cur.grffile->new_signal_ctrl_flags, NSCF_PROGSIG, 1, (buf->ReadByte() != 0 ? 1 : 0)); + break; + + case A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS: + if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break; + SB(_cur.grffile->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG, 1, (buf->ReadByte() != 0 ? 1 : 0)); + break; + + default: + ret = HandleAction0PropertyDefault(buf, prop); + break; + } + } + + return ret; +} + /** * Ignore properties for objects * @param prop The property to ignore. @@ -4886,7 +4920,7 @@ static void FeatureChangeInfo(ByteReader *buf) /* GSF_CARGOES */ nullptr, // Cargo is handled during reservation /* GSF_SOUNDFX */ SoundEffectChangeInfo, /* GSF_AIRPORTS */ AirportChangeInfo, - /* GSF_SIGNALS */ nullptr, + /* GSF_SIGNALS */ SignalsChangeInfo, /* GSF_OBJECTS */ ObjectChangeInfo, /* GSF_RAILTYPES */ RailTypeChangeInfo, /* GSF_AIRPORTTILES */ AirportTilesChangeInfo, @@ -5301,6 +5335,7 @@ static void NewSpriteGroup(ByteReader *buf) case GSF_RAILTYPES: case GSF_ROADTYPES: case GSF_TRAMTYPES: + case GSF_SIGNALS: { byte num_loaded = type; byte num_loading = buf->ReadByte(); @@ -5789,6 +5824,39 @@ static void CargoMapSpriteGroup(ByteReader *buf, uint8 idcount) } } +static void SignalsMapSpriteGroup(ByteReader *buf, uint8 idcount) +{ + uint8 *ids = AllocaM(uint8, idcount); + for (uint i = 0; i < idcount; i++) { + ids[i] = buf->ReadByte(); + } + + /* Skip the cargo type section, we only care about the default group */ + uint8 cidcount = buf->ReadByte(); + buf->Skip(cidcount * 3); + + uint16 groupid = buf->ReadWord(); + if (!IsValidGroupID(groupid, "SignalsMapSpriteGroup")) return; + + for (uint i = 0; i < idcount; i++) { + uint8 id = ids[i]; + + switch (id) { + case NSA3ID_CUSTOM_SIGNALS: + _cur.grffile->new_signals_group = _cur.spritegroups[groupid]; + if (!HasBit(_cur.grffile->new_signal_ctrl_flags, NSCF_GROUPSET)) { + SetBit(_cur.grffile->new_signal_ctrl_flags, NSCF_GROUPSET); + _new_signals_grfs.push_back(_cur.grffile); + } + break; + + default: + grfmsg(1, "SignalsMapSpriteGroup: ID not implemented: %d", id); + break; + } + } +} + static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount) { if (_cur.grffile->objectspec == nullptr) { @@ -6050,6 +6118,10 @@ static void FeatureMapSpriteGroup(ByteReader *buf) AirportMapSpriteGroup(buf, idcount); return; + case GSF_SIGNALS: + SignalsMapSpriteGroup(buf, idcount); + break; + case GSF_OBJECTS: ObjectMapSpriteGroup(buf, idcount); break; @@ -8398,6 +8470,9 @@ static const GRFFeatureInfo _grf_feature_list[] = { GRFFeatureInfo("action0_railtype_disable_realistic_braking", 1), GRFFeatureInfo("action0_roadtype_extra_flags", 1), GRFFeatureInfo("action0_global_extra_station_names", 1), + GRFFeatureInfo("action0_signals_programmable_signals", 1), + GRFFeatureInfo("action0_signals_restricted_signals", 1), + GRFFeatureInfo("action3_signals_custom_signal_sprites", 1), GRFFeatureInfo(), }; @@ -8520,6 +8595,8 @@ static const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = { GRFPropertyMapDefinition(GSF_ROADTYPES, A0RPI_ROADTYPE_EXTRA_FLAGS, "roadtype_extra_flags"), GRFPropertyMapDefinition(GSF_TRAMTYPES, A0RPI_ROADTYPE_EXTRA_FLAGS, "roadtype_extra_flags"), GRFPropertyMapDefinition(GSF_GLOBALVAR, A0RPI_GLOBALVAR_EXTRA_STATION_NAMES, "global_extra_station_names"), + GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_PROGRAMMABLE_SIGNALS, "signals_enable_programmable_signals"), + GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS, "signals_enable_restricted_signals"), GRFPropertyMapDefinition(), }; @@ -9140,6 +9217,7 @@ static void ResetNewGRF() _grf_files.clear(); _cur.grffile = nullptr; + _new_signals_grfs.clear(); } /** Clear all NewGRF errors */ @@ -9314,6 +9392,9 @@ GRFFile::GRFFile(const GRFConfig *config) this->traininfo_vehicle_pitch = 0; this->traininfo_vehicle_width = TRAININFO_DEFAULT_VEHICLE_WIDTH; + this->new_signals_group = nullptr; + this->new_signal_ctrl_flags = 0; + /* Mark price_base_multipliers as 'not set' */ for (Price i = PR_BEGIN; i < PR_END; i++) { this->price_base_multipliers[i] = INVALID_PRICE_MODIFIER; diff --git a/src/newgrf.h b/src/newgrf.h index 1bf44d8c54..6760550e9b 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -120,6 +120,8 @@ enum Action0RemapPropertyIds { A0RPI_RAILTYPE_DISABLE_REALISTIC_BRAKING, A0RPI_ROADTYPE_EXTRA_FLAGS, A0RPI_GLOBALVAR_EXTRA_STATION_NAMES, + A0RPI_SIGNALS_ENABLE_PROGRAMMABLE_SIGNALS, + A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS, }; enum GRFPropertyMapFallbackMode { @@ -215,6 +217,18 @@ struct Action5TypeRemapSet { } }; +/** New signal control flags. */ +enum NewSignalCtrlFlags { + NSCF_GROUPSET = 0, ///< Custom signal sprites group set. + NSCF_PROGSIG = 1, ///< Custom signal sprites enabled for programmable pre-signals. + NSCF_RESTRICTEDSIG = 2, ///< Custom signal sprite flag enabled for restricted signals. +}; + +/** New signal control flags. */ +enum NewSignalAction3ID { + NSA3ID_CUSTOM_SIGNALS = 0, ///< Action 3 ID for custom signal sprites +}; + /** Dynamic data of a loaded NewGRF */ struct GRFFile : ZeroedMemoryAllocator { char *filename; @@ -266,6 +280,9 @@ struct GRFFile : ZeroedMemoryAllocator { uint32 var8D_overlay; ///< Overlay for global variable 8D (action 0x14) uint32 var9D_overlay; ///< Overlay for global variable 9D (action 0x14) + const SpriteGroup *new_signals_group; ///< New signals sprite group + byte new_signal_ctrl_flags; ///< Ctrl flags for new signals + GRFFile(const struct GRFConfig *config); ~GRFFile(); diff --git a/src/newgrf_newsignals.cpp b/src/newgrf_newsignals.cpp new file mode 100644 index 0000000000..26665cbffc --- /dev/null +++ b/src/newgrf_newsignals.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file newgrf_newsignals.cpp NewGRF handling of new signals. */ + +#include "stdafx.h" +#include "debug.h" +#include "newgrf_newsignals.h" +#include "map_func.h" + +#include "safeguards.h" + +std::vector _new_signals_grfs; + +/* virtual */ uint32 NewSignalsScopeResolver::GetRandomBits() const +{ + uint tmp = CountBits(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE); + return GB(tmp, 0, 2); +} + +/* virtual */ uint32 NewSignalsScopeResolver::GetVariable(byte variable, uint32 parameter, GetVariableExtra *extra) const +{ + if (this->tile == INVALID_TILE) { + switch (variable) { + case 0x40: return 0; + } + } + + switch (variable) { + case 0x40: return GetTerrainType(this->tile, this->context); + } + + DEBUG(grf, 1, "Unhandled new signals tile variable 0x%X", variable); + + extra->available = false; + return UINT_MAX; +} + +/* virtual */ const SpriteGroup *NewSignalsResolverObject::ResolveReal(const RealSpriteGroup *group) const +{ + if (!group->loading.empty()) return group->loading[0]; + if (!group->loaded.empty()) return group->loaded[0]; + return nullptr; +} + +GrfSpecFeature NewSignalsResolverObject::GetFeature() const +{ + return GSF_SIGNALS; +} + +/** + * Resolver object for rail types. + * @param grffile GRF file. + * @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead. + * @param context Are we resolving sprites for the upper halftile, or on a bridge? + * @param param1 Extra parameter (first parameter of the callback, except railtypes do not have callbacks). + * @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks). + */ +NewSignalsResolverObject::NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1, uint32 param2) + : ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), newsignals_scope(*this, tile, context) +{ + this->root_spritegroup = grffile != nullptr ? grffile->new_signals_group : nullptr; +} diff --git a/src/newgrf_newsignals.h b/src/newgrf_newsignals.h new file mode 100644 index 0000000000..eb2a3a0049 --- /dev/null +++ b/src/newgrf_newsignals.h @@ -0,0 +1,57 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file newgrf_newsignals.h NewGRF handling of new signals. */ + +#ifndef NEWGRF_NEWSIGNALS_H +#define NEWGRF_NEWSIGNALS_H + +#include "newgrf_commons.h" +#include "newgrf_spritegroup.h" + +extern std::vector _new_signals_grfs; + +/** Resolver for the new signals scope. */ +struct NewSignalsScopeResolver : public ScopeResolver { + TileIndex tile; ///< Tracktile. For track on a bridge this is the southern bridgehead. + TileContext context; ///< Are we resolving sprites for the upper halftile, or on a bridge? + + /** + * Constructor of the railtype scope resolvers. + * @param ro Surrounding resolver. + * @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead. + * @param context Are we resolving sprites for the upper halftile, or on a bridge? + */ + NewSignalsScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context) + : ScopeResolver(ro), tile(tile), context(context) + { + } + + uint32 GetRandomBits() const override; + uint32 GetVariable(byte variable, uint32 parameter, GetVariableExtra *extra) const override; +}; + +/** Resolver object for rail types. */ +struct NewSignalsResolverObject : public ResolverObject { + NewSignalsScopeResolver newsignals_scope; ///< Resolver for the new signals scope. + + NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1 = 0, uint32 param2 = 0); + + ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override + { + switch (scope) { + case VSG_SCOPE_SELF: return &this->newsignals_scope; + default: return ResolverObject::GetScope(scope, relative); + } + } + + const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override; + + GrfSpecFeature GetFeature() const override; +}; + +#endif /* NEWGRF_RAILTYPE_H */ diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index bfa68d5228..c4a94b784e 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -10,6 +10,7 @@ #include "stdafx.h" #include "debug.h" #include "newgrf_railtype.h" +#include "newgrf_newsignals.h" #include "date_func.h" #include "depot_base.h" #include "town.h" @@ -114,6 +115,22 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp return group->GetResult(); } +static SpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui, bool restricted) +{ + if (rti->group[RTSG_SIGNALS] == nullptr) return 0; + if (type == SIGTYPE_PROG && !HasBit(rti->ctrl_flags, RTCF_PROGSIG)) return 0; + + uint32 param1 = gui ? 0x10 : 0x00; + uint32 param2 = (type << 16) | (var << 8) | state; + if (restricted && HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) SetBit(param2, 24); + RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2); + + const SpriteGroup *group = object.Resolve(); + if (group == nullptr || group->GetNumResults() == 0) return 0; + + return group->GetResult(); +} + /** * Get the sprite to draw for a given signal. * @param rti The rail type data (spec). @@ -124,20 +141,24 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp * @param gui Is the sprite being used on the map or in the GUI? * @return The sprite to draw. */ -SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui, bool restricted) +CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui, bool restricted) { - if (rti->group[RTSG_SIGNALS] == nullptr) return 0; - if (type == SIGTYPE_PROG && !HasBit(rti->ctrl_flags, RTCF_PROGSIG)) return 0; + SpriteID spr = GetRailTypeCustomSignalSprite(rti, tile, type, var, state, gui, restricted); + if (spr != 0) return { spr, HasBit(rti->ctrl_flags, RTCF_PROGSIG) }; - uint32 param1 = gui ? 0x10 : 0x00; - uint32 param2 = (type << 16) | (var << 8) | state; - if (restricted && HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) SetBit(param2, 24); - RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2); + for (const GRFFile *grf : _new_signals_grfs) { + if (type == SIGTYPE_PROG && !HasBit(grf->new_signal_ctrl_flags, NSCF_PROGSIG)) continue; - const SpriteGroup *group = object.Resolve(); - if (group == nullptr || group->GetNumResults() == 0) return 0; + uint32 param1 = gui ? 0x10 : 0x00; + uint32 param2 = (type << 16) | (var << 8) | state; + if (restricted && HasBit(grf->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG)) SetBit(param2, 24); + NewSignalsResolverObject object(grf, tile, TCX_NORMAL, param1, param2); - return group->GetResult(); + const SpriteGroup *group = object.Resolve(); + if (group != nullptr && group->GetNumResults() != 0) return { group->GetResult(), HasBit(grf->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG) }; + } + + return { 0, false }; } /** diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index e2900b492f..a2d92f75c8 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -55,8 +55,13 @@ struct RailTypeResolverObject : public ResolverObject { uint32 GetDebugID() const override; }; +struct CustomSignalSpriteResult { + SpriteID sprite_id; + bool restricted_valid; +}; + 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, bool restricted = false); +CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui = false, bool restricted = false); RailType GetRailTypeTranslation(uint8 railtype, const GRFFile *grffile); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 1ce5829a3d..7b0a8b7ede 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -113,8 +113,8 @@ void ResolveRailTypeGUISprites(RailtypeInfo *rti) for (SignalType type = SIGTYPE_NORMAL; type < SIGTYPE_END; type = (SignalType)(type + 1)) { for (SignalVariant var = SIG_ELECTRIC; var <= SIG_SEMAPHORE; var = (SignalVariant)(var + 1)) { - SpriteID red = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true); - SpriteID green = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true); + SpriteID red = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true).sprite_id; + SpriteID green = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true).sprite_id; rti->gui_sprites.signals[type][var][0] = (red != 0) ? red + SIGNAL_TO_SOUTH : _signal_lookup[var][type]; rti->gui_sprites.signals[type][var][1] = (green != 0) ? green + SIGNAL_TO_SOUTH : _signal_lookup[var][type] + 1; } @@ -2670,7 +2670,8 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign uint x, y; GetSignalXY(tile, pos, x, y); - SpriteID sprite = GetCustomSignalSprite(rti, tile, type, variant, condition, false, show_restricted); + const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, tile, type, variant, condition, false, show_restricted); + SpriteID sprite = result.sprite_id; bool is_custom_sprite = (sprite != 0); if (sprite != 0) { sprite += image; @@ -2692,7 +2693,7 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign is_custom_sprite = file != nullptr && (file->flags & SFF_USERGRF) && !(file->flags & SFF_OGFX); } - if (is_custom_sprite && show_restricted && _settings_client.gui.show_restricted_signal_default && !HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) { + if (is_custom_sprite && show_restricted && _settings_client.gui.show_restricted_signal_default && !result.restricted_valid) { /* Use duplicate sprite block, instead of GRF-specified signals */ if (type == SIGTYPE_PROG) { if (variant == SIG_SEMAPHORE) { diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index a9eb44dd40..70f1d10ce0 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1719,7 +1719,7 @@ static void DrawTunnelBridgeRampSingleSignal(const TileInfo *ti, bool is_green, SignalVariant variant = IsTunnelBridgeSemaphore(ti->tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); - SpriteID sprite = GetCustomSignalSprite(rti, ti->tile, type, variant, is_green ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED); + SpriteID sprite = GetCustomSignalSprite(rti, ti->tile, type, variant, is_green ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED).sprite_id; bool is_custom_sprite = (sprite != 0); if (is_custom_sprite) {