NewGRF: Allow using Action 2/3 for custom signal sprites

This is mostly the same format as the railtype custom signal mechanism
pull/306/head
Jonathan G Rennison 3 years ago
parent a6b0d0cde4
commit 322a046f49

@ -278,11 +278,42 @@
</table>
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_global_extra_station_names</font>, version 1</p>
<h3 id="a0signals"><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0">Action 0 - Signals (Feature 0E)</a></h3>
<p>Note that Action 0 feature 0E is not supported (does nothing) in standard OpenTTD.</p>
<p>This implementation of feature 0E is not the same as that in TTDPatch.</p>
<h4 id="signals_enable_programmable_signals">Enable custom signal sprites for programmable pre-signals (mappable property: signals_enable_programmable_signals)</h4>
<p>This enables <a href="#a3signals_custom_signal_sprites">Action 2/3 Signals (Feature 0E) custom signal sprites</a> for programmable pre-signals for this GRF.<br />
Programmable pre-signals have the signal type value: 06.<br />
The property length is 1 byte. 0 is disabled (default). 1 is enabled.<br />
The Action 0 Id field is not used, the value is ignored.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_signals_programmable_signals</font>, version 1</p>
<h4 id="signals_enable_restricted_signals">Enable restricted signal flag for custom signal sprites (mappable property: signals_enable_restricted_signals)</h4>
<p>This applies to <a href="#a3signals_custom_signal_sprites">Action 2/3 Signals (Feature 0E) custom signal sprites</a> for this GRF.<br />
When enabled, bit 24 of variable 18 (extra callback info) is set if the signal is restricted (has a routing restriction program attached).<br />
When enabled, the "Show restricted electric signals using default graphics" client setting and signal post recolouring is not applied.<br />
This flag should only be set if the Action 2/3 actually returns a different sprite when bit 24 of variable 18 is set.<br />
The property length is 1 byte. 0 is disabled (default). 1 is enabled.<br />
The Action 0 Id field is not used, the value is ignored.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_signals_restricted_signals</font>, version 1</p>
<br />
<br />
<h3 id="varaction2_station"><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations">Variational Action 2 - Stations</a></h3>
<h4 id="varaction2_station_var42">Track type in purchase list (42)</h4>
<p>This is indicated by the feature name: <font face="monospace">varaction2_station_var42</font>, version 1</p>
<br />
<h3 id="a3signals"><a href="https://newgrf-specs.tt-wiki.net/wiki/Action3">Action 3 - Signals (Feature 0E)</a></h3>
<p>Note that Action 3 feature 0E is not supported (does nothing) in standard OpenTTD.</p>
<p>This implementation of feature 0E is not the same as that in TTDPatch.</p>
<h4 id="a3signals_custom_signal_sprites">Custom signal sprites using Action 2/3 (action 3 ID: 0)</h4>
<p>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 <a href="https://newgrf-specs.tt-wiki.net/wiki/Action3/Railtypes#Signal_sprites_.280B.29">Action 2/3 - Railtype custom signal sprites</a>,<br />
however, this applies to all signals, not only those of a particular rail type.</p>
<p>Variational Action 2 variables 10, 18 and 40 are available and have the same format as in <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Railtypes">VariationalAction2/Railtypes</a>.</p>
<p>Rail type custom signal sprites have a higher priority than custom signal sprites for all signals as set here.</p>
<p>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).</p>
<p>This is indicated by the feature name: <font face="monospace">action3_signals_custom_signal_sprites</font>, version 1</p>
<br />
<h3 id="action5">Action 14 - Type ID Mapping for Action 5</h3>
<p>See <a href="https://newgrf-specs.tt-wiki.net/wiki/Action14">Action 14 Specification</a> and <a href="https://newgrf-specs.tt-wiki.net/wiki/Action5">Action 5 Specification</a> for background information.</p>
<p>The action 5 type ID mapping mechanism has the feature name: <font face="monospace">action5_type_id_mapping</font>, this document describes version 1.</p>

@ -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

@ -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;

@ -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();

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @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<const GRFFile *> _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;
}

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @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<const GRFFile *> _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 */

@ -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 };
}
/**

@ -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);

@ -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) {

@ -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) {

Loading…
Cancel
Save