Skip to content

Commit

Permalink
Fix #11528: Don't auto-build past tunnelbridge ends (#11606)
Browse files Browse the repository at this point in the history
  • Loading branch information
LordAro committed Feb 3, 2024
1 parent 8d62a8f commit 59f6c19
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 48 deletions.
34 changes: 22 additions & 12 deletions src/rail_cmd.cpp
Expand Up @@ -886,22 +886,32 @@ static CommandCost CmdRailTrackHelper(DoCommandFlag flags, TileIndex tile, TileI
if (ret.Failed()) return ret;

bool had_success = false;
bool under_tunnelbridge = false;
CommandCost last_error = CMD_ERROR;
for (;;) {
ret = remove ? Command<CMD_REMOVE_SINGLE_RAIL>::Do(flags, tile, TrackdirToTrack(trackdir)) : Command<CMD_BUILD_SINGLE_RAIL>::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals);

if (ret.Failed()) {
last_error = ret;
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) {
if (fail_on_obstacle) return last_error;
if (had_success) break; // Keep going if we haven't constructed any rail yet, skipping the start of the drag
/* Don't try to place rail between tunnelbridge ends */
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
under_tunnelbridge = !under_tunnelbridge;
} else if (!under_tunnelbridge) {
if (remove) {
ret = Command<CMD_REMOVE_SINGLE_RAIL>::Do(flags, tile, TrackdirToTrack(trackdir));
} else {
ret = Command<CMD_BUILD_SINGLE_RAIL>::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals);
}

/* Ownership errors are more important. */
if (last_error.GetErrorMessage() == STR_ERROR_OWNED_BY && remove) break;
} else {
had_success = true;
total_cost.AddCost(ret);
if (ret.Failed()) {
last_error = ret;
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) {
if (fail_on_obstacle) return last_error;
if (had_success) break; // Keep going if we haven't constructed any rail yet, skipping the start of the drag
}

/* Ownership errors are more important. */
if (last_error.GetErrorMessage() == STR_ERROR_OWNED_BY && remove) break;
} else {
had_success = true;
total_cost.AddCost(ret);
}
}

if (tile == end_tile) break;
Expand Down
78 changes: 42 additions & 36 deletions src/road_cmd.cpp
Expand Up @@ -1007,49 +1007,55 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex end_tile, TileIndex
bool had_bridge = false;
bool had_tunnel = false;
bool had_success = false;
bool under_tunnelbridge = false;

/* Start tile is the first tile clicked by the user. */
for (;;) {
RoadBits bits = AxisToRoadBits(axis);

/* Determine which road parts should be built. */
if (!is_ai && start_tile != end_tile) {
/* Only build the first and last roadbit if they can connect to something. */
if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
bits = DiagDirToRoadBits(ReverseDiagDir(dir));
} else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
bits = DiagDirToRoadBits(dir);
/* Don't try to place road between tunnelbridge ends */
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
under_tunnelbridge = !under_tunnelbridge;
} else if (!under_tunnelbridge) {
RoadBits bits = AxisToRoadBits(axis);

/* Determine which road parts should be built. */
if (!is_ai && start_tile != end_tile) {
/* Only build the first and last roadbit if they can connect to something. */
if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
bits = DiagDirToRoadBits(ReverseDiagDir(dir));
} else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
bits = DiagDirToRoadBits(dir);
}
} else {
/* Road parts only have to be built at the start tile or at the end tile. */
if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
}
} else {
/* Road parts only have to be built at the start tile or at the end tile. */
if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
}

CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, 0);
if (ret.Failed()) {
last_error = ret;
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
if (is_ai) return last_error;
if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
}
} else {
had_success = true;
/* Only pay for the upgrade on one side of the bridges and tunnels */
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
if (IsBridge(tile)) {
if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
cost.AddCost(ret);
}
had_bridge = true;
} else { // IsTunnel(tile)
if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
cost.AddCost(ret);
}
had_tunnel = true;
CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, 0);
if (ret.Failed()) {
last_error = ret;
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
if (is_ai) return last_error;
if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
}
} else {
cost.AddCost(ret);
had_success = true;
/* Only pay for the upgrade on one side of the bridges and tunnels */
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
if (IsBridge(tile)) {
if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
cost.AddCost(ret);
}
had_bridge = true;
} else { // IsTunnel(tile)
if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
cost.AddCost(ret);
}
had_tunnel = true;
}
} else {
cost.AddCost(ret);
}
}
}

Expand Down

0 comments on commit 59f6c19

Please sign in to comment.