diff --git a/src/lang/english.txt b/src/lang/english.txt index e8f26e201a..ff19eab31d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5002,6 +5002,7 @@ STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Another STR_ERROR_TUNNEL_THROUGH_MAP_BORDER :{WHITE}Tunnel would end out of the map STR_ERROR_UNABLE_TO_EXCAVATE_LAND :{WHITE}Unable to excavate land for other end of tunnel STR_ERROR_TUNNEL_TOO_LONG :{WHITE}... tunnel too long +STR_ERROR_TUNNEL_RAMP_TOO_SHORT :{WHITE}... Ramp too short, tunnels under water have minimal three tiles at the begin and end. # Object related errors STR_ERROR_TOO_MANY_OBJECTS :{WHITE}... too many objects diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index 1e9888e489..0b82c60efe 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -270,7 +270,7 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin } } /* Check if tunnel would take damage */ - if (direction == -1 && IsTunnelInWay(tile, z_min)) { + if (direction == -1 && IsTunnelInWay(tile, z_min, false)) { _terraform_err_tile = tile; // highlight the tile above the tunnel return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE); } diff --git a/src/tunnel_base.h b/src/tunnel_base.h index f03325eabc..66b0871a36 100644 --- a/src/tunnel_base.h +++ b/src/tunnel_base.h @@ -24,6 +24,7 @@ struct Tunnel : TunnelPool::PoolItem<&_tunnel_pool> { TileIndex tile_n; // North tile of tunnel. TileIndex tile_s; // South tile of tunnel. + bool is_chunnel; Tunnel(TileIndex tile_n = INVALID_TILE) : tile_n(tile_n) {} ~Tunnel(); diff --git a/src/tunnel_map.cpp b/src/tunnel_map.cpp index 1771b1d82b..358e83efc9 100644 --- a/src/tunnel_map.cpp +++ b/src/tunnel_map.cpp @@ -44,9 +44,10 @@ TileIndex GetOtherTunnelEnd(TileIndex tile) * Is there a tunnel in the way in any direction? * @param tile the tile to search from. * @param z the 'z' to search on. + * @param not_allowed Only terra forming does not search between tunnel portals. * @return true if and only if there is a tunnel. */ -bool IsTunnelInWay(TileIndex tile, int z) +bool IsTunnelInWay(TileIndex tile, int z, bool not_allowed) { uint x = TileX(tile); uint y = TileY(tile); @@ -61,6 +62,12 @@ bool IsTunnelInWay(TileIndex tile, int z) if (TileY(t->tile_n) != y || (int)TileHeight(t->tile_n) != z) continue; // dir DIAGDIR_SW } + if (t->is_chunnel > not_allowed) { + /* Only if tunnel was build over water terraforming is allowed between portals. */ + TileIndexDiff delta = GetTunnelBridgeDirection(t->tile_n) == DIAGDIR_SE ? TileOffsByDiagDir(DIAGDIR_SE) * 4 : 4; // 4 tiles ramp. + if (tile < t->tile_n + delta || t->tile_s - delta < tile) return true; + continue; + } return true; } return false; diff --git a/src/tunnel_map.h b/src/tunnel_map.h index 3621f54eb6..5d77822c6a 100644 --- a/src/tunnel_map.h +++ b/src/tunnel_map.h @@ -51,7 +51,7 @@ static inline TunnelID GetTunnelIndex(TileIndex t) } TileIndex GetOtherTunnelEnd(TileIndex); -bool IsTunnelInWay(TileIndex, int z); +bool IsTunnelInWay(TileIndex, int z, bool not_allowed = true); /** * Makes a road tunnel entrance diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 599bfcf758..67d76b4c8c 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -670,6 +670,10 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, int tiles_coef = 3; /* Number of tiles from start of tunnel */ int tiles = 0; + /* flag for chunnels. */ + bool is_chunnel = false; + /* Number of chunnel head tiles. */ + int head_tiles = 1; /* Number of tiles at which the cost increase coefficient per tile is halved */ int tiles_bump = 25; @@ -691,6 +695,9 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, /* A shore was found so pass the water and find a proper shore tile that potentially * could have a tunnel portal behind. */ + is_chunnel = true; + if (head_tiles < 4 && is_chunnel) break; // Not enough lead way to go under water. + head_tiles = 0; for (;;) { if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER); @@ -704,10 +711,10 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, tiles++; } } - if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z)) { + if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z, false)) { return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY); } - + head_tiles++; tiles++; } /* The cost of the digging. */ @@ -730,6 +737,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG); + if (head_tiles < 4 && is_chunnel) return_cmd_error(STR_ERROR_TUNNEL_RAMP_TOO_SHORT); + if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER); /* Clear the tile in any case */ @@ -777,6 +786,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, if (!Tunnel::CanAllocateItem()) return CMD_ERROR; Tunnel *t = new Tunnel(tn); t->tile_s = ts; + t->is_chunnel = is_chunnel; if (transport_type == TRANSPORT_RAIL) { if (!IsTunnelTile(start_tile) && c != NULL) c->infrastructure.rail[railtype] += num_pieces;