diff options
author | Erich Eckner <git@eckner.net> | 2021-01-03 22:08:37 +0100 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2021-01-03 22:08:37 +0100 |
commit | 14db446f7428ae55907b15b10e89539a7eefc6ab (patch) | |
tree | ca770ea23c6697178366c7751a0ceded3723e428 | |
parent | eda62ccedb226e760a41bf0f5af379b0add6b072 (diff) | |
download | archlinuxewe-14db446f7428ae55907b15b10e89539a7eefc6ab.tar.xz |
openttd-git: fix chunnel.patch
-rw-r--r-- | openttd-git/PKGBUILD | 13 | ||||
-rw-r--r-- | openttd-git/chunnel-pre.patch | 12 | ||||
-rw-r--r-- | openttd-git/chunnel.patch | 914 |
3 files changed, 924 insertions, 15 deletions
diff --git a/openttd-git/PKGBUILD b/openttd-git/PKGBUILD index 4c1d5542e..bd7a052c2 100644 --- a/openttd-git/PKGBUILD +++ b/openttd-git/PKGBUILD @@ -2,7 +2,7 @@ pkgname=openttd-git pkgver=29779.8596b43b2 _commit=${pkgver#*.} -pkgrel=1 +pkgrel=2 pkgdesc="A FOSS clone of Transport Tycoon Deluxe." arch=('x86_64' 'i686' 'pentium4') url="http://www.openttd.org" @@ -43,6 +43,7 @@ backup=() options=() source=( "${pkgname}::git://github.com/OpenTTD/OpenTTD.git#commit=${_commit}" + "chunnel-pre.patch" "chunnel.patch" "signaltunnel.patch" "sloped-stations.patch" @@ -50,7 +51,8 @@ source=( 'opntitle.dat' ) sha512sums=('SKIP' - 'a6cf640d876aa1e2d20ec9242a602bca8a3e2dfabe036b36bf71872d47ab06d668c24d175c54c5f6e54d3c135ebcbcf3c09b5d762fddceb15f2cc87baad9d76f' + 'fa238b9ea9a2d334bdabcbc667b87eae87748d510d6d2bb3308f5186b6b613b7a50623e42c075cd4261cfd4aa4a6822902d7d6536e1805a1ac00a6e885bc9ae7' + '74283b8adb001a010aa05a8cee33b620371544e2909317f4c7156852e4ea440cdf8793dbe8957d646734ee309fdb5924915e0d967d78d43329ea4fc211e7e8ef' '497f395320edff647dd58c53abc451f706db9934fc847c95ecbbb33d519f67fe94ecd913e13bd7d770320370ea088b675e6583e8b59b69e2d3ee587a62ad2261' '11c87d30824bca5738e46c14422c622cdfe4d7e55a5b3a4fe5e77a0a14ceee742bfa8f6c0e8212e9b38c2a1d1db3a4f525c7a70a0b0ed03751dee2539d3da929' 'f18a389800e5641ebc55d4322089d97a851125ae6d19ff944d3648b3b603128fe0fcb7ba2210cbd13ac8a0839003144299c217b994bdc0bc5e601fbff63308d2' @@ -92,11 +94,16 @@ prepare() { ' cmake/scripts/FindVersion.cmake # for _p in "${srcdir}/"{signaltunnel,sloped-stations,underground,chunnel}.patch; do - for _p in "${srcdir}/"{signaltunnel,underground,chunnel}.patch; do + for _p in "${srcdir}/"{signaltunnel,underground}.patch; do >&2 echo "patching ${_p##*/} ..." patch -p1 -i "${_p}" >&2 echo "... ok" done + ( + cd "${srcdir}" + patch -p2 -i "chunnel-pre.patch" -o - + ) \ + | patch -p1 } build() { diff --git a/openttd-git/chunnel-pre.patch b/openttd-git/chunnel-pre.patch new file mode 100644 index 000000000..9b42f5a93 --- /dev/null +++ b/openttd-git/chunnel-pre.patch @@ -0,0 +1,12 @@ +diff --git a/openttd-git/chunnel.patch b/openttd-git/chunnel.patch +index 33ab7405..6ad137ae 100644 +--- a/openttd-git/chunnel.patch ++++ b/openttd-git/chunnel.patch +@@ -1018,6 +1018,7 @@ index e014944a9f..cb6239f597 100644 + const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF + + while (v != nullptr) { ++ if (LayerIndex(v->tile) == dpi->layer) + - if (!(v->vehstatus & VS_HIDDEN) && + + if (v->IsDrawn() && + l <= v->coord.right && diff --git a/openttd-git/chunnel.patch b/openttd-git/chunnel.patch index c26ea894f..33ab74054 100644 --- a/openttd-git/chunnel.patch +++ b/openttd-git/chunnel.patch @@ -1,8 +1,178 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index bbe66b7645..7fb18d527a 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -442,6 +442,7 @@ add_files( + tree_cmd.cpp + tree_gui.cpp + tree_map.h ++ tunnel_base.h + tunnel_map.cpp + tunnel_map.h + tunnelbridge.h +diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp +index 0f1915c964..0a734a5b55 100644 +--- a/src/ground_vehicle.cpp ++++ b/src/ground_vehicle.cpp +@@ -11,6 +11,8 @@ + #include "train.h" + #include "roadveh.h" + #include "depot_map.h" ++#include "tunnel_base.h" ++#include "slope_type.h" + + #include "safeguards.h" + +@@ -203,6 +205,69 @@ bool GroundVehicle<T, Type>::IsChainInDepot() const + return true; + } + ++/** ++ * Updates vehicle's Z inclination inside a wormhole, where applicable. ++ */ ++template <class T, VehicleType Type> ++void GroundVehicle<T, Type>::UpdateZPositionInWormhole() ++{ ++ if (!IsTunnel(this->tile)) return; ++ ++ const Tunnel *t = Tunnel::GetByTile(this->tile); ++ if (!t->is_chunnel) return; ++ ++ TileIndex pos_tile = TileVirtXY(this->x_pos, this->y_pos); ++ ++ ClrBit(this->gv_flags, GVF_GOINGUP_BIT); ++ ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT); ++ ++ if (pos_tile == t->tile_n || pos_tile == t->tile_s) { ++ this->z_pos = 0; ++ return; ++ } ++ ++ int north_coord, south_coord, pos_coord; ++ Slope slope = SLOPE_FLAT; ++ int delta; ++ if (t->tile_s - t->tile_n > MapMaxX()) { ++ // tunnel extends along Y axis (DIAGDIR_SE from north end), has same X values ++ north_coord = TileY(t->tile_n); ++ south_coord = TileY(t->tile_s); ++ pos_coord = TileY(pos_tile); ++ ++ if ((delta = pos_coord - north_coord) <= 3) { ++ this->z_pos = TILE_HEIGHT * (delta == 3 ? -2 : -1); ++ if (delta != 2) { ++ slope = SLOPE_NW; ++ SetBit(this->gv_flags, this->direction == DIR_NW ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT); ++ } ++ } else if ((delta = south_coord - pos_coord) <= 3) { ++ this->z_pos = TILE_HEIGHT * (delta == 3 ? -2 : -1); ++ if (delta != 2) { ++ slope = SLOPE_ELEVATED ^ SLOPE_NW; ++ SetBit(this->gv_flags, this->direction == DIR_NW ? GVF_GOINGDOWN_BIT : GVF_GOINGUP_BIT); ++ } ++ } ++ } else { ++ // tunnel extends along X axis (DIAGDIR_SW from north end), has same Y values ++ north_coord = TileX(t->tile_n); ++ south_coord = TileX(t->tile_s); ++ pos_coord = TileX(pos_tile); ++ ++ if ((delta = pos_coord - north_coord) <= 3) { ++ this->z_pos = TILE_HEIGHT * (delta == 3 ? -3 : (delta == 2 ? -2 : -1)); ++ slope = SLOPE_NE; ++ SetBit(this->gv_flags, this->direction == DIR_NE ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT); ++ } else if ((delta = south_coord - pos_coord) <= 3) { ++ this->z_pos = TILE_HEIGHT * (delta == 3 ? -3 : (delta == 2 ? -2 : -1)); ++ slope = SLOPE_ELEVATED ^ SLOPE_NE; ++ SetBit(this->gv_flags, this->direction == DIR_NE ? GVF_GOINGDOWN_BIT : GVF_GOINGUP_BIT); ++ } ++ } ++ ++ if (slope != SLOPE_FLAT) this->z_pos += GetPartialPixelZ(this->x_pos & 0xF, this->y_pos & 0xF, slope); ++} ++ + /* Instantiation for Train */ + template struct GroundVehicle<Train, VEH_TRAIN>; + /* Instantiation for RoadVehicle */ +diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp +index af6e25c806..ae4e9ead11 100644 +--- a/src/ground_vehicle.hpp ++++ b/src/ground_vehicle.hpp +@@ -14,6 +14,7 @@ + #include "vehicle_gui.h" + #include "landscape.h" + #include "window_func.h" ++#include "tunnel_map.h" + #include "widgets/vehicle_widget.h" + + /** What is the status of our acceleration? */ +@@ -52,6 +53,7 @@ enum GroundVehicleFlags { + GVF_GOINGUP_BIT = 0, ///< Vehicle is currently going uphill. (Cached track information for acceleration) + GVF_GOINGDOWN_BIT = 1, ///< Vehicle is currently going downhill. (Cached track information for acceleration) + GVF_SUPPRESS_IMPLICIT_ORDERS = 2, ///< Disable insertion and removal of automatic orders until the vehicle completes the real order. ++ GVF_CHUNNEL_BIT = 3, ///< Vehicle may currently be in a chunnel. (Cached track information for inclination changes) + }; + + /** +@@ -220,20 +222,28 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> { + this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d; + } + ++ if (HasBit(this->gv_flags, GVF_CHUNNEL_BIT) && !IsTunnelTile(this->tile)) { ++ ClrBit(this->gv_flags, GVF_CHUNNEL_BIT); ++ } ++ + assert(this->z_pos == GetSlopePixelZ(this->x_pos, this->y_pos)); + } + ++ void UpdateZPositionInWormhole(); ++ + /** + * Checks if the vehicle is in a slope and sets the required flags in that case. + * @param new_tile True if the vehicle reached a new tile. + * @param update_delta Indicates to also update the delta. + * @return Old height of the vehicle. + */ +- inline int UpdateInclination(bool new_tile, bool update_delta) ++ inline int UpdateInclination(bool new_tile, bool update_delta, bool in_wormhole = false) + { + int old_z = this->z_pos; + +- if (new_tile) { ++ if (in_wormhole) { ++ if (HasBit(this->gv_flags, GVF_CHUNNEL_BIT)) this->UpdateZPositionInWormhole(); ++ } else if (new_tile) { + this->UpdateZPositionAndInclination(); + } else { + this->UpdateZPosition(); +diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp +index 816146212f..5491936557 100644 +--- a/src/industry_cmd.cpp ++++ b/src/industry_cmd.cpp +@@ -20,6 +20,7 @@ + #include "company_base.h" + #include "genworld.h" + #include "tree_map.h" ++#include "tunnel_map.h" + #include "newgrf_cargo.h" + #include "newgrf_debug.h" + #include "newgrf_industrytiles.h" +@@ -1521,6 +1522,11 @@ static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town + return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER); + } + ++ if (type == IT_OIL_RIG && ++ (IsTunnelInWay(tile, 0) || ++ IsTunnelInWay(tile + TileDiffXY(0, 1), 0) || ++ IsTunnelInWay(tile + TileDiffXY(1, 2), 0))) return_cmd_error(STR_ERROR_NO_DRILLING_ABOVE_CHUNNEL); ++ + return CommandCost(); + } + diff --git a/src/lang/english.txt b/src/lang/english.txt -index 8a79d87ea6..c6169a78ec 100644 +index 1751e360f0..ce8baa7a4c 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt -@@ -2337,6 +2337,7 @@ STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Toggle t +@@ -2325,6 +2325,7 @@ STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Toggle t STR_TRANSPARENT_STRUCTURES_TOOLTIP :{BLACK}Toggle transparency for structures like lighthouses and antennas. Ctrl+Click to lock STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Toggle transparency for catenary. Ctrl+Click to lock STR_TRANSPARENT_LOADING_TOOLTIP :{BLACK}Toggle transparency for loading indicators. Ctrl+Click to lock @@ -10,6 +180,215 @@ index 8a79d87ea6..c6169a78ec 100644 STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}Set objects invisible instead of transparent # Linkgraph legend window +@@ -2724,7 +2725,9 @@ STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT :Ship depot + # Industries come directly from their industry names + + STR_LAI_TUNNEL_DESCRIPTION_RAILROAD :Railway tunnel ++STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_CHUNNEL :Railway tunnel (underwater) + STR_LAI_TUNNEL_DESCRIPTION_ROAD :Road tunnel ++STR_LAI_TUNNEL_DESCRIPTION_ROAD_CHUNNEL :Road tunnel (underwater) + + STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL :Steel suspension rail bridge + STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL :Steel girder rail bridge +@@ -4542,6 +4545,10 @@ 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 must have a ramp at least three tiles long at both ends. ++STR_ERROR_TUNNEL_TOO_MANY :{WHITE}... too many tunnels ++STR_ERROR_NO_DRILLING_ABOVE_CHUNNEL :{WHITE}No oil rigs allowed above underwater tunnels. ++STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY_FOR_CHUNNEL :{WHITE}Three tiles are needed to pass under the other tunnel. + + # Object related errors + STR_ERROR_TOO_MANY_OBJECTS :{WHITE}... too many objects +diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp +index 0e490fbc21..73c4648926 100644 +--- a/src/roadveh_cmd.cpp ++++ b/src/roadveh_cmd.cpp +@@ -1182,6 +1182,7 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev) + v->x_pos = gp.x; + v->y_pos = gp.y; + v->UpdatePosition(); ++ RoadZPosAffectSpeed(v, v->UpdateInclination(false, false, true)); + if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true); + return true; + } +@@ -1549,7 +1550,7 @@ again: + v->x_pos = x; + v->y_pos = y; + v->UpdatePosition(); +- RoadZPosAffectSpeed(v, v->UpdateInclination(false, true)); ++ RoadZPosAffectSpeed(v, v->UpdateInclination(false, true, v->state == RVSB_WORMHOLE)); + return true; + } + +diff --git a/src/saveload/CMakeLists.txt b/src/saveload/CMakeLists.txt +index 52f103fa7e..c888a899cd 100644 +--- a/src/saveload/CMakeLists.txt ++++ b/src/saveload/CMakeLists.txt +@@ -38,6 +38,7 @@ add_files( + story_sl.cpp + subsidy_sl.cpp + town_sl.cpp ++ tunnel_sl.cpp + vehicle_sl.cpp + waypoint_sl.cpp + ) +diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp +index 329152ab27..7ebefb7ad7 100644 +--- a/src/saveload/afterload.cpp ++++ b/src/saveload/afterload.cpp +@@ -11,6 +11,7 @@ + #include "../void_map.h" + #include "../signs_base.h" + #include "../depot_base.h" ++#include "../tunnel_base.h" + #include "../fios.h" + #include "../gamelog_internal.h" + #include "../network/network.h" +@@ -534,6 +535,25 @@ static inline bool MayHaveBridgeAbove(TileIndex t) + IsTileType(t, MP_WATER) || IsTileType(t, MP_TUNNELBRIDGE) || IsTileType(t, MP_OBJECT); + } + ++TileIndex GetOtherTunnelBridgeEndOld(TileIndex tile) ++{ ++ DiagDirection dir = GetTunnelBridgeDirection(tile); ++ TileIndexDiff delta = TileOffsByDiagDir(dir); ++ int z = GetTileZ(tile); ++ ++ dir = ReverseDiagDir(dir); ++ do { ++ tile += delta; ++ } while ( ++ !IsTunnelTile(tile) || ++ GetTunnelBridgeDirection(tile) != dir || ++ GetTileZ(tile) != z ++ ); ++ ++ return tile; ++} ++ ++ + /** + * Perform a (large) amount of savegame conversion *magic* in order to + * load older savegames and to fill the caches for various purposes. +@@ -1944,6 +1964,32 @@ bool AfterLoadGame() + } + } + ++ /* Tunnel pool has to be initiated before reservations. */ ++ if (IsSavegameVersionBefore(SLV_196)) { ++ for (TileIndex t = 0; t < map_size; t++) { ++ if (IsTunnelTile(t)) { ++ DiagDirection dir = GetTunnelBridgeDirection(t); ++ if (dir == DIAGDIR_SE || dir == DIAGDIR_SW) { ++ TileIndex start_tile = t; ++ TileIndex end_tile = GetOtherTunnelBridgeEndOld(start_tile); ++ ++ if (!Tunnel::CanAllocateItem()) { ++ SetSaveLoadError(STR_ERROR_TUNNEL_TOO_MANY); ++ /* Restore the signals */ ++ ResetSignalHandlers(); ++ return false; ++ } ++ ++ const Tunnel *t = new Tunnel(start_tile, end_tile, false); ++ ++ _m[start_tile].m2 = t->index; ++ _m[end_tile].m2 = t->index; ++ } ++ } ++ } ++ } ++ ++ + /* Move the signal variant back up one bit for PBS. We don't convert the old PBS + * format here, as an old layout wouldn't work properly anyway. To be safe, we + * clear any possible PBS reservations as well. */ +@@ -2547,7 +2593,7 @@ bool AfterLoadGame() + } else if (dir == ReverseDiagDir(vdir)) { // Leaving tunnel + hidden = frame < TILE_SIZE - _tunnel_visibility_frame[dir]; + /* v->tile changes at the moment when the vehicle leaves the tunnel. */ +- v->tile = hidden ? GetOtherTunnelBridgeEnd(vtile) : vtile; ++ v->tile = hidden ? GetOtherTunnelBridgeEndOld(vtile) : vtile; + } else { + /* We could get here in two cases: + * - for road vehicles, it is reversing at the end of the tunnel +diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp +index 1b79ad926b..69e8b60905 100644 +--- a/src/saveload/saveload.cpp ++++ b/src/saveload/saveload.cpp +@@ -248,6 +248,7 @@ extern const ChunkHandler _linkgraph_chunk_handlers[]; + extern const ChunkHandler _airport_chunk_handlers[]; + extern const ChunkHandler _object_chunk_handlers[]; + extern const ChunkHandler _persistent_storage_chunk_handlers[]; ++extern const ChunkHandler _tunnel_chunk_handlers[]; + + /** Array of all chunks in a savegame, \c nullptr terminated. */ + static const ChunkHandler * const _chunk_handlers[] = { +@@ -284,6 +285,8 @@ static const ChunkHandler * const _chunk_handlers[] = { + _airport_chunk_handlers, + _object_chunk_handlers, + _persistent_storage_chunk_handlers, ++ _tunnel_chunk_handlers, ++ + nullptr, + }; + +diff --git a/src/saveload/tunnel_sl.cpp b/src/saveload/tunnel_sl.cpp +new file mode 100644 +index 0000000000..7ad37b12b9 +--- /dev/null ++++ b/src/saveload/tunnel_sl.cpp +@@ -0,0 +1,48 @@ ++/* $Id$ */ ++ ++/* ++ * This file is part of OpenTTD. ++ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. ++ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++/** @file tunnel_sl.cpp Code handling saving and loading of tunnels */ ++ ++#include "../stdafx.h" ++#include "../tunnel_base.h" ++ ++#include "saveload.h" ++ ++#include "../safeguards.h" ++ ++ ++static const SaveLoad _tunnel_desc[] = { ++ SLE_CONDVAR(Tunnel, tile_n, SLE_UINT32, SLV_196, SL_MAX_VERSION), ++ SLE_CONDVAR(Tunnel, tile_s, SLE_UINT32, SLV_196, SL_MAX_VERSION), ++ SLE_CONDVAR(Tunnel, is_chunnel, SLE_BOOL, SLV_196, SL_MAX_VERSION), ++ SLE_END() ++}; ++ ++static void Save_TUNN() ++{ ++ for(Tunnel *tunnel : Tunnel::Iterate()) { ++ SlSetArrayIndex(tunnel->index); ++ SlObject(tunnel, _tunnel_desc); ++ } ++} ++ ++static void Load_TUNN() ++{ ++ int index; ++ ++ while ((index = SlIterateArray()) != -1) { ++ Tunnel *tunnel = new (index) Tunnel(); ++ SlObject(tunnel, _tunnel_desc); ++ } ++} ++ ++ ++extern const ChunkHandler _tunnel_chunk_handlers[] = { ++ { 'TUNN', Save_TUNN, Load_TUNN, nullptr, nullptr, CH_ARRAY | CH_LAST}, ++}; diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index edad848165..f0322ee359 100644 --- a/src/table/misc_settings.ini @@ -32,11 +411,57 @@ index edad848165..f0322ee359 100644 cat = SC_BASIC [SDTG_VAR] +diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp +index 85edb73128..1a902dd59c 100644 +--- a/src/terraform_cmd.cpp ++++ b/src/terraform_cmd.cpp +@@ -268,7 +268,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, true)) { + _terraform_err_tile = tile; // highlight the tile above the tunnel + return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE); + } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp -index 5d02764b55..6438e18661 100644 +index 5d02764b55..cc0455f8f9 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp -@@ -3853,7 +3853,7 @@ static bool TrainLocoHandler(Train *v, bool mode) +@@ -1563,6 +1563,7 @@ static void UpdateStatusAfterSwap(Train *v) + } + + v->UpdatePosition(); ++ if (v->track == TRACK_BIT_WORMHOLE) v->UpdateInclination(false, false, true); + v->UpdateViewport(true, true); + } + +@@ -3326,6 +3327,15 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) + v->x_pos = gp.x; + v->y_pos = gp.y; + v->UpdatePosition(); ++ if (v->track == TRACK_BIT_WORMHOLE) { ++ /* update the Z position of the vehicle */ ++ int old_z = v->UpdateInclination(false, false, true); ++ ++ if (prev == nullptr) { ++ /* This is the first vehicle in the train */ ++ AffectSpeedByZChange(v, old_z); ++ } ++ } + if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true); + continue; + } +@@ -3339,7 +3349,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) + v->UpdatePosition(); + + /* update the Z position of the vehicle */ +- int old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false); ++ int old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false, v->track == TRACK_BIT_WORMHOLE); + + if (prev == nullptr) { + /* This is the first vehicle in the train */ +@@ -3853,7 +3863,7 @@ static bool TrainLocoHandler(Train *v, bool mode) } for (Train *u = v; u != nullptr; u = u->Next()) { @@ -58,7 +483,7 @@ index 54ba24e933..08b13ca9b9 100644 TO_INVALID, ///< Invalid transparency option }; diff --git a/src/transparency_gui.cpp b/src/transparency_gui.cpp -index 153dcb5d03..55ac1a75de 100644 +index 153dcb5d03..611094cdeb 100644 --- a/src/transparency_gui.cpp +++ b/src/transparency_gui.cpp @@ -50,7 +50,8 @@ public: @@ -66,7 +491,7 @@ index 153dcb5d03..55ac1a75de 100644 case WID_TT_STRUCTURES: case WID_TT_CATENARY: - case WID_TT_LOADING: { -+ case WID_TT_LOADING: ++ case WID_TT_LOADING: + case WID_TT_TUNNELS: { uint i = widget - WID_TT_BEGIN; if (HasBit(_transparency_lock, i)) DrawSprite(SPR_LOCK, PAL_NONE, r.left + 1, r.top + 1); @@ -96,11 +521,476 @@ index 153dcb5d03..55ac1a75de 100644 NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 1), EndContainer(), EndContainer(), /* Panel with 'invisibility' buttons. */ +diff --git a/src/tunnel_base.h b/src/tunnel_base.h +new file mode 100644 +index 0000000000..4a2493fa7f +--- /dev/null ++++ b/src/tunnel_base.h +@@ -0,0 +1,39 @@ ++/* $Id$ */ ++ ++/* ++ * This file is part of OpenTTD. ++ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. ++ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++/** @file tunnel_base.h Base for all tunnels */ ++ ++#ifndef TUNNEL_BASE_H ++#define TUNNEL_BASE_H ++ ++#include "tunnel_map.h" ++#include "core/pool_type.hpp" ++ ++struct Tunnel; ++ ++typedef Pool<Tunnel, TunnelID, 64, 64000> TunnelPool; ++extern TunnelPool _tunnel_pool; ++ ++struct Tunnel : TunnelPool::PoolItem<&_tunnel_pool> { ++ ++ TileIndex tile_n; // North tile of tunnel. ++ TileIndex tile_s; // South tile of tunnel. ++ bool is_chunnel; ++ ++ Tunnel() {} ++ Tunnel(TileIndex tile_n, TileIndex tile_s, bool is_chunnel) : tile_n(tile_n), tile_s(tile_s), is_chunnel(is_chunnel) {} ++ ~Tunnel(); ++ ++ static inline Tunnel *GetByTile(TileIndex tile) ++ { ++ return Tunnel::Get(GetTunnelIndex(tile)); ++ } ++}; ++ ++#endif /* TUNNEL_BASE_H */ +diff --git a/src/tunnel_map.cpp b/src/tunnel_map.cpp +index 9de5235801..6234193e1e 100644 +--- a/src/tunnel_map.cpp ++++ b/src/tunnel_map.cpp +@@ -10,63 +10,62 @@ + #include "stdafx.h" + #include "tunnelbridge_map.h" + ++#include "core/pool_func.hpp" ++ + #include "safeguards.h" + ++/** All tunnel portals tucked away in a pool. */ ++TunnelPool _tunnel_pool("Tunnel"); ++INSTANTIATE_POOL_METHODS(Tunnel) + + /** +- * Gets the other end of the tunnel. Where a vehicle would reappear when it +- * enters at the given tile. +- * @param tile the tile to search from. +- * @return the tile of the other end of the tunnel. ++ * Clean up a tunnel tile + */ +-TileIndex GetOtherTunnelEnd(TileIndex tile) ++Tunnel::~Tunnel() + { +- DiagDirection dir = GetTunnelBridgeDirection(tile); +- TileIndexDiff delta = TileOffsByDiagDir(dir); +- int z = GetTileZ(tile); +- +- dir = ReverseDiagDir(dir); +- do { +- tile += delta; +- } while ( +- !IsTunnelTile(tile) || +- GetTunnelBridgeDirection(tile) != dir || +- GetTileZ(tile) != z +- ); +- +- return tile; ++ if (CleaningPool()) return; + } + +- + /** +- * Is there a tunnel in the way in the given direction? ++ * Gets the other end of the tunnel. Where a vehicle would reappear when it ++ * enters at the given tile. + * @param tile the tile to search from. +- * @param z the 'z' to search on. +- * @param dir the direction to start searching to. +- * @return true if and only if there is a tunnel. ++ * @return the tile of the other end of the tunnel. + */ +-bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir) ++TileIndex GetOtherTunnelEnd(TileIndex tile) + { +- TileIndexDiff delta = TileOffsByDiagDir(dir); +- int height; +- +- do { +- tile -= delta; +- if (!IsValidTile(tile)) return false; +- height = GetTileZ(tile); +- } while (z < height); +- +- return z == height && IsTunnelTile(tile) && GetTunnelBridgeDirection(tile) == dir; ++ Tunnel *t = Tunnel::GetByTile(tile); ++ return t->tile_n == tile ? t->tile_s : t->tile_n; + } + + /** + * 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 chunnel_allowed True if chunnel mid-parts are allowed, used when terraforming. + * @return true if and only if there is a tunnel. + */ +-bool IsTunnelInWay(TileIndex tile, int z) ++bool IsTunnelInWay(TileIndex tile, int z, bool chunnel_allowed) + { +- return IsTunnelInWayDir(tile, z, (TileX(tile) > (MapMaxX() / 2)) ? DIAGDIR_NE : DIAGDIR_SW) || +- IsTunnelInWayDir(tile, z, (TileY(tile) > (MapMaxY() / 2)) ? DIAGDIR_NW : DIAGDIR_SE); ++ uint x = TileX(tile); ++ uint y = TileY(tile); ++ ++ for(Tunnel *t : Tunnel::Iterate()) { ++ if (t->tile_n > tile || tile > t->tile_s) continue; ++ ++ if (t->tile_s - t->tile_n > MapMaxX()){ ++ if (TileX(t->tile_n) != x || (int)TileHeight(t->tile_n) != z) continue; // dir DIAGDIR_SE ++ } else { ++ if (TileY(t->tile_n) != y || (int)TileHeight(t->tile_n) != z) continue; // dir DIAGDIR_SW ++ } ++ ++ if (t->is_chunnel && chunnel_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 c347626d55..45589dacb4 100644 +--- a/src/tunnel_map.h ++++ b/src/tunnel_map.h +@@ -13,6 +13,7 @@ + #include "rail_map.h" + #include "road_map.h" + ++typedef uint16 TunnelID; ///< Type for the unique identifier of tunnels. + + /** + * Is this a tunnel (entrance)? +@@ -36,22 +37,34 @@ static inline bool IsTunnelTile(TileIndex t) + return IsTileType(t, MP_TUNNELBRIDGE) && IsTunnel(t); + } + ++/** ++ * Get the index of tunnel tile. ++ * @param t the tile ++ * @pre IsTunnelTile(t) ++ * @return TunnelID ++ */ ++static inline TunnelID GetTunnelIndex(TileIndex t) ++{ ++ assert(IsTunnelTile(t)); ++ return _m[t].m2; ++} ++ + TileIndex GetOtherTunnelEnd(TileIndex); +-bool IsTunnelInWay(TileIndex, int z); +-bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir); ++bool IsTunnelInWay(TileIndex, int z, bool chunnel_allowed = false); + + /** + * Makes a road tunnel entrance + * @param t the entrance of the tunnel + * @param o the owner of the entrance ++ * @param id the tunnel ID + * @param d the direction facing out of the tunnel + * @param r the road type used in the tunnel + */ +-static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadType road_rt, RoadType tram_rt) ++static inline void MakeRoadTunnel(TileIndex t, Owner o, TunnelID id, DiagDirection d, RoadType road_rt, RoadType tram_rt) + { + SetTileType(t, MP_TUNNELBRIDGE); + SetTileOwner(t, o); +- _m[t].m2 = 0; ++ _m[t].m2 = id; + _m[t].m3 = 0; + _m[t].m4 = 0; + _m[t].m5 = TRANSPORT_ROAD << 2 | d; +@@ -67,14 +80,15 @@ static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTyp + * Makes a rail tunnel entrance + * @param t the entrance of the tunnel + * @param o the owner of the entrance ++ * @param id the tunnel ID + * @param d the direction facing out of the tunnel + * @param r the rail type used in the tunnel + */ +-static inline void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailType r) ++static inline void MakeRailTunnel(TileIndex t, Owner o, TunnelID id, DiagDirection d, RailType r) + { + SetTileType(t, MP_TUNNELBRIDGE); + SetTileOwner(t, o); +- _m[t].m2 = 0; ++ _m[t].m2 = id; + _m[t].m3 = 0; + _m[t].m4 = 0; + _m[t].m5 = TRANSPORT_RAIL << 2 | d; +diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp +index 0423cde1f9..159f06f3fd 100644 +--- a/src/tunnelbridge_cmd.cpp ++++ b/src/tunnelbridge_cmd.cpp +@@ -40,12 +40,15 @@ + #include "water.h" + #include "company_gui.h" + #include "station_func.h" ++#include "station_map.h" ++#include "industry_map.h" + + #include "table/strings.h" + #include "table/bridge_land.h" + + #include "safeguards.h" + ++ + BridgeSpec _bridge[MAX_BRIDGES]; ///< The specification of all bridges. + TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from the tunnel build command for GUI purposes. + +@@ -649,12 +652,6 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, + * position, because of increased-cost-by-length: 'cost += cost >> 3' */ + + 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; +- } else { +- tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW; +- } + + TileIndex end_tile = start_tile; + +@@ -662,9 +659,15 @@ 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 = 0; + /* Number of tiles at which the cost increase coefficient per tile is halved */ + int tiles_bump = 25; + ++ TileIndex found_tunnel_tile = INVALID_TILE; ++ + CommandCost cost(EXPENSES_CONSTRUCTION); + Slope end_tileh; + for (;;) { +@@ -672,13 +675,69 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, + if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER); + end_tileh = GetTileSlope(end_tile, &end_z); + +- if (start_z == end_z) break; ++ if (start_z == end_z) { ++ _build_tunnel_endtile = found_tunnel_tile != INVALID_TILE ? found_tunnel_tile : end_tile; ++ ++ /* Test if we are on a shore. */ ++ if (end_z == 0 && ++ (IsCoastTile(end_tile) || ++ (IsValidTile(end_tile + delta) && HasTileWaterGround(end_tile + delta)) || ++ (IsValidTile(end_tile + delta * 2) && HasTileWaterGround(end_tile + delta * 2)))) { ++ if (!is_chunnel) { ++ /*We are about to pass water for the first time so check if not to close to other tunnel */ ++ if (tiles + 1 < head_tiles + 4 && found_tunnel_tile != INVALID_TILE) return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY_FOR_CHUNNEL); ++ if (tiles + 1 < 4) return_cmd_error(STR_ERROR_TUNNEL_RAMP_TOO_SHORT); ++ } ++ } else {/* We are leaving.*/ ++ if (is_chunnel) { ++ /* Check if there is enough ramp space to come up. */ ++ if (head_tiles < 4 && found_tunnel_tile != INVALID_TILE) return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY_FOR_CHUNNEL); ++ if (head_tiles < 4) return_cmd_error(STR_ERROR_TUNNEL_RAMP_TOO_SHORT); ++ } else { ++ if (found_tunnel_tile != INVALID_TILE) return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY); ++ } ++ break; ++ } + +- if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) { +- return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY); +- } ++ /* A shore was found so pass the water and find a proper shore tile that potentially ++ * could have a tunnel portal behind. */ ++ for (;;) { ++ if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER); ++ ++ end_tileh = GetTileSlope(end_tile); ++ if(direction == DIAGDIR_NE && (end_tileh & SLOPE_NE) == SLOPE_NE) break; ++ if(direction == DIAGDIR_SE && (end_tileh & SLOPE_SE) == SLOPE_SE) break; ++ if(direction == DIAGDIR_SW && (end_tileh & SLOPE_SW) == SLOPE_SW) break; ++ if(direction == DIAGDIR_NW && (end_tileh & SLOPE_NW) == SLOPE_NW) break; ++ ++ /* No drilling under oil rigs.*/ ++ if ((IsTileType(end_tile, MP_STATION) && IsOilRig(end_tile)) || ++ (IsTileType(end_tile, MP_INDUSTRY) && ++ GetIndustryGfx(end_tile) >= GFX_OILRIG_1 && ++ GetIndustryGfx(end_tile) <= GFX_OILRIG_5)) { ++ _build_tunnel_endtile = end_tile; ++ return_cmd_error(STR_ERROR_NO_DRILLING_ABOVE_CHUNNEL); ++ } + ++ end_tile += delta; ++ tiles++; ++ } ++ /* The water was passed */ ++ is_chunnel = true; ++ head_tiles = 0; ++ found_tunnel_tile = INVALID_TILE; ++ } ++ if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z, (tiles + 1 < 4 || (is_chunnel && head_tiles < 4) ? false : true))) { ++ if (found_tunnel_tile == INVALID_TILE || is_chunnel) { // Remember the first or the last when we pass a tunnel. ++ found_tunnel_tile = end_tile; ++ head_tiles = 0; ++ } ++ } ++ head_tiles++; + tiles++; ++ } ++ /* The cost of the digging. */ ++ for (int i = tiles; i > 0; i--) { + if (tiles == tiles_bump) { + tiles_coef++; + tiles_bump *= 2; +@@ -746,21 +805,32 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, + default: NOT_REACHED(); + } + ++ if (is_chunnel) cost.MultiplyCost(2); ++ + if (flags & DC_EXEC) { + Company *c = Company::GetIfValid(company); + uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR; ++ ++ /* The most northern tile first. */ ++ TileIndex tn = start_tile; ++ TileIndex ts = end_tile; ++ if(start_tile > end_tile) Swap(tn, ts); ++ ++ if (!Tunnel::CanAllocateItem()) return_cmd_error(STR_ERROR_TUNNEL_TOO_MANY); ++ const Tunnel *t = new Tunnel(tn, ts, is_chunnel); ++ + if (transport_type == TRANSPORT_RAIL) { + if (c != nullptr) c->infrastructure.rail[railtype] += num_pieces; +- MakeRailTunnel(start_tile, company, direction, railtype); +- MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype); ++ MakeRailTunnel(start_tile, company, t->index, direction, railtype); ++ MakeRailTunnel(end_tile, company, t->index, ReverseDiagDir(direction), railtype); + AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company); + YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction)); + } else { + if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits. + RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE; + RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE; +- MakeRoadTunnel(start_tile, company, direction, road_rt, tram_rt); +- MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), road_rt, tram_rt); ++ MakeRoadTunnel(start_tile, company, t->index, direction, road_rt, tram_rt); ++ MakeRoadTunnel(end_tile, company, t->index, ReverseDiagDir(direction), road_rt, tram_rt); + } + DirtyCompanyInfrastructureWindows(company); + } +@@ -850,6 +920,8 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) + ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags); + } + ++ const bool is_chunnel = Tunnel::GetByTile(tile)->is_chunnel; ++ + uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles. + + if (flags & DC_EXEC) { +@@ -870,6 +942,8 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) + DirtyCompanyInfrastructureWindows(owner); + } + ++ delete Tunnel::GetByTile(tile); ++ + DoClearSquare(tile); + DoClearSquare(endtile); + +@@ -886,11 +960,13 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) + UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR)); + UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR)); + ++ delete Tunnel::GetByTile(tile); ++ + DoClearSquare(tile); + DoClearSquare(endtile); + } + } +- return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len); ++ return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len * (is_chunnel ? 2 : 1)); + } + + +@@ -1866,6 +1942,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti + if (frame == _tunnel_visibility_frame[dir]) { + t->tile = tile; + t->track = TRACK_BIT_WORMHOLE; ++ if (Tunnel::GetByTile(tile)->is_chunnel) SetBit(t->gv_flags, GVF_CHUNNEL_BIT); + t->vehstatus |= VS_HIDDEN; + return VETSB_ENTERED_WORMHOLE; + } +@@ -1873,6 +1950,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti + + if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) { + /* We're at the tunnel exit ?? */ ++ if (t->tile != tile && GetOtherTunnelEnd(t->tile) != tile) return VETSB_CONTINUE; // In chunnel + t->tile = tile; + t->track = DiagDirToDiagTrackBits(vdir); + assert(t->track); +@@ -1889,6 +1967,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti + assert(frame == rv->frame + 1); + rv->tile = tile; + rv->state = RVSB_WORMHOLE; ++ if (Tunnel::GetByTile(tile)->is_chunnel) SetBit(rv->gv_flags, GVF_CHUNNEL_BIT); + rv->vehstatus |= VS_HIDDEN; + return VETSB_ENTERED_WORMHOLE; + } else { +@@ -1898,6 +1977,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti + + /* We're at the tunnel exit ?? */ + if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) { ++ if (rv->tile != tile && GetOtherTunnelEnd(rv->tile) != tile) return VETSB_CONTINUE; // In chunnel + rv->tile = tile; + rv->state = DiagDirToDiagTrackdir(vdir); + rv->frame = frame; +@@ -1906,6 +1986,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti + } + } + } else { // IsBridge(tile) ++ if (v->vehstatus & VS_HIDDEN) return VETSB_CONTINUE; // Building bridges between chunnel portals allowed. + if (v->type != VEH_SHIP) { + /* modify speed of vehicle */ + uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed; +diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h +index 62d3c14b2d..37e00457e4 100644 +--- a/src/tunnelbridge_map.h ++++ b/src/tunnelbridge_map.h +@@ -11,7 +11,7 @@ + #define TUNNELBRIDGE_MAP_H + + #include "bridge_map.h" +-#include "tunnel_map.h" ++#include "tunnel_base.h" + + + /** diff --git a/src/vehicle.cpp b/src/vehicle.cpp -index 956b449602..abce02af64 100644 +index e014944a9f..cb6239f597 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp -@@ -286,6 +286,14 @@ uint Vehicle::Crash(bool flooded) +@@ -285,6 +285,14 @@ uint Vehicle::Crash(bool flooded) return RandomRange(pass + 1); // Randomise deceased passengers. } @@ -115,7 +1005,7 @@ index 956b449602..abce02af64 100644 /** * Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking. -@@ -1083,7 +1091,7 @@ static void DoDrawVehicle(const Vehicle *v) +@@ -1082,7 +1090,7 @@ static void DoDrawVehicle(const Vehicle *v) if (v->vehstatus & VS_DEFPAL) pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); /* Check whether the vehicle shall be transparent due to the game state */ @@ -124,16 +1014,16 @@ index 956b449602..abce02af64 100644 if (v->type == VEH_EFFECT) { /* Check whether the vehicle shall be transparent/invisible due to GUI settings. -@@ -1141,7 +1149,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) +@@ -1139,7 +1147,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) + const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF while (v != nullptr) { - if (LayerIndex(v->tile) == dpi->layer) - if (!(v->vehstatus & VS_HIDDEN) && + if (v->IsDrawn() && l <= v->coord.right && t <= v->coord.bottom && r >= v->coord.left && -@@ -1176,7 +1184,7 @@ Vehicle *CheckClickOnVehicle(const Viewport *vp, int x, int y) +@@ -1174,7 +1182,7 @@ Vehicle *CheckClickOnVehicle(const Viewport *vp, int x, int y) y = ScaleByZoom(y, vp->zoom) + vp->virtual_top; for (Vehicle *v : Vehicle::Iterate()) { |