Changeset - r28655:c8bf53648e55
[Not reviewed]
master
0 2 0
Charles Pigott - 3 months ago 2024-02-03 10:18:10
charlespigott@googlemail.com
Fix #11528: Don't auto-build past tunnelbridge ends (#11606)
2 files changed with 66 insertions and 50 deletions:
0 comments (0 inline, 0 general)
src/rail_cmd.cpp
Show inline comments
 
@@ -886,22 +886,32 @@ static CommandCost CmdRailTrackHelper(Do
 
	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;
src/road_cmd.cpp
Show inline comments
 
@@ -1007,49 +1007,55 @@ CommandCost CmdBuildLongRoad(DoCommandFl
 
	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);
 
			}
 
		} 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;
 
		/* 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 {
 
				cost.AddCost(ret);
 
				/* 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;
 
					}
 
				} else {
 
					cost.AddCost(ret);
 
				}
 
			}
 
		}
 

	
0 comments (0 inline, 0 general)