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
+
+ 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
+
Track type in purchase list (42)
This is indicated by the feature name: varaction2_station_var42, version 1
+
+ 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) {