summaryrefslogtreecommitdiff
path: root/src/rail_cmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rail_cmd.cpp')
-rw-r--r--src/rail_cmd.cpp129
1 files changed, 110 insertions, 19 deletions
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index e362a132b..327d8f998 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -41,6 +41,7 @@
typedef SmallVector<Train *, 16> TrainList;
RailtypeInfo _railtypes[RAILTYPE_END];
+TileIndex _rail_track_endtile; ///< The end of a rail track; as hidden return from the rail build/remove command for GUI purposes.
assert_compile(sizeof(_original_railtypes) <= sizeof(_railtypes));
@@ -557,6 +558,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
}
cost.AddCost(RailBuildCost(railtype));
+ _rail_track_endtile = tile;
return cost;
}
@@ -701,6 +703,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (v != NULL) TryPathReserve(v, true);
}
+ _rail_track_endtile = tile;
return cost;
}
@@ -1011,9 +1014,12 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (sigtype > SIGTYPE_LAST) return CMD_ERROR;
if (cycle_start > cycle_stop || cycle_stop > SIGTYPE_LAST) return CMD_ERROR;
- /* You can only build signals on plain rail tiles, and the selected track must exist */
- if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) ||
- !HasTrack(tile, track)) {
+ /* You can only build signals on plain rail tiles or tunnel/bridges, and the selected track must exist */
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return CMD_ERROR;
+ CommandCost ret = EnsureNoTrainOnTrack(GetOtherTunnelBridgeEnd(tile), track);
+ //if (ret.Failed()) return ret;
+ } else if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
}
/* Protect against invalid signal copying */
@@ -1022,6 +1028,53 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
CommandCost ret = CheckTileOwnership(tile);
if (ret.Failed()) return ret;
+ CommandCost cost;
+ /* handle signals simulation on tunnel/bridge. */
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ TileIndex tile_exit = GetOtherTunnelBridgeEnd(tile);
+ cost = CommandCost();
+ if (!HasWormholeSignals(tile)) { // toggle signal zero costs.
+ if (p2 != 12) cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_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);
+ } else {
+ ClrBitTunnelBridgeSignal(tile_exit);
+ ClrBitTunnelBridgeExit(tile);
+ SetBitTunnelBridgeExit(tile_exit);
+ SetBitTunnelBridgeSignal(tile);
+ }
+ } else{
+ /* Create one direction tunnel/bridge if required. */
+ if (p2 == 0) {
+ SetBitTunnelBridgeSignal(tile);
+ SetBitTunnelBridgeExit(tile_exit);
+ } else if (p2 == 4 || p2 == 8) {
+ DiagDirection tbdir = GetTunnelBridgeDirection(tile);
+ /* 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))) {
+ SetBitTunnelBridgeSignal(tile);
+ SetBitTunnelBridgeExit(tile_exit);
+ } else {
+ SetBitTunnelBridgeSignal(tile_exit);
+ SetBitTunnelBridgeExit(tile);
+ }
+ }
+ }
+ MarkTileDirtyByTile(tile);
+ MarkTileDirtyByTile(tile_exit);
+ AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company);
+ YapfNotifyTrackLayoutChange(tile, track);
+ }
+ return cost;
+ }
+
{
/* See if this is a valid track combination for signals, (ie, no overlap) */
TrackBits trackbits = GetTrackBits(tile);
@@ -1038,7 +1091,6 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1,
/* you can not convert a signal if no signal is on track */
if (convert_signal && !HasSignalOnTrack(tile, track)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
- CommandCost cost;
if (!HasSignalOnTrack(tile, track)) {
/* build new signals */
cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
@@ -1196,6 +1248,7 @@ static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal
return true;
case MP_TUNNELBRIDGE: {
+ if (!remove && HasWormholeSignals(tile)) return false;
TileIndex orig_tile = tile; // backup old value
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
@@ -1307,7 +1360,8 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
bool had_success = false;
for (;;) {
/* only build/remove signals with the specified density */
- if (remove || minimise_gaps || signal_ctr % signal_density == 0) {
+
+ if (remove || minimise_gaps || signal_ctr % signal_density == 0 || IsTileType(tile, MP_TUNNELBRIDGE)) {
uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
SB(p1, 3, 1, mode);
SB(p1, 4, 1, semaphores);
@@ -1343,13 +1397,20 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
/* Collect cost. */
if (!test_only) {
- /* Be user-friendly and try placing signals as much as possible */
- if (ret.Succeeded()) {
- had_success = true;
- total_cost.AddCost(ret);
- last_used_ctr = last_suitable_ctr;
- last_suitable_tile = INVALID_TILE;
+ /* Be user-friendly and try placing signals as much as possible */
+ if (ret.Succeeded()) {
+ had_success = true;
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ if ((!autofill && GetTunnelBridgeDirection(tile) == TrackdirToExitdir(trackdir)) ||
+ (autofill && GetTunnelBridgeDirection(tile) != TrackdirToExitdir(trackdir))) {
+ total_cost.AddCost(ret);
+ }
} else {
+ total_cost.AddCost(ret);
+ }
+ last_used_ctr = last_suitable_ctr;
+ last_suitable_tile = INVALID_TILE;
+ } else {
/* The "No railway" error is the least important one. */
if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK ||
last_error.GetErrorMessage() == INVALID_STRING_ID) {
@@ -1420,22 +1481,48 @@ CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1,
CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
Track track = Extract<Track, 0, 3>(p1);
+ Money cost = _price[PR_CLEAR_SIGNALS];
- if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
- return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
- }
- if (!HasSignalOnTrack(tile, track)) {
- return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ TileIndex end = GetOtherTunnelBridgeEnd(tile);
+ if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+ if (!HasWormholeSignals(tile)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
+
+ cost *= ((GetTunnelBridgeLength(tile, end) + 4) >> 2);
+
+ CommandCost ret = EnsureNoTrainOnTrack(GetOtherTunnelBridgeEnd(tile), track);
+ //if (ret.Failed()) return ret;
+ } else {
+ if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+ return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+ }
+ if (!HasSignalOnTrack(tile, track)) {
+ return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
+ }
+ CommandCost ret = EnsureNoTrainOnTrack(tile, track);
+ //if (ret.Failed()) return ret;
}
/* Only water can remove signals from anyone */
if (_current_company != OWNER_WATER) {
- CommandCost ret = CheckTileOwnership(tile);
- if (ret.Failed()) return ret;
}
/* Do it? */
if (flags & DC_EXEC) {
+
+ if (HasWormholeSignals(tile)) { // handle tunnel/bridge signals.
+ TileIndex end = GetOtherTunnelBridgeEnd(tile);
+ ClrBitTunnelBridgeExit(tile);
+ ClrBitTunnelBridgeExit(end);
+ ClrBitTunnelBridgeSignal(tile);
+ ClrBitTunnelBridgeSignal(end);
+ _m[tile].m2 = 0;
+ _m[end].m2 = 0;
+ MarkTileDirtyByTile(tile);
+ MarkTileDirtyByTile(end);
+ return CommandCost(EXPENSES_CONSTRUCTION, cost);
+ }
+
Train *v = NULL;
if (HasReservedTracks(tile, TrackToTrackBits(track))) {
v = GetTrainForReservation(tile, track);
@@ -1471,7 +1558,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1
MarkTileDirtyByTile(tile);
}
- return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_SIGNALS]);
+ return CommandCost(EXPENSES_CONSTRUCTION, cost);
}
/**
@@ -1946,6 +2033,7 @@ static void DrawTrackFence_WE_1(const TileInfo *ti, SpriteID base_image)
ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
}
+
/**
* Draw fence at northern side of track.
*/
@@ -2483,11 +2571,14 @@ static Foundation GetFoundation_Track(TileIndex tile, Slope tileh)
return IsPlainRail(tile) ? GetRailFoundation(tileh, GetTrackBits(tile)) : FlatteningFoundation(tileh);
}
+
static void TileLoop_Track(TileIndex tile)
{
RailGroundType old_ground = GetRailGroundType(tile);
RailGroundType new_ground;
+ ReduceStuckCounter(tile);
+
if (old_ground == RAIL_GROUND_WATER) {
TileLoop_Water(tile);
return;