diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 386b1b5498..06d65d0770 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -179,35 +179,17 @@ bool CheckBridge_Stuff(BridgeType bridge_type, uint bridge_len, DoCommandFlag fl */ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - BridgeType bridge_type; RailType railtype = INVALID_RAILTYPE; RoadTypes roadtypes = ROADTYPES_NONE; - uint x; - uint y; - uint sx; - uint sy; - TileIndex tile_start; - TileIndex tile_end; - Slope tileh_start; - Slope tileh_end; - uint z_start; - uint z_end; - TileIndex tile; - TileIndexDiff delta; - uint bridge_len; - Axis direction; CommandCost cost(EXPENSES_CONSTRUCTION); - CommandCost ret; - bool replace_bridge = false; - BridgeType replaced_bridge_type; - TransportType transport_type; + Owner owner; /* unpack parameters */ - bridge_type = GB(p2, 0, 8); + BridgeType bridge_type = GB(p2, 0, 8); if (p1 >= MapSize()) return CMD_ERROR; - transport_type = (TransportType)GB(p2, 15, 2); + TransportType transport_type = (TransportType)GB(p2, 15, 2); /* type of bridge */ switch (transport_type) { @@ -225,42 +207,42 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u break; default: - /* Airports don't have tunnels. */ + /* Airports don't have bridges. */ return CMD_ERROR; } + TileIndex tile_start = p1; + TileIndex tile_end = end_tile; - x = TileX(end_tile); - y = TileY(end_tile); - sx = TileX(p1); - sy = TileY(p1); + if (tile_start == tile_end) { + return_cmd_error(STR_ERROR_CANNOT_START_AND_END_ON); + } - /* check if valid, and make sure that (x,y) are smaller than (sx,sy) */ - if (x == sx) { - if (y == sy) return_cmd_error(STR_ERROR_CANNOT_START_AND_END_ON); + Axis direction; + if (TileX(tile_start) == TileX(tile_end)) { direction = AXIS_Y; - if (y > sy) Swap(y, sy); - } else if (y == sy) { + } else if (TileY(tile_start) == TileY(tile_end)) { direction = AXIS_X; - if (x > sx) Swap(x, sx); } else { return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN); } - bridge_len = sx + sy - x - y - 1; + if (tile_end < tile_start) Swap(tile_start, tile_end); + + uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end); if (transport_type != TRANSPORT_WATER) { /* set and test bridge length, availability */ if (!CheckBridge_Stuff(bridge_type, bridge_len, flags)) return_cmd_error(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE); } /* retrieve landscape height and ensure it's on land */ - tile_start = TileXY(x, y); - tile_end = TileXY(sx, sy); if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) { return_cmd_error(STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH); } - tileh_start = GetTileSlope(tile_start, &z_start); - tileh_end = GetTileSlope(tile_end, &z_end); + uint z_start; + uint z_end; + Slope tileh_start = GetTileSlope(tile_start, &z_start); + Slope tileh_end = GetTileSlope(tile_end, &z_end); CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start); CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end, &z_end); @@ -301,8 +283,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u } cost.AddCost((bridge_len + 1) * _price.clear_bridge); // The cost of clearing the current bridge. - replace_bridge = true; - replaced_bridge_type = GetBridgeType(tile_start); + owner = GetTileOwner(tile_start); /* Do not remove road types when upgrading a bridge */ roadtypes |= GetRoadTypes(tile_start); @@ -312,7 +293,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER); /* Try and clear the start landscape */ - ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return ret; cost = ret; @@ -331,13 +312,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u cost.AddCost(terraform_cost_south); if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); - } - if (!replace_bridge) { TileIndex Heads[] = {tile_start, tile_end}; - int i; - - for (i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { if (MayHaveBridgeAbove(Heads[i])) { if (IsBridgeAbove(Heads[i])) { TileIndex north_head = GetNorthernBridgeEnd(Heads[i]); @@ -350,12 +327,63 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u } } } + + TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); + for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) { + if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_BRIDGE_TOO_LOW_FOR_TERRAIN); + + if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) { + /* Disallow crossing bridges for the time being */ + return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + } + + switch (GetTileType(tile)) { + case MP_WATER: + if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below; + break; + + case MP_RAILWAY: + if (!IsPlainRail(tile)) goto not_valid_below; + break; + + case MP_ROAD: + if (IsRoadDepot(tile)) goto not_valid_below; + break; + + case MP_TUNNELBRIDGE: + if (IsTunnel(tile)) break; + if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below; + if (z_start < GetBridgeHeight(tile)) goto not_valid_below; + break; + + case MP_UNMOVABLE: + if (!IsOwnedLand(tile)) goto not_valid_below; + break; + + case MP_CLEAR: + break; + + default: + not_valid_below:; + /* try and clear the middle landscape */ + ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (CmdFailed(ret)) return ret; + cost.AddCost(ret); + break; + } + + if (flags & DC_EXEC) { + SetBridgeMiddle(tile, direction); + MarkTileDirtyByTile(tile); + } + } + + owner = _current_company; } /* do the drill? */ if (flags & DC_EXEC) { DiagDirection dir = AxisToDiagDir(direction); - Owner owner = replace_bridge ? GetTileOwner(tile_start) : _current_company; switch (transport_type) { case TRANSPORT_RAIL: @@ -375,63 +403,11 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u default: NOT_REACHED(); - break; } MarkTileDirtyByTile(tile_start); MarkTileDirtyByTile(tile_end); } - delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); - for (tile = tile_start + delta; tile != tile_end; tile += delta) { - if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_BRIDGE_TOO_LOW_FOR_TERRAIN); - - if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) && !replace_bridge) { - /* Disallow crossing bridges for the time being */ - return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); - } - - switch (GetTileType(tile)) { - case MP_WATER: - if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below; - break; - - case MP_RAILWAY: - if (!IsPlainRail(tile)) goto not_valid_below; - break; - - case MP_ROAD: - if (IsRoadDepot(tile)) goto not_valid_below; - break; - - case MP_TUNNELBRIDGE: - if (IsTunnel(tile)) break; - if (replace_bridge) break; - if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below; - if (z_start < GetBridgeHeight(tile)) goto not_valid_below; - break; - - case MP_UNMOVABLE: - if (!IsOwnedLand(tile)) goto not_valid_below; - break; - - case MP_CLEAR: - break; - - default: -not_valid_below:; - /* try and clear the middle landscape */ - ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (CmdFailed(ret)) return ret; - cost.AddCost(ret); - break; - } - - if (flags & DC_EXEC) { - SetBridgeMiddle(tile, direction); - MarkTileDirtyByTile(tile); - } - } - if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) { Track track = AxisToTrack(direction); AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_company); @@ -466,16 +442,8 @@ not_valid_below:; */ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TileIndexDiff delta; - TileIndex end_tile; - DiagDirection direction; - Slope start_tileh; - Slope end_tileh; TransportType transport_type = (TransportType)GB(p1, 9, 1); - uint start_z; - uint end_z; CommandCost cost(EXPENSES_CONSTRUCTION); - CommandCost ret; _build_tunnel_endtile = 0; if (transport_type == TRANSPORT_RAIL) { @@ -485,13 +453,15 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR; } - start_tileh = GetTileSlope(start_tile, &start_z); - direction = GetInclinedSlopeDirection(start_tileh); + uint start_z; + uint end_z; + Slope start_tileh = GetTileSlope(start_tile, &start_z); + DiagDirection direction = GetInclinedSlopeDirection(start_tileh); if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL); if (IsWaterTile(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER); - ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + CommandCost ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return ret; /* XXX - do NOT change 'ret' in the loop, as it is used as the price @@ -499,7 +469,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, * cost before the loop will yield different costs depending on start- * position, because of increased-cost-by-length: 'cost += cost >> 3' */ - delta = TileOffsByDiagDir(direction); + TileIndexDiff delta = TileOffsByDiagDir(direction); DiagDirection tunnel_in_way_dir; if (DiagDirToAxis(direction) == AXIS_Y) { tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE; @@ -507,15 +477,16 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW; } - end_tile = start_tile; + TileIndex end_tile = start_tile; - /** Tile shift coeficient. Will decrease for very long tunnels to avoid exponential growth of price*/ + /* Tile shift coeficient. Will decrease for very long tunnels to avoid exponential growth of price*/ int tiles_coef = 3; - /** Number of tiles from start of tunnel */ + /* Number of tiles from start of tunnel */ int tiles = 0; - /** Number of tiles at which the cost increase coefficient per tile is halved */ + /* Number of tiles at which the cost increase coefficient per tile is halved */ int tiles_bump = 25; + Slope end_tileh; for (;;) { end_tile += delta; if (!IsValidTile(end_tile)) return_cmd_error(STR_TUNNEL_THROUGH_MAP_BORDER);