diff options
Diffstat (limited to 'openttd-git/chunnel.patch')
-rw-r--r-- | openttd-git/chunnel.patch | 1063 |
1 files changed, 0 insertions, 1063 deletions
diff --git a/openttd-git/chunnel.patch b/openttd-git/chunnel.patch deleted file mode 100644 index 4071429f6..000000000 --- a/openttd-git/chunnel.patch +++ /dev/null @@ -1,1063 +0,0 @@ -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 8d8a128717..765fc146a1 100644 ---- a/src/lang/english.txt -+++ b/src/lang/english.txt -@@ -2321,6 +2321,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 -+STR_TRANSPARENT_TUNNELS_TOOLTIP :{BLACK}Toggle transparency for vehicles in tunnels. Ctrl+Click to lock. - STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}Set objects invisible instead of transparent - - # Linkgraph legend window -@@ -2720,7 +2721,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 14fa8d79d8..604b51ea46 100644 ---- a/src/roadveh_cmd.cpp -+++ b/src/roadveh_cmd.cpp -@@ -1178,6 +1178,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; - } -@@ -1545,7 +1546,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 -+++ b/src/table/misc_settings.ini -@@ -254,7 +254,7 @@ type = SLE_UINT - var = _transparency_opt - def = 0 - min = 0 --max = 0x1FF -+max = 0x3FF - cat = SC_BASIC - - [SDTG_VAR] -@@ -263,7 +263,7 @@ type = SLE_UINT - var = _transparency_lock - def = 0 - min = 0 --max = 0x1FF -+max = 0x3FF - 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 ae9cb45de3..a9ca119ec3 100644 ---- a/src/train_cmd.cpp -+++ b/src/train_cmd.cpp -@@ -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()) { -- if ((u->vehstatus & VS_HIDDEN) != 0) continue; -+ if (!u->IsDrawn()) continue; - - u->UpdateViewport(false, false); - } -diff --git a/src/transparency.h b/src/transparency.h -index 54ba24e933..08b13ca9b9 100644 ---- a/src/transparency.h -+++ b/src/transparency.h -@@ -29,6 +29,7 @@ enum TransparencyOption { - TO_STRUCTURES, ///< other objects such as transmitters and lighthouses - TO_CATENARY, ///< catenary - TO_LOADING, ///< loading indicators -+ TO_TUNNELS, ///< vehicles in tunnels - TO_END, - TO_INVALID, ///< Invalid transparency option - }; -diff --git a/src/transparency_gui.cpp b/src/transparency_gui.cpp -index 153dcb5d03..611094cdeb 100644 ---- a/src/transparency_gui.cpp -+++ b/src/transparency_gui.cpp -@@ -50,7 +50,8 @@ public: - case WID_TT_BRIDGES: - case WID_TT_STRUCTURES: - case WID_TT_CATENARY: -- 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); - break; -@@ -58,6 +59,7 @@ public: - case WID_TT_BUTTONS: - for (uint i = WID_TT_BEGIN; i < WID_TT_END; i++) { - if (i == WID_TT_LOADING) continue; // Do not draw button for invisible loading indicators. -+ if (i == WID_TT_TUNNELS) continue; // Do not draw button for invisible vehicles in tunnels. - - const NWidgetBase *wi = this->GetWidget<NWidgetBase>(i); - DrawFrameRect(wi->pos_x + 1, r.top + 2, wi->pos_x + wi->current_x - 2, r.bottom - 2, COLOUR_PALE_GREEN, -@@ -69,7 +71,7 @@ public: - - void OnClick(Point pt, int widget, int click_count) override - { -- if (widget >= WID_TT_BEGIN && widget < WID_TT_END) { -+ if (IsInsideMM(widget, WID_TT_BEGIN, WID_TT_END)) { - if (_ctrl_pressed) { - /* toggle the bit of the transparencies lock variable */ - ToggleTransparencyLock((TransparencyOption)(widget - WID_TT_BEGIN)); -@@ -139,6 +141,7 @@ static const NWidgetPart _nested_transparency_widgets[] = { - NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_STRUCTURES), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_TRANSPARENT_STRUCTURES_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_CATENARY), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_BUILD_X_ELRAIL, STR_TRANSPARENT_CATENARY_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_LOADING), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_TRANSPARENT_LOADING_TOOLTIP), -+ NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_TUNNELS), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_TRANSPARENT_TUNNELS_TOOLTIP), - 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 e358421186..da107682f0 100644 ---- a/src/vehicle.cpp -+++ b/src/vehicle.cpp -@@ -285,6 +285,14 @@ uint Vehicle::Crash(bool flooded) - return RandomRange(pass + 1); // Randomise deceased passengers. - } - -+bool Vehicle::IsDrawn() const -+{ -+ return !(this->vehstatus & VS_HIDDEN) || -+ (!IsTransparencySet(TO_TUNNELS) && -+ ((this->type == VEH_TRAIN && Train::From(this)->track == TRACK_BIT_WORMHOLE) || -+ (this->type == VEH_ROAD && RoadVehicle::From(this)->state == RVSB_WORMHOLE))); -+} -+ - - /** - * Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking. -@@ -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 */ -- bool shadowed = (v->vehstatus & VS_SHADOW) != 0; -+ bool shadowed = (v->vehstatus & (VS_SHADOW | VS_HIDDEN)) != 0; - - if (v->type == VEH_EFFECT) { - /* Check whether the vehicle shall be transparent/invisible due to GUI settings. -@@ -1155,7 +1163,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) - - while (v != nullptr) { - -- if (!(v->vehstatus & VS_HIDDEN) && -+ if (v->IsDrawn() && - l <= v->coord.right && - t <= v->coord.bottom && - r >= v->coord.left && -@@ -1209,7 +1217,7 @@ Vehicle *CheckClickOnVehicle(const Viewport *vp, int x, int y) - y = ScaleByZoom(y, vp->zoom) + vp->virtual_top; - - for (Vehicle *v : Vehicle::Iterate()) { -- if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 && -+ if (v->IsDrawn() && !(v->vehstatus & VS_UNCLICKABLE) && - x >= v->coord.left && x <= v->coord.right && - y >= v->coord.top && y <= v->coord.bottom) { - -diff --git a/src/vehicle_base.h b/src/vehicle_base.h -index 24facfb3e4..f3a964261c 100644 ---- a/src/vehicle_base.h -+++ b/src/vehicle_base.h -@@ -363,6 +363,12 @@ public: - - uint GetConsistTotalCapacity() const; - -+ /** -+ * Is this vehicle drawn? -+ * @return true if it is drawn -+ */ -+ bool IsDrawn() const; -+ - /** - * Marks the vehicles to be redrawn and updates cached variables - * -diff --git a/src/widgets/transparency_widget.h b/src/widgets/transparency_widget.h -index 2b096e733b..099d48a339 100644 ---- a/src/widgets/transparency_widget.h -+++ b/src/widgets/transparency_widget.h -@@ -23,6 +23,7 @@ enum TransparencyToolbarWidgets { - WID_TT_STRUCTURES, ///< Object structure transparency toggle button. - WID_TT_CATENARY, ///< Catenary transparency toggle button. - WID_TT_LOADING, ///< Loading indicators transparency toggle button. -+ WID_TT_TUNNELS, ///< Vehicles in tunnels toggle button. - WID_TT_END, ///< End of toggle buttons. - - /* Panel with buttons for invisibility */ |