mirror of https://github.com/OpenTTD/OpenTTD
Change: Path signals now show green on junction-less tracks by default (#12857)
parent
9965cd9151
commit
ddf6f33a8a
|
@ -57,6 +57,8 @@ private:
|
||||||
Trackdir m_res_fail_td; ///< The trackdir where the reservation failed
|
Trackdir m_res_fail_td; ///< The trackdir where the reservation failed
|
||||||
TileIndex m_origin_tile; ///< Tile our reservation will originate from
|
TileIndex m_origin_tile; ///< Tile our reservation will originate from
|
||||||
|
|
||||||
|
std::vector<std::pair<TileIndex, Trackdir>> m_signals_set_to_red; ///< List of signals turned red during a path reservation.
|
||||||
|
|
||||||
bool FindSafePositionProc(TileIndex tile, Trackdir td)
|
bool FindSafePositionProc(TileIndex tile, Trackdir td)
|
||||||
{
|
{
|
||||||
if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
|
if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
|
||||||
|
@ -88,8 +90,9 @@ private:
|
||||||
/** Try to reserve a single track/platform. */
|
/** Try to reserve a single track/platform. */
|
||||||
bool ReserveSingleTrack(TileIndex tile, Trackdir td)
|
bool ReserveSingleTrack(TileIndex tile, Trackdir td)
|
||||||
{
|
{
|
||||||
|
Trackdir rev_td = ReverseTrackdir(td);
|
||||||
if (IsRailStationTile(tile)) {
|
if (IsRailStationTile(tile)) {
|
||||||
if (!ReserveRailStationPlatform(tile, TrackdirToExitdir(ReverseTrackdir(td)))) {
|
if (!ReserveRailStationPlatform(tile, TrackdirToExitdir(rev_td))) {
|
||||||
/* Platform could not be reserved, undo. */
|
/* Platform could not be reserved, undo. */
|
||||||
m_res_fail_tile = tile;
|
m_res_fail_tile = tile;
|
||||||
m_res_fail_td = td;
|
m_res_fail_td = td;
|
||||||
|
@ -101,6 +104,13 @@ private:
|
||||||
m_res_fail_td = td;
|
m_res_fail_td = td;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Green path signal opposing the path? Turn to red. */
|
||||||
|
if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
|
||||||
|
m_signals_set_to_red.emplace_back(tile, rev_td);
|
||||||
|
SetSignalStateByTrackdir(tile, rev_td, SIGNAL_STATE_RED);
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tile != m_res_dest || td != m_res_dest_td;
|
return tile != m_res_dest || td != m_res_dest_td;
|
||||||
|
@ -159,6 +169,7 @@ public:
|
||||||
/* Don't bother if the target is reserved. */
|
/* Don't bother if the target is reserved. */
|
||||||
if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false;
|
if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false;
|
||||||
|
|
||||||
|
m_signals_set_to_red.clear();
|
||||||
for (Node *node = m_res_node; node->m_parent != nullptr; node = node->m_parent) {
|
for (Node *node = m_res_node; node->m_parent != nullptr; node = node->m_parent) {
|
||||||
node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
|
node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
|
||||||
if (m_res_fail_tile != INVALID_TILE) {
|
if (m_res_fail_tile != INVALID_TILE) {
|
||||||
|
@ -171,6 +182,11 @@ public:
|
||||||
fail_node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::UnreserveSingleTrack);
|
fail_node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::UnreserveSingleTrack);
|
||||||
} while (fail_node != node && (fail_node = fail_node->m_parent) != nullptr);
|
} while (fail_node != node && (fail_node = fail_node->m_parent) != nullptr);
|
||||||
|
|
||||||
|
/* Re-instate green path signals we turned to red. */
|
||||||
|
for (auto [sig_tile, td] : m_signals_set_to_red) {
|
||||||
|
SetSignalStateByTrackdir(sig_tile, td, SIGNAL_STATE_GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "viewport_func.h"
|
#include "viewport_func.h"
|
||||||
#include "train.h"
|
#include "train.h"
|
||||||
#include "company_base.h"
|
#include "company_base.h"
|
||||||
|
#include "pbs.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
@ -251,6 +252,9 @@ enum SigFlags {
|
||||||
SF_GREEN2 = 1 << 4, ///< two or more green exits found
|
SF_GREEN2 = 1 << 4, ///< two or more green exits found
|
||||||
SF_FULL = 1 << 5, ///< some of buffers was full, do not continue
|
SF_FULL = 1 << 5, ///< some of buffers was full, do not continue
|
||||||
SF_PBS = 1 << 6, ///< pbs signal found
|
SF_PBS = 1 << 6, ///< pbs signal found
|
||||||
|
SF_SPLIT = 1 << 7, ///< track merge/split found
|
||||||
|
SF_ENTER = 1 << 8, ///< signal entering the block found
|
||||||
|
SF_ENTER2 = 1 << 9, ///< two or more signals entering the block found
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_ENUM_AS_BIT_SET(SigFlags)
|
DECLARE_ENUM_AS_BIT_SET(SigFlags)
|
||||||
|
@ -305,6 +309,9 @@ static SigFlags ExploreSegment(Owner owner)
|
||||||
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
|
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this a track merge or split? */
|
||||||
|
if (!HasAtMostOneBit(tracks)) flags |= SF_SPLIT;
|
||||||
|
|
||||||
if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
|
if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
|
||||||
Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
|
Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
|
||||||
if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
|
if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
|
||||||
|
@ -315,11 +322,11 @@ static SigFlags ExploreSegment(Owner owner)
|
||||||
* ANY conventional signal in REVERSE direction
|
* ANY conventional signal in REVERSE direction
|
||||||
* (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
|
* (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
|
||||||
if (HasSignalOnTrackdir(tile, reversedir)) {
|
if (HasSignalOnTrackdir(tile, reversedir)) {
|
||||||
if (IsPbsSignal(sig)) {
|
if (IsPbsSignal(sig)) flags |= SF_PBS;
|
||||||
flags |= SF_PBS;
|
if (flags & SF_ENTER) flags |= SF_ENTER2;
|
||||||
} else if (!_tbuset.Add(tile, reversedir)) {
|
flags |= SF_ENTER;
|
||||||
return flags | SF_FULL;
|
|
||||||
}
|
if (!_tbuset.Add(tile, reversedir)) return flags | SF_FULL;
|
||||||
}
|
}
|
||||||
if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS;
|
if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS;
|
||||||
|
|
||||||
|
@ -411,13 +418,20 @@ static void UpdateSignalsAroundSegment(SigFlags flags)
|
||||||
while (_tbuset.Get(&tile, &trackdir)) {
|
while (_tbuset.Get(&tile, &trackdir)) {
|
||||||
assert(HasSignalOnTrackdir(tile, trackdir));
|
assert(HasSignalOnTrackdir(tile, trackdir));
|
||||||
|
|
||||||
SignalType sig = GetSignalType(tile, TrackdirToTrack(trackdir));
|
Track track = TrackdirToTrack(trackdir);
|
||||||
|
SignalType sig = GetSignalType(tile, track);
|
||||||
SignalState newstate = SIGNAL_STATE_GREEN;
|
SignalState newstate = SIGNAL_STATE_GREEN;
|
||||||
|
|
||||||
|
/* Signal state of reserved path signals is handled by the reserve/unreserve process. */
|
||||||
|
if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
|
||||||
|
|
||||||
/* determine whether the new state is red */
|
/* determine whether the new state is red */
|
||||||
if (flags & SF_TRAIN) {
|
if (flags & SF_TRAIN) {
|
||||||
/* train in the segment */
|
/* train in the segment */
|
||||||
newstate = SIGNAL_STATE_RED;
|
newstate = SIGNAL_STATE_RED;
|
||||||
|
} else if (IsPbsSignal(sig) && (flags & (SF_SPLIT | SF_ENTER2))) {
|
||||||
|
/* Turn path signals red if the segment has a junction or more than one way in. */
|
||||||
|
newstate = SIGNAL_STATE_RED;
|
||||||
} else {
|
} else {
|
||||||
/* is it a bidir combo? - then do not count its other signal direction as exit */
|
/* is it a bidir combo? - then do not count its other signal direction as exit */
|
||||||
if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
|
if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
|
||||||
|
|
|
@ -2430,6 +2430,9 @@ void FreeTrainTrackReservation(const Train *v)
|
||||||
SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
|
SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
|
||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
}
|
}
|
||||||
|
} else if (HasPbsSignalOnTrackdir(tile, ReverseTrackdir(td))) {
|
||||||
|
/* Reservation passes an opposing path signal. Mark signal for update to re-establish the proper default state. */
|
||||||
|
AddSideToSignalBuffer(tile, TrackdirToExitdir(ReverseTrackdir(td)), v->owner);
|
||||||
} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
|
} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2440,6 +2443,8 @@ void FreeTrainTrackReservation(const Train *v)
|
||||||
|
|
||||||
free_tile = true;
|
free_tile = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateSignalsInBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t _initial_tile_subcoord[6][4][3] = {
|
static const uint8_t _initial_tile_subcoord[6][4][3] = {
|
||||||
|
@ -2481,6 +2486,8 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
|
|
||||||
CFollowTrackRail ft(v);
|
CFollowTrackRail ft(v);
|
||||||
|
|
||||||
|
std::vector<std::pair<TileIndex, Trackdir>> signals_set_to_red;
|
||||||
|
|
||||||
TileIndex tile = origin.tile;
|
TileIndex tile = origin.tile;
|
||||||
Trackdir cur_td = origin.trackdir;
|
Trackdir cur_td = origin.trackdir;
|
||||||
while (ft.Follow(tile, cur_td)) {
|
while (ft.Follow(tile, cur_td)) {
|
||||||
|
@ -2518,14 +2525,28 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
tile = ft.m_new_tile;
|
tile = ft.m_new_tile;
|
||||||
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||||
|
|
||||||
|
Trackdir rev_td = ReverseTrackdir(cur_td);
|
||||||
if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
|
if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
|
||||||
bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg);
|
bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg);
|
||||||
if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break;
|
if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break;
|
||||||
|
/* Green path signal opposing the path? Turn to red. */
|
||||||
|
if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
|
||||||
|
signals_set_to_red.emplace_back(tile, rev_td);
|
||||||
|
SetSignalStateByTrackdir(tile, rev_td, SIGNAL_STATE_RED);
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
/* Safe position is all good, path valid and okay. */
|
/* Safe position is all good, path valid and okay. */
|
||||||
return PBSTileInfo(tile, cur_td, true);
|
return PBSTileInfo(tile, cur_td, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryReserveRailTrack(tile, TrackdirToTrack(cur_td))) break;
|
if (!TryReserveRailTrack(tile, TrackdirToTrack(cur_td))) break;
|
||||||
|
|
||||||
|
/* Green path signal opposing the path? Turn to red. */
|
||||||
|
if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
|
||||||
|
signals_set_to_red.emplace_back(tile, rev_td);
|
||||||
|
SetSignalStateByTrackdir(tile, rev_td, SIGNAL_STATE_RED);
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
|
if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
|
||||||
|
@ -2553,6 +2574,11 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
UnreserveRailTrack(tile, TrackdirToTrack(cur_td));
|
UnreserveRailTrack(tile, TrackdirToTrack(cur_td));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Re-instate green signals we turned to red. */
|
||||||
|
for (auto [sig_tile, td] : signals_set_to_red) {
|
||||||
|
SetSignalStateByTrackdir(sig_tile, td, SIGNAL_STATE_GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
/* Path invalid. */
|
/* Path invalid. */
|
||||||
return PBSTileInfo();
|
return PBSTileInfo();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue