Merge branch 'signal_tunnels_bridges-sx' into jgrpp

# Conflicts:
#	src/saveload/afterload.cpp
#	src/saveload/extended_ver_sl.cpp
#	src/signal.cpp
#	src/train_cmd.cpp
pull/6/merge
Jonathan G Rennison 8 years ago
commit d08b162119

@ -364,7 +364,7 @@ protected:
if (IsTunnel(m_new_tile)) {
if (!m_is_tunnel) {
DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_new_tile);
if (tunnel_enterdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) {
if (tunnel_enterdir != m_exitdir) {
m_err = EC_NO_WAY;
return false;
}
@ -372,7 +372,7 @@ protected:
} else { // IsBridge(m_new_tile)
if (!m_is_bridge) {
DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile);
if (ramp_enderdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) {
if (ramp_enderdir != m_exitdir) {
m_err = EC_NO_WAY;
return false;
}

@ -943,6 +943,10 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
break;
}
}
if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(dst_tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(dst_tile)) == dst_trackdir) {
/* Entering a signalled bridge/tunnel from the wrong side, equivalent to encountering a one-way signal from the wrong side */
break;
}
{
/* We've found ourselves a neighbour :-) */
AyStarNode *neighbour = &aystar->neighbours[i];

@ -360,6 +360,10 @@ public:
}
}
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == trackdir) {
/* Entering a signalled bridge/tunnel from the wrong side, equivalent to encountering a one-way signal from the wrong side */
n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
}
return cost;
}

@ -143,6 +143,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
case MP_TUNNELBRIDGE:
if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetTunnelBridgeReservationTrackBits(tile)) {
SetTunnelBridgeReservation(tile, true);
if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, true);
return true;
}
break;
@ -195,7 +196,10 @@ void UnreserveRailTrack(TileIndex tile, Track t)
break;
case MP_TUNNELBRIDGE:
if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) SetTunnelBridgeReservation(tile, false);
if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
SetTunnelBridgeReservation(tile, false);
if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false);
}
break;
default:
@ -264,6 +268,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
if (IsRailDepotTile(tile)) break;
/* Non-pbs signal? Reservation can't continue. */
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) break;
if (IsTileType(tile, MP_TUNNELBRIDGE) && HasWormholeSignals(tile)) break;
}
return PBSTileInfo(tile, trackdir, false);
@ -332,7 +337,7 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
if (ftoti.best != NULL) *train_on_res = ftoti.best->First();
}
}
if (*train_on_res == NULL && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) {
if (*train_on_res == NULL && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE) && !HasWormholeSignals(ftoti.res.tile)) {
/* The target tile is a bridge/tunnel, also check the other end tile. */
FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
if (ftoti.best != NULL) *train_on_res = ftoti.best->First();
@ -447,6 +452,12 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
if (IsTunnelBridgeEntrance(tile)) {
return true;
}
}
/* Check next tile. For performance reasons, we check for 90 degree turns ourself. */
CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes);
@ -507,6 +518,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
/* Not reserved and depot or not a pbs signal -> free. */
if (IsRailDepotTile(tile)) return true;
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) return true;
if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && IsTunnelBridgeEntrance(tile)) return true;
/* Check the next tile, if it's a PBS signal, it has to be free as well. */
CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes);

@ -1058,21 +1058,46 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
TileIndex tile_exit = GetOtherTunnelBridgeEnd(tile);
cost = CommandCost();
bool flip_variant = false;
bool is_pbs = (sigtype == SIGTYPE_PBS) || (sigtype == SIGTYPE_PBS_ONEWAY);
if (!HasWormholeSignals(tile)) { // toggle signal zero costs.
if (convert_signal) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
if (p2 != 12) cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] * ((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1
} else {
if (HasBit(p1, 17)) return CommandCost();
if ((p2 != 0 && (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)) ||
(convert_signal && (ctrl_pressed || (sigvar == SIG_SEMAPHORE) != IsTunnelBridgeSemaphore(tile)))) {
flip_variant = true;
cost = CommandCost(EXPENSES_CONSTRUCTION, (_price[PR_BUILD_SIGNALS] + _price[PR_CLEAR_SIGNALS]) *
((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1
}
}
if (flags & DC_EXEC) {
if (p2 == 0 && HasWormholeSignals(tile)) { // Toggle signal if already signals present.
if (IsTunnelBridgeEntrance(tile)) {
ClrBitTunnelBridgeSignal(tile);
ClrBitTunnelBridgeExit(tile_exit);
SetBitTunnelBridgeExit(tile);
SetBitTunnelBridgeSignal(tile_exit);
if (convert_signal) {
if (flip_variant) {
SetTunnelBridgeSemaphore(tile, !IsTunnelBridgeSemaphore(tile));
SetTunnelBridgeSemaphore(tile_exit, IsTunnelBridgeSemaphore(tile));
}
if (!ctrl_pressed) {
SetTunnelBridgePBS(tile, is_pbs);
SetTunnelBridgePBS(tile_exit, is_pbs);
}
} else if (ctrl_pressed) {
SetTunnelBridgePBS(tile, !IsTunnelBridgePBS(tile));
SetTunnelBridgePBS(tile_exit, IsTunnelBridgePBS(tile));
} else {
ClrBitTunnelBridgeSignal(tile_exit);
ClrBitTunnelBridgeExit(tile);
SetBitTunnelBridgeExit(tile_exit);
SetBitTunnelBridgeSignal(tile);
if (IsTunnelBridgeEntrance(tile)) {
ClrBitTunnelBridgeSignal(tile);
ClrBitTunnelBridgeExit(tile_exit);
SetBitTunnelBridgeExit(tile);
SetBitTunnelBridgeSignal(tile_exit);
} else {
ClrBitTunnelBridgeSignal(tile_exit);
ClrBitTunnelBridgeExit(tile);
SetBitTunnelBridgeExit(tile_exit);
SetBitTunnelBridgeSignal(tile);
}
}
} else {
/* Create one direction tunnel/bridge if required. */
@ -1084,14 +1109,24 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
/* If signal only on one side build accoringly one-way tunnel/bridge. */
if ((p2 == 8 && (tbdir == DIAGDIR_NE || tbdir == DIAGDIR_SE)) ||
(p2 == 4 && (tbdir == DIAGDIR_SW || tbdir == DIAGDIR_NW))) {
ClrBitTunnelBridgeExit(tile);
ClrBitTunnelBridgeSignal(tile_exit);
SetBitTunnelBridgeSignal(tile);
SetBitTunnelBridgeExit(tile_exit);
} else {
ClrBitTunnelBridgeSignal(tile);
ClrBitTunnelBridgeExit(tile_exit);
SetBitTunnelBridgeSignal(tile_exit);
SetBitTunnelBridgeExit(tile);
}
}
SetTunnelBridgeSemaphore(tile, sigvar == SIG_SEMAPHORE);
SetTunnelBridgeSemaphore(tile_exit, sigvar == SIG_SEMAPHORE);
SetTunnelBridgePBS(tile, is_pbs);
SetTunnelBridgePBS(tile_exit, is_pbs);
}
if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile) && !HasTunnelBridgeReservation(tile)) SetTunnelBridgeExitGreen(tile, false);
if (IsTunnelBridgeExit(tile_exit) && IsTunnelBridgePBS(tile_exit) && !HasTunnelBridgeReservation(tile_exit)) SetTunnelBridgeExitGreen(tile_exit, false);
MarkBridgeOrTunnelDirty(tile);
AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile));
AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile));

@ -18,6 +18,7 @@
#include "track_func.h"
#include "tile_map.h"
#include "signal_type.h"
#include "tunnelbridge_map.h"
/** Different types of Rail-related tiles */
@ -479,8 +480,15 @@ static inline bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td)
*/
static inline bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td)
{
return IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)) &&
!HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td));
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)) &&
!HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
return true;
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) &&
DiagDirToDiagTrackdir(GetTunnelBridgeDirection(tile)) == td) {
return true;
}
return false;
}
/**

@ -3181,6 +3181,18 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 1)) {
/* set the semaphore bit to match what it would have been in v1 */
/* clear the PBS bit, update the end signal state */
for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && HasWormholeSignals(t)) {
SetTunnelBridgeSemaphore(t, _cur_year < _settings_client.gui.semaphore_build_before);
SetTunnelBridgePBS(t, false);
UpdateSignalsOnSegment(t, INVALID_DIAGDIR, GetTileOwner(t));
}
}
}
/* Station acceptance is some kind of cache */
if (IsSavegameVersionBefore(127)) {
Station *st;

@ -54,7 +54,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", NULL, NULL, NULL },
{ XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 1, 1, "timetable_start_ticks", NULL, NULL, NULL },
{ XSLFI_TOWN_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "town_cargo_adj", NULL, NULL, NULL },
{ XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 1, 1, "signal_tunnel_bridge", NULL, NULL, NULL },
{ XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 2, 2, "signal_tunnel_bridge", NULL, NULL, NULL },
{ XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 3, 3, "improved_breakdowns", NULL, NULL, NULL },
{ XSLFI_TT_WAIT_IN_DEPOT, XSCF_NULL, 1, 1, "tt_wait_in_depot", NULL, NULL, NULL },
{ XSLFI_AUTO_TIMETABLE, XSCF_NULL, 3, 3, "auto_timetables", NULL, NULL, NULL },

@ -414,11 +414,23 @@ static SigInfo ExploreSegment(Owner owner)
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
}
if (IsTunnelBridgeExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) {
info.flags |= SF_FULL;
return info;
}
enterdir = dir;
exitdir = ReverseDiagDir(dir);
tile += TileOffsByDiagDir(exitdir); // just skip to next tile
} else { // NOT incoming from the wormhole!
if (ReverseDiagDir(enterdir) != dir) continue;
if (IsTunnelBridgeExit(tile)) {
if (IsTunnelBridgePBS(tile)) {
info.flags |= SF_PBS;
} else if (!_tbuset.Add(tile, INVALID_TRACKDIR)) {
info.flags |= SF_FULL;
return info;
}
}
if (!(info.flags & SF_TRAIN)) {
if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
if (!(info.flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) {
@ -469,6 +481,17 @@ static void UpdateSignalsAroundSegment(SigInfo info)
Track track;
while (_tbuset.Get(&tile, &trackdir)) {
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile)) {
if (IsTunnelBridgePBS(tile)) continue;
bool old_state = IsTunnelBridgeExitGreen(tile);
bool new_state = !(info.flags & SF_TRAIN);
if (old_state != new_state) {
SetTunnelBridgeExitGreen(tile, new_state);
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
}
continue;
}
assert(HasSignalOnTrackdir(tile, trackdir));
track = TrackdirToTrack(trackdir);

@ -2376,6 +2376,12 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir
}
}
static void UnreserveBridgeTunnelTile(TileIndex tile)
{
SetTunnelBridgeReservation(tile, false);
if (IsTunnelBridgeExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitGreen(tile, false);
}
/**
* Clear the reservation of \a tile that was just left by a wagon on \a track_dir.
* @param v %Train owning the reservation.
@ -2392,10 +2398,16 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_
TileIndex end = GetOtherTunnelBridgeEnd(tile);
bool free = TunnelBridgeIsFree(tile, end, v).Succeeded();
if (free) {
if (HasWormholeSignals(tile)) {
UnreserveBridgeTunnelTile(tile);
HandleLastTunnelBridgeSignals(tile, end, dir, free);
if (_settings_client.gui.show_track_reservation) {
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
}
} else if (free) {
/* Free the reservation only if no other train is on the tiles. */
SetTunnelBridgeReservation(tile, false);
SetTunnelBridgeReservation(end, false);
UnreserveBridgeTunnelTile(tile);
UnreserveBridgeTunnelTile(end);
if (_settings_client.gui.show_track_reservation) {
if (IsBridge(tile)) {
@ -2406,7 +2418,12 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_
}
}
}
if (HasWormholeSignals(tile)) HandleLastTunnelBridgeSignals(tile, end, dir, free);
} else if (GetTunnelBridgeDirection(tile) == dir && HasWormholeSignals(tile)) {
/* cancelling reservation of entry ramp, due to reverse */
UnreserveBridgeTunnelTile(tile);
if (_settings_client.gui.show_track_reservation) {
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
}
}
} else if (IsRailStationTile(tile)) {
TileIndex new_tile = TileAddByDiagDir(tile, dir);
@ -2935,6 +2952,12 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
}
}
if (IsTileType(v->tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(v->tile) &&
DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile)) == v->track) {
// prevent any attempt to reserve the wrong way onto a tunnel/bridge exit
return false;
}
Vehicle *other_train = NULL;
PBSTileInfo origin = FollowTrainReservation(v, &other_train);
/* The path we are driving on is already blocked by some other train.
@ -3167,6 +3190,11 @@ static TrainMovedChangeSignalEnum TrainMovedChangeSignal(Train* v, TileIndex til
if (HasLongReservePbsSignalOnTrackdir(v, tile, trackdir)) return CHANGED_LR_PBS;
}
}
if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeExit(tile) && GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
if (UpdateSignalsOnSegment(tile, dir, GetTileOwner(tile)) == SIGSEG_PBS) {
return CHANGED_NORMAL_TO_PBS_BLOCK;
}
}
return CHANGED_NOTHING;
}
@ -3208,7 +3236,7 @@ uint Train::Crash(bool flooded)
if (IsTileType(v->tile, MP_TUNNELBRIDGE)) {
/* ClearPathReservation will not free the wormhole exit
* if the train has just entered the wormhole. */
SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(v->tile), false);
UnreserveBridgeTunnelTile(GetOtherTunnelBridgeEnd(v->tile));
}
}
@ -3402,6 +3430,23 @@ static bool IsToCloseBehindTrain(Vehicle *v, TileIndex tile, bool check_endtile)
return false;
}
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
{
TileIndex veh_orig = t->tile;
t->tile = tile;
CFollowTrackRail ft(GetTileOwner(tile), GetRailTypeInfo(t->railtype)->compatible_railtypes);
if (ft.Follow(tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) {
TrackdirBits reserved = ft.m_new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.m_new_tile));
if (reserved == TRACKDIR_BIT_NONE) {
/* next tile is not reserved, so reserve the exit tile */
SetTunnelBridgeReservation(tile, true);
}
}
bool ok = TryPathReserve(t);
t->tile = veh_orig;
return ok;
}
/** Simulate signals in tunnel - bridge. */
static bool CheckTrainStayInWormHole(Train *t, TileIndex tile)
{
@ -3413,8 +3458,20 @@ static bool CheckTrainStayInWormHole(Train *t, TileIndex tile)
ToggleBit(t->flags, VRF_REVERSING);
return true;
}
SigSegState seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner);
if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !TryPathReserve(t))) {
SigSegState seg_state = (_settings_game.pf.reserve_paths || IsTunnelBridgePBS(tile)) ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner);
if (seg_state != SIGSEG_PBS) {
CFollowTrackRail ft(GetTileOwner(tile), GetRailTypeInfo(t->railtype)->compatible_railtypes);
if (ft.Follow(tile, DiagDirToDiagTrackdir(ReverseDiagDir(GetTunnelBridgeDirection(tile))))) {
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
Trackdir td = FindFirstTrackdir(ft.m_new_td_bits);
if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) {
/* immediately after the exit, there is a PBS signal, switch to PBS mode */
seg_state = SIGSEG_PBS;
}
}
}
}
if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !CheckTrainStayInWormHolePathReserve(t, tile))) {
t->vehstatus |= VS_TRAIN_SLOWING;
t->cur_speed = 0;
return true;
@ -3724,7 +3781,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
} else {
/* Handle signal simulation on tunnel/bridge. */
TileIndex old_tile = TileVirtXY(v->x_pos, v->y_pos);
if (old_tile != gp.new_tile && HasWormholeSignals(v->tile) && (v->IsFrontEngine() || v->Next() == NULL)){
if (old_tile != gp.new_tile && HasWormholeSignals(v->tile) && (v->IsFrontEngine() || v->Next() == NULL)) {
if (old_tile == v->tile) {
if (v->IsFrontEngine() && v->force_proceed == 0 && IsTunnelBridgeExit(v->tile)) goto invalid_rail;
/* Entered wormhole set counters. */
@ -3763,6 +3820,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
v->x_pos = gp.x;
v->y_pos = gp.y;
UpdateSignalsOnSegment(old_tile, INVALID_DIAGDIR, v->owner);
UnreserveBridgeTunnelTile(old_tile);
}
}
if (distance == 0) v->load_unload_ticks++;

@ -1167,27 +1167,44 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti)
case DIAGDIR_NW: position = 3; break;
}
uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side][position].x;
uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][position].y;
SignalType type = SIGTYPE_NORMAL;
bool is_green;
bool show_exit;
if (IsTunnelBridgeExit(ti->tile)) {
is_green = IsTunnelBridgeExitGreen(ti->tile);
show_exit = true;
position ^= 1;
if (IsTunnelBridgePBS(ti->tile)) type = SIGTYPE_PBS_ONEWAY;
} else {
is_green = IsTunnelBridgeWithSignGreen(ti->tile);
show_exit = false;
}
uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side != show_exit][position ^ show_exit].x;
uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side != show_exit][position ^ show_exit].y;
uint z = ti->z;
if (ti->tileh == SLOPE_FLAT && side == show_exit && dir == DIAGDIR_SE) z += 2;
if (ti->tileh == SLOPE_FLAT && side != show_exit && dir == DIAGDIR_SW) z += 2;
if (ti->tileh != SLOPE_FLAT && IsBridge(ti->tile)) z += 8; // sloped bridge head
SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
SignalVariant variant = IsTunnelBridgeSemaphore(ti->tile) ? SIG_SEMAPHORE : SIG_ELECTRIC;
SpriteID sprite;
if (variant == SIG_ELECTRIC) {
if (variant == SIG_ELECTRIC && type == SIGTYPE_NORMAL) {
/* Normal electric signals are picked from original sprites. */
sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + IsTunnelBridgeWithSignGreen(ti->tile));
sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + is_green);
} else {
/* All other signals are picked from add on sprites. */
sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + IsTunnelBridgeWithSignGreen(ti->tile));
sprite = SPR_SIGNALS_BASE + ((type - 1) * 16 + variant * 64 + (position << 1) + is_green) + (IsSignalSpritePBS(type) ? 64 : 0);
}
AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR);
}
/* Draws a signal on tunnel / bridge entrance tile. */
static void DrawBrigeSignalOnMiddelPart(const TileInfo *ti, TileIndex bridge_start_tile, uint z)
static void DrawBrigeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_start_tile, uint z)
{
uint bridge_signal_position = 0;
@ -1222,7 +1239,7 @@ static void DrawBrigeSignalOnMiddelPart(const TileInfo *ti, TileIndex bridge_sta
uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][position].y;
z += 5;
SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
SignalVariant variant = IsTunnelBridgeSemaphore(bridge_start_tile) ? SIG_SEMAPHORE : SIG_ELECTRIC;
SpriteID sprite;
@ -1355,7 +1372,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
/* Draw signals for tunnel. */
if (IsTunnelBridgeEntrance(ti->tile)) DrawTunnelBridgeRampSignal(ti);
if (HasWormholeSignals(ti->tile)) DrawTunnelBridgeRampSignal(ti);
DrawBridgeMiddle(ti);
} else { // IsBridge(ti->tile)
@ -1601,7 +1618,8 @@ void DrawBridgeMiddle(const TileInfo *ti)
}
}
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)
&& !HasWormholeSignals(rampnorth)) {
if (rti->UsesOverlay()) {
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
@ -1616,7 +1634,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
DrawCatenaryOnBridge(ti);
}
if (HasWormholeSignals(rampsouth)) {
IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddelPart(ti, rampnorth, z): DrawBrigeSignalOnMiddelPart(ti, rampsouth, z);
IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddlePart(ti, rampnorth, z): DrawBrigeSignalOnMiddlePart(ti, rampsouth, z);
}
}

@ -213,6 +213,40 @@ static inline bool IsTunnelBridgeExit(TileIndex t)
return !HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6);
}
static inline bool IsTunnelBridgeExitGreen(TileIndex t)
{
assert(IsTunnelBridgeExit(t));
return HasBit(_me[t].m6, 0);
}
static inline void SetTunnelBridgeExitGreen(TileIndex t, bool green)
{
assert(IsTunnelBridgeExit(t));
SB(_me[t].m6, 0, 1, green ? 1 : 0);
}
static inline bool IsTunnelBridgeSemaphore(TileIndex t)
{
assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t));
return HasBit(_me[t].m6, 1);
}
static inline void SetTunnelBridgeSemaphore(TileIndex t, bool is_semaphore)
{
assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t));
SB(_me[t].m6, 1, 1, is_semaphore ? 1 : 0);
}
static inline bool IsTunnelBridgePBS(TileIndex t)
{
assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t));
return HasBit(_me[t].m6, 6);
}
static inline void SetTunnelBridgePBS(TileIndex t, bool is_pbs)
{
assert(IsTileType(t, MP_TUNNELBRIDGE) && HasWormholeSignals(t));
SB(_me[t].m6, 6, 1, is_pbs ? 1 : 0);
}
#endif /* TUNNELBRIDGE_MAP_H */

Loading…
Cancel
Save