Chunnel: Prevent chunnels from intersecting with each other.
This commit is contained in:
@@ -270,7 +270,7 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check if tunnel would take damage */
|
/* Check if tunnel would take damage */
|
||||||
if (direction == -1 && IsTunnelInWay(tile, z_min, true)) {
|
if (direction == -1 && IsTunnelInWay(tile, z_min, ITIWF_IGNORE_CHUNNEL)) {
|
||||||
_terraform_err_tile = tile; // highlight the tile above the tunnel
|
_terraform_err_tile = tile; // highlight the tile above the tunnel
|
||||||
return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE);
|
return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE);
|
||||||
}
|
}
|
||||||
|
@@ -103,14 +103,17 @@ TileIndex GetOtherTunnelEnd(TileIndex tile)
|
|||||||
return t->tile_n == tile ? t->tile_s : t->tile_n;
|
return t->tile_n == tile ? t->tile_s : t->tile_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsTunnelInWaySingleAxis(TileIndex tile, int z, bool chunnel_allowed, bool y_axis, TileIndexDiff tile_diff)
|
static inline bool IsTunnelInWaySingleAxis(TileIndex tile, int z, IsTunnelInWayFlags flags, bool y_axis, TileIndexDiff tile_diff)
|
||||||
{
|
{
|
||||||
const auto tunnels = tunnel_axis_height_index.equal_range(GetTunnelAxisHeightCacheKey(tile, z, y_axis));
|
const auto tunnels = tunnel_axis_height_index.equal_range(GetTunnelAxisHeightCacheKey(tile, z, y_axis));
|
||||||
for (auto it = tunnels.first; it != tunnels.second; ++it) {
|
for (auto it = tunnels.first; it != tunnels.second; ++it) {
|
||||||
const Tunnel *t = it->second;
|
const Tunnel *t = it->second;
|
||||||
if (t->tile_n > tile || tile > t->tile_s) continue;
|
if (t->tile_n > tile || tile > t->tile_s) continue;
|
||||||
|
|
||||||
if (t->is_chunnel && chunnel_allowed) {
|
if (!t->is_chunnel && (flags & ITIWF_CHUNNEL_ONLY)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (t->is_chunnel && (flags & ITIWF_IGNORE_CHUNNEL)) {
|
||||||
/* Only if tunnel was built over water is terraforming is allowed between portals. */
|
/* Only if tunnel was built over water is terraforming is allowed between portals. */
|
||||||
const TileIndexDiff delta = tile_diff * 4; // 4 tiles ramp.
|
const TileIndexDiff delta = tile_diff * 4; // 4 tiles ramp.
|
||||||
if (tile < t->tile_n + delta || t->tile_s - delta < tile) return true;
|
if (tile < t->tile_n + delta || t->tile_s - delta < tile) return true;
|
||||||
@@ -128,7 +131,7 @@ static inline bool IsTunnelInWaySingleAxis(TileIndex tile, int z, bool chunnel_a
|
|||||||
* @param chunnel_allowed True if chunnel mid-parts are allowed, used when terraforming.
|
* @param chunnel_allowed True if chunnel mid-parts are allowed, used when terraforming.
|
||||||
* @return true if and only if there is a tunnel.
|
* @return true if and only if there is a tunnel.
|
||||||
*/
|
*/
|
||||||
bool IsTunnelInWay(TileIndex tile, int z, bool chunnel_allowed)
|
bool IsTunnelInWay(TileIndex tile, int z, IsTunnelInWayFlags flags)
|
||||||
{
|
{
|
||||||
return IsTunnelInWaySingleAxis(tile, z, chunnel_allowed, false, 1) || IsTunnelInWaySingleAxis(tile, z, chunnel_allowed, true, TileOffsByDiagDir(DIAGDIR_SE));
|
return IsTunnelInWaySingleAxis(tile, z, flags, false, 1) || IsTunnelInWaySingleAxis(tile, z, flags, true, TileOffsByDiagDir(DIAGDIR_SE));
|
||||||
}
|
}
|
||||||
|
@@ -56,7 +56,16 @@ static inline TunnelID GetTunnelIndex(TileIndex t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TileIndex GetOtherTunnelEnd(TileIndex);
|
TileIndex GetOtherTunnelEnd(TileIndex);
|
||||||
bool IsTunnelInWay(TileIndex, int z, bool chunnel_allowed = false);
|
|
||||||
|
/** Flags for miscellaneous industry tile specialities */
|
||||||
|
enum IsTunnelInWayFlags {
|
||||||
|
ITIWF_NONE = 0,
|
||||||
|
ITIWF_IGNORE_CHUNNEL = 1 << 0, ///< Chunnel mid-parts are ignored, used when terraforming.
|
||||||
|
ITIWF_CHUNNEL_ONLY = 1 << 1, ///< Only check for chunnels
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_AS_BIT_SET(IsTunnelInWayFlags)
|
||||||
|
|
||||||
|
bool IsTunnelInWay(TileIndex, int z, IsTunnelInWayFlags flags = ITIWF_NONE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the index of tunnel tile.
|
* Set the index of tunnel tile.
|
||||||
|
@@ -740,7 +740,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||||||
head_tiles = 0;
|
head_tiles = 0;
|
||||||
found_tunnel_tile = INVALID_TILE;
|
found_tunnel_tile = INVALID_TILE;
|
||||||
}
|
}
|
||||||
if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z, true)) {
|
if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z, ITIWF_IGNORE_CHUNNEL)) {
|
||||||
if (found_tunnel_tile == INVALID_TILE || is_chunnel) { // Remember the first or the last when we pass a tunnel.
|
if (found_tunnel_tile == INVALID_TILE || is_chunnel) { // Remember the first or the last when we pass a tunnel.
|
||||||
found_tunnel_tile = end_tile;
|
found_tunnel_tile = end_tile;
|
||||||
head_tiles = 0;
|
head_tiles = 0;
|
||||||
@@ -749,6 +749,26 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||||||
head_tiles++;
|
head_tiles++;
|
||||||
tiles++;
|
tiles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_chunnel && !_cheats.crossing_tunnels.value) {
|
||||||
|
/*
|
||||||
|
* Chunnel check: second pass
|
||||||
|
*
|
||||||
|
* Make sure that we don't intersect with any other chunnels
|
||||||
|
*/
|
||||||
|
|
||||||
|
TileIndex check_tile = start_tile;
|
||||||
|
for (;;) {
|
||||||
|
check_tile += delta;
|
||||||
|
if (check_tile == end_tile) break;
|
||||||
|
|
||||||
|
if (IsTunnelInWay(check_tile, start_z, ITIWF_CHUNNEL_ONLY)) {
|
||||||
|
_build_tunnel_endtile = check_tile;
|
||||||
|
return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The cost of the digging. */
|
/* The cost of the digging. */
|
||||||
for (int i = tiles; i > 0; i--) {
|
for (int i = tiles; i > 0; i--) {
|
||||||
if (tiles == tiles_bump) {
|
if (tiles == tiles_bump) {
|
||||||
|
Reference in New Issue
Block a user