Add combined normal and shunt aspect signal style flag

This commit is contained in:
Jonathan G Rennison
2022-06-27 18:51:26 +01:00
parent a6e3467d58
commit 78ae295dfe
15 changed files with 199 additions and 26 deletions

View File

@@ -516,13 +516,20 @@ item (FEAT_GLOBALVARS) {
<tr><td>style_lookahead_single_signal_only</td><td>0 or 1</td> <tr><td>style_lookahead_single_signal_only</td><td>0 or 1</td>
<td> <td>
Set the look-ahead to single signal only mode for the most recently defined style (defined using the <span class="code">define_style</span> property).<br /> Set the look-ahead to single signal only mode for the most recently defined style (defined using the <span class="code">define_style</span> property).<br />
This property only makes a difference when the "limit train lookahead to signal aspect" game setting is enabled.<br /> This property only makes a difference when the "limit train lookahead to signal aspect" game setting is enabled, or when using a different signal
type which uses <span class="code">tyle_combined_normal_shunt</span>.<br />
This is similar to <span class="code">style_lookahead_extra_aspects</span> with a value of 0, except the lookahead always ends at the This is similar to <span class="code">style_lookahead_extra_aspects</span> with a value of 0, except the lookahead always ends at the
next signal, even if that signal type sets <span class="code">style_no_aspect_increase</span>.<br /> next signal, even if that signal type sets <span class="code">style_no_aspect_increase</span>.<br />
If enabled, this property overrides <span class="code">style_lookahead_extra_aspects</span>.<br /> If enabled, this property overrides <span class="code">style_lookahead_extra_aspects</span>.<br />
This can be used for shunt signals. This can be used for shunt signals.
</td> </td>
</tr> </tr>
<tr><td>style_combined_normal_shunt</td><td>0 or 1</td>
<td>
Enable functioning as a combined normal aspect and shunt signal for the most recently defined style (defined using the <span class="code">define_style</span> property).<br />
When enabled and displaying a shunt aspect, the signal state in the lowest byte of <span class="code">extra_callback_info2</span> will have the value: 0xFF.
</td>
</tr>
<tr><td>style_opposite_side</td><td>0 or 1</td> <tr><td>style_opposite_side</td><td>0 or 1</td>
<td> <td>
Set whether signals should be drawn on the opposite side of the track for the most recently defined style (defined using the <span class="code">define_style</span> property). Set whether signals should be drawn on the opposite side of the track for the most recently defined style (defined using the <span class="code">define_style</span> property).

View File

@@ -483,7 +483,8 @@
<p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p> <p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p>
<h4 id="signals_style_lookahead_single_signal_only">Set custom signal style train look-ahead to single signal only mode (mappable property: signals_style_lookahead_single_signal_only)</h4> <h4 id="signals_style_lookahead_single_signal_only">Set custom signal style train look-ahead to single signal only mode (mappable property: signals_style_lookahead_single_signal_only)</h4>
<p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br /> <p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br />
This property only makes a difference when the "limit train lookahead to signal aspect" game setting is enabled.<br /> This property only makes a difference when the "limit train lookahead to signal aspect" game setting is enabled, or when using a different signal
type which uses <a href="#signals_style_combined_normal_shunt">signals_style_combined_normal_shunt</a>.<br />
This is similar to <a href="#signals_style_lookahead_extra_aspects">signals_style_lookahead_extra_aspects</a> with a value of 0, except the lookahead always ends at the This is similar to <a href="#signals_style_lookahead_extra_aspects">signals_style_lookahead_extra_aspects</a> with a value of 0, except the lookahead always ends at the
next signal, even if that signal type sets <a href="#signals_style_no_aspect_increase">signals_style_no_aspect_increase</a>.<br /> next signal, even if that signal type sets <a href="#signals_style_no_aspect_increase">signals_style_no_aspect_increase</a>.<br />
If enabled, this property overrides <a href="#signals_style_lookahead_extra_aspects">signals_style_lookahead_extra_aspects</a>.<br /> If enabled, this property overrides <a href="#signals_style_lookahead_extra_aspects">signals_style_lookahead_extra_aspects</a>.<br />
@@ -492,6 +493,13 @@
The Action 0 Id field is not used, the value is ignored. The Action 0 Id field is not used, the value is ignored.
</p> </p>
<p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p> <p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p>
<h4 id="signals_style_combined_normal_shunt">Set custom signal style combined normal aspect and shunt signal mode (mappable property: signals_style_combined_normal_shunt)</h4>
<p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br />
When enabled and displaying a shunt aspect, the signal state in the lowest byte of variable 0x18 (SS: signal state) will have the value: 0xFF.</p>
<p>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_style</font>, version 1</p>
<h4 id="signals_style_opposite_side">Set custom signal style signal drawn on opposite side (mappable property: signals_style_opposite_side)</h4> <h4 id="signals_style_opposite_side">Set custom signal style signal drawn on opposite side (mappable property: signals_style_opposite_side)</h4>
<p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br /> <p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br />
When enabled, signals using this style are drawn on the opposite side of the track.</p> When enabled, signals using this style are drawn on the opposite side of the track.</p>

View File

@@ -356,7 +356,7 @@ void UpdateAllBlockSignals(Owner owner)
} }
if (_extra_aspects > 0 && IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeEntranceSignalState(tile) == SIGNAL_STATE_GREEN) { if (_extra_aspects > 0 && IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeEntranceSignalState(tile) == SIGNAL_STATE_GREEN) {
SetTunnelBridgeEntranceSignalAspect(tile, 0); SetTunnelBridgeEntranceSignalAspect(tile, 0);
UpdateAspectDeferred(tile, GetTunnelBridgeEntranceTrackdir(tile)); UpdateAspectDeferred(tile, GetTunnelBridgeEntranceTrackdir(tile), false);
} }
} }
} while (++tile != MapSize()); } while (++tile != MapSize());

View File

@@ -4289,6 +4289,15 @@ static ChangeInfoResult SignalsChangeInfo(uint id, int numinfo, int prop, const
break; break;
} }
case A0RPI_SIGNALS_STYLE_COMBINED_NORMAL_SHUNT: {
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
uint8 value = buf->ReadByte();
if (_cur.grffile->current_new_signal_style != nullptr) {
SB(_cur.grffile->current_new_signal_style->style_flags, NSSF_COMBINED_NORMAL_SHUNT, 1, (value != 0 ? 1 : 0));
}
break;
}
default: default:
ret = HandleAction0PropertyDefault(buf, prop); ret = HandleAction0PropertyDefault(buf, prop);
break; break;

View File

@@ -101,6 +101,7 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED, "signals_style_semaphore_enabled"), GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED, "signals_style_semaphore_enabled"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED, "signals_style_electric_enabled"), GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED, "signals_style_electric_enabled"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE, "signals_style_opposite_side"), GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE, "signals_style_opposite_side"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_COMBINED_NORMAL_SHUNT, "signals_style_combined_normal_shunt"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_USE_LAND_GROUND, "object_use_land_ground"), GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_USE_LAND_GROUND, "object_use_land_ground"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_EDGE_FOUNDATION_MODE, "object_edge_foundation_mode"), GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_EDGE_FOUNDATION_MODE, "object_edge_foundation_mode"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_FLOOD_RESISTANT, "object_flood_resistant"), GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_FLOOD_RESISTANT, "object_flood_resistant"),

View File

@@ -45,6 +45,7 @@ enum Action0RemapPropertyIds {
A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED, A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED,
A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED, A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED,
A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE, A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE,
A0RPI_SIGNALS_STYLE_COMBINED_NORMAL_SHUNT,
A0RPI_OBJECT_USE_LAND_GROUND, A0RPI_OBJECT_USE_LAND_GROUND,
A0RPI_OBJECT_EDGE_FOUNDATION_MODE, A0RPI_OBJECT_EDGE_FOUNDATION_MODE,
A0RPI_OBJECT_FLOOD_RESISTANT, A0RPI_OBJECT_FLOOD_RESISTANT,

View File

@@ -33,6 +33,7 @@ enum NewSignalStyleFlags {
NSSF_LOOKAHEAD_ASPECTS_SET = 2, NSSF_LOOKAHEAD_ASPECTS_SET = 2,
NSSF_OPPOSITE_SIDE = 3, NSSF_OPPOSITE_SIDE = 3,
NSSF_LOOKAHEAD_SINGLE_SIGNAL = 4, NSSF_LOOKAHEAD_SINGLE_SIGNAL = 4,
NSSF_COMBINED_NORMAL_SHUNT = 5,
}; };
struct NewSignalStyle { struct NewSignalStyle {

View File

@@ -15,6 +15,7 @@
#include "date_func.h" #include "date_func.h"
#include "depot_base.h" #include "depot_base.h"
#include "town.h" #include "town.h"
#include "signal_func.h"
#include "safeguards.h" #include "safeguards.h"
@@ -117,10 +118,16 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp
return group->GetResult(); return group->GetResult();
} }
inline uint8 RemapAspect(uint8 aspect, uint8 extra_aspects) inline uint8 RemapAspect(uint8 aspect, uint8 extra_aspects, uint8 style)
{ {
if (likely(extra_aspects == 0 || _extra_aspects == 0)) return std::min<uint8>(aspect, 1); if (likely(extra_aspects == 0 || _extra_aspects == 0)) return std::min<uint8>(aspect, 1);
if (aspect == 0) return 0; if (aspect == 0) return 0;
if (style != 0 && HasBit(_signal_style_masks.combined_normal_shunt, style)) {
if (aspect == 1) {
return 0xFF;
}
aspect--;
}
if (aspect >= extra_aspects + 1) return 1; if (aspect >= extra_aspects + 1) return 1;
return aspect + 1; return aspect + 1;
} }
@@ -132,7 +139,7 @@ static PalSpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIn
if (type == SIGTYPE_NO_ENTRY && !HasBit(rti->ctrl_flags, RTCF_NOENTRYSIG)) return { 0, PAL_NONE }; if (type == SIGTYPE_NO_ENTRY && !HasBit(rti->ctrl_flags, RTCF_NOENTRYSIG)) return { 0, PAL_NONE };
uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00; uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00;
uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, rti->signal_extra_aspects); uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, rti->signal_extra_aspects, 0);
if ((prog != nullptr) && HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) SetBit(param2, 24); if ((prog != nullptr) && HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) SetBit(param2, 24);
RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2, context, prog); RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2, context, prog);
@@ -170,7 +177,7 @@ CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileInde
if (!HasBit(grf->new_signal_style_mask, style)) continue; if (!HasBit(grf->new_signal_style_mask, style)) continue;
uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00; uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00;
uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, grf->new_signal_extra_aspects); uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, grf->new_signal_extra_aspects, style);
if ((prog != nullptr) && HasBit(grf->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG)) SetBit(param2, 24); if ((prog != nullptr) && HasBit(grf->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG)) SetBit(param2, 24);
NewSignalsResolverObject object(grf, tile, TCX_NORMAL, param1, param2, context, style, prog); NewSignalsResolverObject object(grf, tile, TCX_NORMAL, param1, param2, context, style, prog);

View File

@@ -88,7 +88,7 @@ bool TryReserveRailTrackdir(TileIndex tile, Trackdir td, bool trigger_stations)
MarkSingleSignalDirty(tile, td); MarkSingleSignalDirty(tile, td);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetSignalAspect(tile, TrackdirToTrack(td), 0); SetSignalAspect(tile, TrackdirToTrack(td), 0);
UpdateAspectDeferred(tile, td); UpdateAspectDeferred(tile, td, true);
} }
} }
return success; return success;
@@ -667,6 +667,10 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
if (HasBit(_signal_style_masks.next_only, signal_style)) { if (HasBit(_signal_style_masks.next_only, signal_style)) {
SetBit(signal_flags, TRSLAI_NEXT_ONLY); SetBit(signal_flags, TRSLAI_NEXT_ONLY);
} }
if (HasBit(_signal_style_masks.combined_normal_shunt, signal_style)) {
SetBit(signal_flags, TRSLAI_COMBINED);
UpdateLookaheadCombinedNormalShuntSignalDeferred(tile, trackdir, lookahead->RealEndPosition());
}
lookahead->AddSignal(signal_speed, 0, z, signal_flags); lookahead->AddSignal(signal_speed, 0, z, signal_flags);
lookahead->SetNextExtendPositionIfUnset(); lookahead->SetNextExtendPositionIfUnset();
} }
@@ -1011,6 +1015,18 @@ void SetTrainReservationLookaheadEnd(Train *v)
for (const TrainReservationLookAheadItem &item : v->lookahead->items) { for (const TrainReservationLookAheadItem &item : v->lookahead->items) {
if (item.end >= v->lookahead->reservation_end_position) break; if (item.end >= v->lookahead->reservation_end_position) break;
if (item.type == TRLIT_SIGNAL) { if (item.type == TRLIT_SIGNAL) {
if (HasBit(item.data_aux, TRSLAI_COMBINED_SHUNT)) {
/* Combined normal/shunt in shunt mode */
allow_skip_no_aspect_inc = false;
if (item.start <= threshold) {
known_signals_ahead = 1;
continue;
} else {
if (item.start > v->lookahead->lookahead_end_position) v->lookahead->lookahead_end_position = item.start;
return;
}
}
if (item.start <= threshold) { if (item.start <= threshold) {
/* Signal is within visual range */ /* Signal is within visual range */
uint8 style = item.data_aux >> 8; uint8 style = item.data_aux >> 8;
@@ -1090,6 +1106,7 @@ void FillTrainReservationLookAhead(Train *v)
} }
if (!(HasAcrossTunnelBridgeReservation(end) && GetTunnelBridgeExitSignalState(end) == SIGNAL_STATE_GREEN && raw_free_tiles == INT_MAX)) { if (!(HasAcrossTunnelBridgeReservation(end) && GetTunnelBridgeExitSignalState(end) == SIGNAL_STATE_GREEN && raw_free_tiles == INT_MAX)) {
/* do not attempt to follow through a signalled tunnel/bridge if it is not empty or the far end is not reserved */ /* do not attempt to follow through a signalled tunnel/bridge if it is not empty or the far end is not reserved */
FlushDeferredDetermineCombineNormalShuntMode(v);
SetTrainReservationLookaheadEnd(v); SetTrainReservationLookaheadEnd(v);
return; return;
} }
@@ -1097,6 +1114,7 @@ void FillTrainReservationLookAhead(Train *v)
} }
if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) { if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) {
FlushDeferredDetermineCombineNormalShuntMode(v);
SetTrainReservationLookaheadEnd(v); SetTrainReservationLookaheadEnd(v);
return; return;
} }
@@ -1131,6 +1149,7 @@ void FillTrainReservationLookAhead(Train *v)
v->lookahead->reservation_end_tile = res.tile; v->lookahead->reservation_end_tile = res.tile;
v->lookahead->reservation_end_trackdir = res.trackdir; v->lookahead->reservation_end_trackdir = res.trackdir;
FlushDeferredDetermineCombineNormalShuntMode(v);
SetTrainReservationLookaheadEnd(v); SetTrainReservationLookaheadEnd(v);
} }

View File

@@ -61,6 +61,8 @@ enum TrainReservationLookAheadItemType : byte {
enum TrainReservationSignalLookAheadItemFlags { enum TrainReservationSignalLookAheadItemFlags {
TRSLAI_NO_ASPECT_INC = 0, ///< This signal does not increase the signal aspect (e.g. banner repeater) TRSLAI_NO_ASPECT_INC = 0, ///< This signal does not increase the signal aspect (e.g. banner repeater)
TRSLAI_NEXT_ONLY = 1, ///< This signal only permits lookahead up to the next physical signal, even if that has TRSLAI_NO_ASPECT_INC (e.g. shunt) TRSLAI_NEXT_ONLY = 1, ///< This signal only permits lookahead up to the next physical signal, even if that has TRSLAI_NO_ASPECT_INC (e.g. shunt)
TRSLAI_COMBINED = 2, ///< This signal is a combined normal/shunt signal, special handling
TRSLAI_COMBINED_SHUNT = 3, ///< This signal is a combined normal/shunt signal, in shunt mode
}; };
struct TrainReservationLookAheadItem { struct TrainReservationLookAheadItem {

View File

@@ -1434,7 +1434,7 @@ static void SetupBridgeTunnelSignalSimulation(TileIndex entrance, TileIndex exit
SetTunnelBridgeSignalSimulationExit(exit); SetTunnelBridgeSignalSimulationExit(exit);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeEntranceSignalAspect(entrance, 0); SetTunnelBridgeEntranceSignalAspect(entrance, 0);
UpdateAspectDeferred(entrance, GetTunnelBridgeEntranceTrackdir(entrance)); UpdateAspectDeferred(entrance, GetTunnelBridgeEntranceTrackdir(entrance), false);
} }
} }
@@ -1583,7 +1583,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
SetTunnelBridgeSignalSimulationExit(t); SetTunnelBridgeSignalSimulationExit(t);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeEntranceSignalAspect(t, 0); SetTunnelBridgeEntranceSignalAspect(t, 0);
UpdateAspectDeferred(t, GetTunnelBridgeEntranceTrackdir(t)); UpdateAspectDeferred(t, GetTunnelBridgeEntranceTrackdir(t), false);
} }
}; };

View File

@@ -25,6 +25,7 @@
#include "newgrf_newsignals.h" #include "newgrf_newsignals.h"
#include "core/checksum_func.hpp" #include "core/checksum_func.hpp"
#include "core/hash_func.hpp" #include "core/hash_func.hpp"
#include "pathfinder/follow_track.hpp"
#include "safeguards.h" #include "safeguards.h"
@@ -367,7 +368,7 @@ static SigInfo ExploreSegment(Owner owner)
if (HasSignalOnTrackdir(tile, reversedir)) { if (HasSignalOnTrackdir(tile, reversedir)) {
if (IsPbsSignalNonExtended(sig)) { if (IsPbsSignalNonExtended(sig)) {
info.flags |= SF_PBS; info.flags |= SF_PBS;
if (_extra_aspects > 0 && GetSignalStateByTrackdir(tile, reversedir) == SIGNAL_STATE_GREEN) { if (_extra_aspects > 0 && GetSignalStateByTrackdir(tile, reversedir) == SIGNAL_STATE_GREEN && !IsRailSpecialSignalAspect(tile, track)) {
_tbpset.Add(tile, reversedir); _tbpset.Add(tile, reversedir);
} }
} else if (!_tbuset.Add(tile, reversedir)) { } else if (!_tbuset.Add(tile, reversedir)) {
@@ -778,7 +779,7 @@ static void UpdateSignalsAroundSegment(SigInfo info)
/* don't change signal state if tile is reserved in realistic braking mode */ /* don't change signal state if tile is reserved in realistic braking mode */
if ((_settings_game.vehicle.train_braking_model == TBM_REALISTIC && HasBit(GetRailReservationTrackBits(tile), track))) { if ((_settings_game.vehicle.train_braking_model == TBM_REALISTIC && HasBit(GetRailReservationTrackBits(tile), track))) {
if (_extra_aspects > 0 && GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { if (_extra_aspects > 0 && GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN && !IsRailSpecialSignalAspect(tile, track)) {
uint8 aspect = GetForwardAspectAndIncrement(info, tile, trackdir); uint8 aspect = GetForwardAspectAndIncrement(info, tile, trackdir);
uint8 old_aspect = GetSignalAspect(tile, track); uint8 old_aspect = GetSignalAspect(tile, track);
if (aspect != old_aspect) { if (aspect != old_aspect) {
@@ -1263,7 +1264,14 @@ uint8 GetSignalAspectGeneric(TileIndex tile, Trackdir trackdir, bool check_non_i
void AdjustSignalAspectIfNonIncStyleIntl(TileIndex tile, Track track, uint8 &aspect) void AdjustSignalAspectIfNonIncStyleIntl(TileIndex tile, Track track, uint8 &aspect)
{ {
if (IsTileType(tile, MP_RAILWAY) && HasBit(_signal_style_masks.non_aspect_inc, GetSignalStyle(tile, track))) aspect--; if (IsTileType(tile, MP_RAILWAY)) {
uint8 style = GetSignalStyle(tile, track);
if (HasBit(_signal_style_masks.combined_normal_shunt, style)) {
aspect--;
if (aspect == 0) return;
}
if (HasBit(_signal_style_masks.non_aspect_inc, style)) aspect--;
}
} }
static void RefreshBridgeOnExitAspectChange(TileIndex entrance, TileIndex exit) static void RefreshBridgeOnExitAspectChange(TileIndex entrance, TileIndex exit)
@@ -1282,6 +1290,11 @@ static void RefreshBridgeOnExitAspectChange(TileIndex entrance, TileIndex exit)
} }
} }
static inline bool IsRailCombinedNormalShuntSignalStyle(TileIndex tile, Track track)
{
return _signal_style_masks.combined_normal_shunt != 0 && HasBit(_signal_style_masks.combined_normal_shunt, GetSignalStyle(tile, track));
}
void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect) void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect)
{ {
AdjustSignalAspectIfNonIncStyle(tile, TrackdirToTrack(trackdir), aspect); AdjustSignalAspectIfNonIncStyle(tile, TrackdirToTrack(trackdir), aspect);
@@ -1330,7 +1343,14 @@ void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect)
if (HasSignalOnTrackdir(tile, reversedir)) { if (HasSignalOnTrackdir(tile, reversedir)) {
if (GetSignalStateByTrackdir(tile, reversedir) == SIGNAL_STATE_RED) return; if (GetSignalStateByTrackdir(tile, reversedir) == SIGNAL_STATE_RED) return;
if (GetSignalAspect(tile, track) == aspect) return; // aspect already correct bool combined_mode = IsRailCombinedNormalShuntSignalStyle(tile, track);
const uint8 current_aspect = GetSignalAspect(tile, track);
if (combined_mode && current_aspect == 1) {
/* Don't change special combined_normal_shunt aspect */
return;
}
if (combined_mode && aspect > 0) aspect = std::min<uint8>(aspect + 1, 7);
if (current_aspect == aspect) return; // aspect already correct
SetSignalAspect(tile, track, aspect); SetSignalAspect(tile, track, aspect);
MarkSingleSignalDirty(tile, reversedir); MarkSingleSignalDirty(tile, reversedir);
AdjustSignalAspectIfNonIncStyle(tile, TrackdirToTrack(trackdir), aspect); AdjustSignalAspectIfNonIncStyle(tile, TrackdirToTrack(trackdir), aspect);
@@ -1426,12 +1446,29 @@ void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect)
} }
static std::vector<std::pair<TileIndex, Trackdir>> _deferred_aspect_updates; static std::vector<std::pair<TileIndex, Trackdir>> _deferred_aspect_updates;
static std::vector<std::pair<TileIndex, Trackdir>> _deferred_determine_combined_normal_shunt_mode;
void UpdateAspectDeferred(TileIndex tile, Trackdir trackdir) struct DeferredLookaheadCombinedNormalShuntModeItem {
TileIndex tile;
Trackdir trackdir;
int lookahead_position;
};
static std::vector<DeferredLookaheadCombinedNormalShuntModeItem> _deferred_lookahead_combined_normal_shunt_mode;
void UpdateAspectDeferred(TileIndex tile, Trackdir trackdir, bool check_combined_normal_aspect)
{ {
if (check_combined_normal_aspect && IsRailCombinedNormalShuntSignalStyle(tile, TrackdirToTrack(trackdir)) &&
_settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
_deferred_determine_combined_normal_shunt_mode.push_back({ tile, trackdir });
}
_deferred_aspect_updates.push_back({ tile, trackdir }); _deferred_aspect_updates.push_back({ tile, trackdir });
} }
void UpdateLookaheadCombinedNormalShuntSignalDeferred(TileIndex tile, Trackdir trackdir, int lookahead_position)
{
_deferred_lookahead_combined_normal_shunt_mode.push_back({ tile, trackdir, lookahead_position });
}
void FlushDeferredAspectUpdates() void FlushDeferredAspectUpdates()
{ {
/* Iterate in reverse order to reduce backtracking when updating the aspects of a new reservation */ /* Iterate in reverse order to reduce backtracking when updating the aspects of a new reservation */
@@ -1441,7 +1478,7 @@ void FlushDeferredAspectUpdates()
switch (GetTileType(tile)) { switch (GetTileType(tile)) {
case MP_RAILWAY: case MP_RAILWAY:
if (HasSignalOnTrackdir(tile, trackdir) && GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN && GetSignalAspect(tile, TrackdirToTrack(trackdir)) == 0) { if (HasSignalOnTrackdir(tile, trackdir) && GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN && GetSignalAspect(tile, TrackdirToTrack(trackdir)) == 0) {
uint8 aspect = GetForwardAspectFollowingTrackAndIncrement(tile, trackdir); uint8 aspect = GetForwardAspectFollowingTrackAndIncrement(tile, trackdir, IsRailCombinedNormalShuntSignalStyle(tile, TrackdirToTrack(trackdir)));
SetSignalAspect(tile, TrackdirToTrack(trackdir), aspect); SetSignalAspect(tile, TrackdirToTrack(trackdir), aspect);
PropagateAspectChange(tile, trackdir, aspect); PropagateAspectChange(tile, trackdir, aspect);
} }
@@ -1469,6 +1506,68 @@ void FlushDeferredAspectUpdates()
_deferred_aspect_updates.clear(); _deferred_aspect_updates.clear();
} }
void DetermineCombineNormalShuntModeWithLookahead(Train *v, TileIndex tile, Trackdir trackdir, int lookahead_position)
{
size_t count = v->lookahead->items.size();
for (size_t i = 0; i < count; i++) {
TrainReservationLookAheadItem &item = v->lookahead->items[i];
if (item.start == lookahead_position && item.type == TRLIT_SIGNAL && HasBit(item.data_aux, TRSLAI_COMBINED)) {
container_unordered_remove(_deferred_determine_combined_normal_shunt_mode, std::pair<TileIndex, Trackdir>({ tile, trackdir }));
for (size_t j = i + 1; j < count; j++) {
const TrainReservationLookAheadItem &ahead = v->lookahead->items[j];
if (ahead.type == TRLIT_SIGNAL) {
if (HasBit(item.data_aux, TRSLAI_COMBINED)) return;
if (!HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC) && !HasBit(item.data_aux, TRSLAI_NEXT_ONLY)) return;
}
}
if (IsRailDepotTile(v->lookahead->reservation_end_tile) || IsTileType(v->lookahead->reservation_end_tile, MP_TUNNELBRIDGE)) return;
CFollowTrackRail ft(v);
if (ft.Follow(v->lookahead->reservation_end_tile, v->lookahead->reservation_end_trackdir)) {
if (KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
/* reached a junction tile, shouldn't be reached, just assume normal route */
return;
}
TileIndex new_tile = ft.m_new_tile;
Trackdir new_trackdir = FindFirstTrackdir(ft.m_new_td_bits);
if (!(IsTileType(new_tile, MP_RAILWAY) && HasSignalOnTrackdir(new_tile, new_trackdir) && !IsNoEntrySignal(new_tile, TrackdirToTrack(new_trackdir)) &&
HasBit(_signal_style_masks.next_only, GetSignalStyle(new_tile, TrackdirToTrack(new_trackdir))))) {
/* Didn't find a shunt signal at the end of the reservation */
return;
}
} else {
/* end of line */
return;
}
/* shunt mode */
SetSignalAspect(tile, TrackdirToTrack(trackdir), 1);
SetBit(item.data_aux, TRSLAI_COMBINED_SHUNT);
return;
}
}
}
void FlushDeferredDetermineCombineNormalShuntMode(Train *v)
{
for (const auto &iter : _deferred_lookahead_combined_normal_shunt_mode) {
DetermineCombineNormalShuntModeWithLookahead(v, iter.tile, iter.trackdir, iter.lookahead_position);
}
_deferred_lookahead_combined_normal_shunt_mode.clear();
for (const auto &iter : _deferred_determine_combined_normal_shunt_mode) {
TileIndex tile = iter.first;
Trackdir trackdir = iter.second;
/* Reservation with no associated lookahead, default to a shunt route */
SetSignalAspect(tile, TrackdirToTrack(trackdir), 1);
}
_deferred_determine_combined_normal_shunt_mode.clear();
}
void UpdateAllSignalAspects() void UpdateAllSignalAspects()
{ {
for (TileIndex tile = 0; tile != MapSize(); ++tile) { for (TileIndex tile = 0; tile != MapSize(); ++tile) {
@@ -1479,8 +1578,8 @@ void UpdateAllSignalAspects()
if (HasSignalOnTrack(tile, track)) { if (HasSignalOnTrack(tile, track)) {
Trackdir trackdir = TrackToTrackdir(track); Trackdir trackdir = TrackToTrackdir(track);
if (!HasSignalOnTrackdir(tile, trackdir)) trackdir = ReverseTrackdir(trackdir); if (!HasSignalOnTrackdir(tile, trackdir)) trackdir = ReverseTrackdir(trackdir);
if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN && !IsRailSpecialSignalAspect(tile, track)) {
uint8 aspect = GetForwardAspectFollowingTrackAndIncrement(tile, trackdir); uint8 aspect = GetForwardAspectFollowingTrackAndIncrement(tile, trackdir, IsRailCombinedNormalShuntSignalStyle(tile, track));
SetSignalAspect(tile, track, aspect); SetSignalAspect(tile, track, aspect);
PropagateAspectChange(tile, trackdir, aspect); PropagateAspectChange(tile, trackdir, aspect);
} }
@@ -1613,6 +1712,12 @@ static bool DetermineExtraAspectsVariable()
if (HasBit(_new_signal_styles[i].style_flags, NSSF_OPPOSITE_SIDE)) { if (HasBit(_new_signal_styles[i].style_flags, NSSF_OPPOSITE_SIDE)) {
SetBit(_signal_style_masks.signal_opposite_side, i + 1); SetBit(_signal_style_masks.signal_opposite_side, i + 1);
} }
if (HasBit(_new_signal_styles[i].style_flags, NSSF_COMBINED_NORMAL_SHUNT)) {
SetBit(_signal_style_masks.combined_normal_shunt, i + 1);
SetBit(_signal_style_masks.no_tunnel_bridge, i + 1);
_new_signal_styles[i].electric_mask &= (1 << SIGTYPE_PBS) | (1 << SIGTYPE_PBS_ONEWAY) | (1 << SIGTYPE_NO_ENTRY);
_new_signal_styles[i].semaphore_mask &= (1 << SIGTYPE_PBS) | (1 << SIGTYPE_PBS_ONEWAY) | (1 << SIGTYPE_NO_ENTRY);
}
} }
for (uint i = _num_new_signal_styles; i < MAX_NEW_SIGNAL_STYLES; i++) { for (uint i = _num_new_signal_styles; i < MAX_NEW_SIGNAL_STYLES; i++) {
_new_signal_styles[i].lookahead_extra_aspects = new_extra_aspects; _new_signal_styles[i].lookahead_extra_aspects = new_extra_aspects;
@@ -1665,6 +1770,12 @@ void InitialiseExtraAspectsVariable()
DetermineExtraAspectsVariable(); DetermineExtraAspectsVariable();
} }
bool IsRailSpecialSignalAspect(TileIndex tile, Track track)
{
return _signal_style_masks.combined_normal_shunt != 0 && GetSignalAspect(tile, track) == 1 &&
HasBit(_signal_style_masks.combined_normal_shunt, GetSignalStyle(tile, track));
}
void UpdateSignalReserveThroughBit(TileIndex tile, Track track, bool update_signal) void UpdateSignalReserveThroughBit(TileIndex tile, Track track, bool update_signal)
{ {
bool reserve_through = false; bool reserve_through = false;

View File

@@ -33,6 +33,7 @@ struct SignalStyleMasks {
uint16 always_reserve_through = 0; uint16 always_reserve_through = 0;
uint16 no_tunnel_bridge = 0; uint16 no_tunnel_bridge = 0;
uint16 signal_opposite_side = 0; uint16 signal_opposite_side = 0;
uint16 combined_normal_shunt = 0;
}; };
extern SignalStyleMasks _signal_style_masks; extern SignalStyleMasks _signal_style_masks;
@@ -188,21 +189,24 @@ void UpdateSignalsInBufferIfOwnerNotAddable(Owner owner);
uint8 GetForwardAspectFollowingTrack(TileIndex tile, Trackdir trackdir); uint8 GetForwardAspectFollowingTrack(TileIndex tile, Trackdir trackdir);
uint8 GetSignalAspectGeneric(TileIndex tile, Trackdir trackdir, bool check_non_inc_style); uint8 GetSignalAspectGeneric(TileIndex tile, Trackdir trackdir, bool check_non_inc_style);
void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect); void PropagateAspectChange(TileIndex tile, Trackdir trackdir, uint8 aspect);
void UpdateAspectDeferred(TileIndex tile, Trackdir trackdir); void UpdateAspectDeferred(TileIndex tile, Trackdir trackdir, bool check_combined_normal_aspect);
void UpdateLookaheadCombinedNormalShuntSignalDeferred(TileIndex tile, Trackdir trackdir, int lookahead_position);
void FlushDeferredAspectUpdates(); void FlushDeferredAspectUpdates();
void FlushDeferredDetermineCombineNormalShuntMode(Train *v);
void UpdateAllSignalAspects(); void UpdateAllSignalAspects();
void UpdateExtraAspectsVariable(); void UpdateExtraAspectsVariable();
void InitialiseExtraAspectsVariable(); void InitialiseExtraAspectsVariable();
bool IsRailSpecialSignalAspect(TileIndex tile, Track track);
inline void AdjustSignalAspectIfNonIncStyle(TileIndex tile, Track track, uint8 &aspect) inline void AdjustSignalAspectIfNonIncStyle(TileIndex tile, Track track, uint8 &aspect)
{ {
extern void AdjustSignalAspectIfNonIncStyleIntl(TileIndex tile, Track track, uint8 &aspect); extern void AdjustSignalAspectIfNonIncStyleIntl(TileIndex tile, Track track, uint8 &aspect);
if (aspect > 0 && _signal_style_masks.non_aspect_inc != 0) AdjustSignalAspectIfNonIncStyleIntl(tile, track, aspect); if (aspect > 0 && (_signal_style_masks.non_aspect_inc != 0 || _signal_style_masks.combined_normal_shunt != 0)) AdjustSignalAspectIfNonIncStyleIntl(tile, track, aspect);
} }
inline uint8 GetForwardAspectFollowingTrackAndIncrement(TileIndex tile, Trackdir trackdir) inline uint8 GetForwardAspectFollowingTrackAndIncrement(TileIndex tile, Trackdir trackdir, bool combined_normal_mode = false)
{ {
return std::min<uint8>(GetForwardAspectFollowingTrack(tile, trackdir) + 1, GetMaximumSignalAspect()); return std::min<uint8>(GetForwardAspectFollowingTrack(tile, trackdir) + (combined_normal_mode ? 2 : 1), GetMaximumSignalAspect());
} }
void UpdateSignalReserveThroughBit(TileIndex tile, Track track, bool update_signal); void UpdateSignalReserveThroughBit(TileIndex tile, Track track, bool update_signal);

View File

@@ -279,6 +279,8 @@ class NIHVehicle : public NIHelper {
b += seprintf(b, lastof(buffer), "signal: target speed: %u, style: %u, flags:", item.data_id, item.data_aux >> 8); b += seprintf(b, lastof(buffer), "signal: target speed: %u, style: %u, flags:", item.data_id, item.data_aux >> 8);
if (HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC)) b += seprintf(b, lastof(buffer), "n"); if (HasBit(item.data_aux, TRSLAI_NO_ASPECT_INC)) b += seprintf(b, lastof(buffer), "n");
if (HasBit(item.data_aux, TRSLAI_NEXT_ONLY)) b += seprintf(b, lastof(buffer), "s"); if (HasBit(item.data_aux, TRSLAI_NEXT_ONLY)) b += seprintf(b, lastof(buffer), "s");
if (HasBit(item.data_aux, TRSLAI_COMBINED)) b += seprintf(b, lastof(buffer), "c");
if (HasBit(item.data_aux, TRSLAI_COMBINED_SHUNT)) b += seprintf(b, lastof(buffer), "X");
if (_settings_game.vehicle.realistic_braking_aspect_limited == TRBALM_ON && l.lookahead_end_position == item.start) { if (_settings_game.vehicle.realistic_braking_aspect_limited == TRBALM_ON && l.lookahead_end_position == item.start) {
b += seprintf(b, lastof(buffer), ", lookahead end"); b += seprintf(b, lastof(buffer), ", lookahead end");
print_braking_speed(item.start, 0, item.z_pos); print_braking_speed(item.start, 0, item.z_pos);

View File

@@ -3454,7 +3454,7 @@ static void SetTunnelBridgeEntranceSignalGreen(TileIndex tile)
MarkTunnelBridgeSignalDirty(tile, false); MarkTunnelBridgeSignalDirty(tile, false);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeEntranceSignalAspect(tile, 0); SetTunnelBridgeEntranceSignalAspect(tile, 0);
UpdateAspectDeferred(tile, GetTunnelBridgeEntranceTrackdir(tile)); UpdateAspectDeferred(tile, GetTunnelBridgeEntranceTrackdir(tile), false);
} }
} else if (_extra_aspects > 0) { } else if (_extra_aspects > 0) {
UpdateTunnelBridgeEntranceSignalAspect(tile); UpdateTunnelBridgeEntranceSignalAspect(tile);
@@ -4086,6 +4086,7 @@ static TileIndex CheckLongReservePbsTunnelBridgeOnTrackdir(Train* v, TileIndex t
} else { } else {
raw_free_tiles = GetAvailableFreeTilesInSignalledTunnelBridgeWithStartOffset(tile, end, v->lookahead->tunnel_bridge_reserved_tiles + 1); raw_free_tiles = GetAvailableFreeTilesInSignalledTunnelBridgeWithStartOffset(tile, end, v->lookahead->tunnel_bridge_reserved_tiles + 1);
ApplyAvailableFreeTunnelBridgeTiles(v->lookahead.get(), raw_free_tiles, tile, end); ApplyAvailableFreeTunnelBridgeTiles(v->lookahead.get(), raw_free_tiles, tile, end);
FlushDeferredDetermineCombineNormalShuntMode(v);
SetTrainReservationLookaheadEnd(v); SetTrainReservationLookaheadEnd(v);
} }
} else { } else {
@@ -4156,7 +4157,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
} else { } else {
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeExitSignalAspect(exit_tile, 0); SetTunnelBridgeExitSignalAspect(exit_tile, 0);
UpdateAspectDeferred(exit_tile, GetTunnelBridgeExitTrackdir(exit_tile)); UpdateAspectDeferred(exit_tile, GetTunnelBridgeExitTrackdir(exit_tile), false);
} }
MarkTileDirtyByTile(exit_tile, VMDF_NOT_MAP_MODE); MarkTileDirtyByTile(exit_tile, VMDF_NOT_MAP_MODE);
} }
@@ -4250,7 +4251,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
SetSignalStateByTrackdir(tile, changed_signal, SIGNAL_STATE_GREEN); SetSignalStateByTrackdir(tile, changed_signal, SIGNAL_STATE_GREEN);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetSignalAspect(tile, track, 0); SetSignalAspect(tile, track, 0);
UpdateAspectDeferred(tile, changed_signal); UpdateAspectDeferred(tile, changed_signal, true);
} }
} else if (!do_track_reservation) { } else if (!do_track_reservation) {
return track; return track;
@@ -5141,7 +5142,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
if (ok) { if (ok) {
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeExitSignalAspect(tile, 0); SetTunnelBridgeExitSignalAspect(tile, 0);
UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile)); UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile), false);
} }
mark_dirty = true; mark_dirty = true;
if (t->lookahead->reservation_end_tile == veh_orig_tile && t->lookahead->reservation_end_position - t->lookahead->current_position <= (int)TILE_SIZE) { if (t->lookahead->reservation_end_tile == veh_orig_tile && t->lookahead->reservation_end_position - t->lookahead->current_position <= (int)TILE_SIZE) {
@@ -5186,7 +5187,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_GREEN); SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_GREEN);
if (_extra_aspects > 0) { if (_extra_aspects > 0) {
SetTunnelBridgeExitSignalAspect(tile, 0); SetTunnelBridgeExitSignalAspect(tile, 0);
UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile)); UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile), false);
} }
mark_dirty = true; mark_dirty = true;
} }