diff options
Diffstat (limited to 'manualPorts')
-rw-r--r-- | manualPorts/openttd-git/.md5sum | 6 | ||||
-rw-r--r-- | manualPorts/openttd-git/.signature | 10 | ||||
-rw-r--r-- | manualPorts/openttd-git/Pkgfile | 10 | ||||
-rw-r--r-- | manualPorts/openttd-git/chunnel-pre.patch | 12 | ||||
-rw-r--r-- | manualPorts/openttd-git/chunnel-signaltunnel-pre.patch | 22 | ||||
-rw-r--r-- | manualPorts/openttd-git/chunnel-underground-pre.patch | 22 | ||||
-rw-r--r-- | manualPorts/openttd-git/chunnel.patch | 914 |
7 files changed, 976 insertions, 20 deletions
diff --git a/manualPorts/openttd-git/.md5sum b/manualPorts/openttd-git/.md5sum index 318c1ed..d2788ff 100644 --- a/manualPorts/openttd-git/.md5sum +++ b/manualPorts/openttd-git/.md5sum @@ -1,5 +1,7 @@ -45d70a42c456cdcc79250d0af5c754fb 5b1fb9424.tar.gz -baf45bd3f088439b66a3e1b9a5a37e87 chunnel.patch +0ffa0a12430f54ef62a440d1341b9ae2 8596b43b2.tar.gz +b1743db8efd877f8ede49e5d773eeb57 chunnel-signaltunnel-pre.patch +67cd092775c89c94d5867a7c446fa836 chunnel-underground-pre.patch +5abc7dcd023758b7ab559d91008cc61c chunnel.patch 4f4a6465cd5b84964b7ceecd1c06d686 opengfx-0.5.4.zip 858b79d44aea6de5e15d9d1439e86cc3 openmsx-0.3.1.zip 6e3a5cf97fe69e3a351c3e0615a14b04 opensfx-0.2.3.zip diff --git a/manualPorts/openttd-git/.signature b/manualPorts/openttd-git/.signature index b91a23c..c82b33d 100644 --- a/manualPorts/openttd-git/.signature +++ b/manualPorts/openttd-git/.signature @@ -1,13 +1,15 @@ untrusted comment: verify with /etc/ports/deepthought.pub -RWQxCptPusLGGj6kt1db0Hg7a7hQD9mzODj5gXFwUZDuNnhP12odW8E44IhfEJlpdPQN63DCuRHwL0pEy2xtnXvHf3Xg29T5/g4= -SHA256 (Pkgfile) = 4d7764a2a26e58744df836025a411e743f6de1dca0eb05fda38d65fa275d3283 +RWQxCptPusLGGjOjii9irekLJpMUF1OKg1Xf17HHWZIS8y7Zv/LLYwklri/mg5DXcCM0p8xN7Q5+LW6/s+wnO1I4XlGGsvHUYAg= +SHA256 (Pkgfile) = 4ff775405fb87a219bf7e9ff5e7a71009d59d8a67a0345f8ac761d669575dc77 SHA256 (.footprint) = c9df484f7cd09eda02d1cdbb365d3a78a874a6b895a96d90146bb7a226666cbd SHA256 (opengfx-0.5.4.zip) = 3d136d776906dbe8b5df1434cb9a68d1249511a3c4cfaca55cc24cc0028ae078 SHA256 (opensfx-0.2.3.zip) = 3574745ac0c138bae53b56972591db8d778ad9faffd51deae37a48a563e71662 SHA256 (openmsx-0.3.1.zip) = 92e293ae89f13ad679f43185e83fb81fb8cad47fe63f4af3d3d9f955130460f5 -SHA256 (chunnel.patch) = c7545b0423dd95cfa4f36076fed979b26bef58c5b78cf4e10725efa23cb11978 +SHA256 (chunnel.patch) = c3e3442115c73c7dbd4a4c039d7e2261d316d2ad71ede63b5a5064e5b38655ed +SHA256 (chunnel-signaltunnel-pre.patch) = 7f6c5c38eb052c1844b8c7e50a5fae29b753fdf2c0ae187df5e7ee787ece7f51 +SHA256 (chunnel-underground-pre.patch) = 99f6f907bb1e32aecfa915f12b91e841d45f5baae5fd6c088b8f6b142177da2d SHA256 (signaltunnel.patch) = d875acd1ebab6ea1decffcbd40a0810181200f0b482c53c8b3eb8eddc210e13b SHA256 (sloped-stations.patch) = 2b232bf1efa8e14b1e10d40ee74a02c5918f539e7af78a10b2e37b3c63fd2149 SHA256 (underground.patch) = c2320b8ae0c705d788acc9084ab17921669f870e4bbcb3029d41ebbafc3083a5 SHA256 (opntitle.dat) = f4931200a68a6f592716ec2dce468530670484dd357ab52c3a2272b9db3dfd95 -SHA256 (5b1fb9424.tar.gz) = 8226c49671b6704f60fbc64424150f28ea99e574a9251526c4998f0bbba6b890 +SHA256 (8596b43b2.tar.gz) = 2e3cca0dbd3a31e99a81e1a16146d91db27afa55cbfec2a70067ed40d35872dd diff --git a/manualPorts/openttd-git/Pkgfile b/manualPorts/openttd-git/Pkgfile index bbe9838..17f43bc 100644 --- a/manualPorts/openttd-git/Pkgfile +++ b/manualPorts/openttd-git/Pkgfile @@ -5,7 +5,7 @@ # Depends on: libsdl libpng fontconfig lzo name=openttd-git -version=29780.5b1fb9424 +version=29779.8596b43b2 gfxversion=0.5.4 sfxversion=0.2.3 @@ -15,6 +15,8 @@ source=(http://bundles.openttdcoop.org/opengfx/releases/$gfxversion/opengfx-$gfx http://bundles.openttdcoop.org/opensfx/releases/$sfxversion/opensfx-$sfxversion.zip http://bundles.openttdcoop.org/openmsx/releases/$msxversion/openmsx-$msxversion.zip chunnel.patch + chunnel-signaltunnel-pre.patch + chunnel-underground-pre.patch signaltunnel.patch sloped-stations.patch underground.patch @@ -23,6 +25,10 @@ source=(http://bundles.openttdcoop.org/opengfx/releases/$gfxversion/opengfx-$gfx build() { + cp chunnel.patch chunnel.pre.patch + patch -p1 -i chunnel-signaltunnel-pre.patch + patch -p1 -i chunnel-underground-pre.patch + tar -xf opengfx-$gfxversion.tar cd OpenTTD-${version##*.}* @@ -45,7 +51,7 @@ build() { patch -p1 -i "$SRC/signaltunnel.patch" # patch -p1 -i "$SRC/sloped-stations.patch" # broken! patch -p1 -i "$SRC/underground.patch" # broken? - patch -p1 -i "$SRC/chunnel.patch" + patch -p1 -i "$SRC/chunnel.pre.patch" mkdir build cd build diff --git a/manualPorts/openttd-git/chunnel-pre.patch b/manualPorts/openttd-git/chunnel-pre.patch new file mode 100644 index 0000000..9b42f5a --- /dev/null +++ b/manualPorts/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/manualPorts/openttd-git/chunnel-signaltunnel-pre.patch b/manualPorts/openttd-git/chunnel-signaltunnel-pre.patch new file mode 100644 index 0000000..572e405 --- /dev/null +++ b/manualPorts/openttd-git/chunnel-signaltunnel-pre.patch @@ -0,0 +1,22 @@ +--- a/chunnel.pre.patch 2021-01-03 22:39:24.363263631 +0100 ++++ b/chunnel.pre.patch 2021-01-03 22:39:24.363263631 +0100 +@@ -180,16 +180,17 @@ + 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 ++@@ -2724,8 +2725,10 @@ 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_RAILROAD_SIGNAL :Railway tunnel with signal simulation + STR_LAI_TUNNEL_DESCRIPTION_ROAD :Road tunnel + +STR_LAI_TUNNEL_DESCRIPTION_ROAD_CHUNNEL :Road tunnel (underwater) + ++ STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL :Railway bridge with signal simulation + 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 diff --git a/manualPorts/openttd-git/chunnel-underground-pre.patch b/manualPorts/openttd-git/chunnel-underground-pre.patch new file mode 100644 index 0000000..4a055d6 --- /dev/null +++ b/manualPorts/openttd-git/chunnel-underground-pre.patch @@ -0,0 +1,22 @@ +--- a/chunnel.pre.patch 2021-01-03 22:30:58.721115549 +0100 ++++ b/chunnel.pre.patch 2021-01-03 22:30:58.721115549 +0100 +@@ -790,7 +790,7 @@ + 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; +@@ -1015,9 +1015,9 @@ + if (v->type == VEH_EFFECT) { + /* Check whether the vehicle shall be transparent/invisible due to GUI settings. + @@ -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 && diff --git a/manualPorts/openttd-git/chunnel.patch b/manualPorts/openttd-git/chunnel.patch index c26ea89..33ab740 100644 --- a/manualPorts/openttd-git/chunnel.patch +++ b/manualPorts/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()) { |