From 1d3cf59d8a06ebf1d11fc3ee00f4f1f42fd42300 Mon Sep 17 00:00:00 2001 From: keldorkatarn Date: Mon, 11 Sep 2017 22:48:19 +0200 Subject: [PATCH 1/5] Allow building multiple docks per station. (cherry picked from commit 0110c4a35d383e0be2cbb53cbe9cbe6784abb3e9) # Conflicts: # src/station_cmd.cpp --- projects/openttd_vs100.vcxproj | 6 ++ projects/openttd_vs100.vcxproj.filters | 18 ++++ projects/openttd_vs140.vcxproj | 6 ++ projects/openttd_vs140.vcxproj.filters | 18 ++++ projects/openttd_vs80.vcproj | 24 ++++++ projects/openttd_vs90.vcproj | 24 ++++++ source.list | 2 + src/base_station_base.h | 10 +++ src/dock.cpp | 37 ++++++++ src/dock_base.h | 40 +++++++++ src/lang/english.txt | 1 + src/order_cmd.cpp | 2 +- src/saveload/afterload.cpp | 22 ++++- src/saveload/oldloader_sl.cpp | 2 +- src/saveload/saveload.cpp | 6 ++ src/saveload/saveload.h | 27 +++--- src/saveload/station_sl.cpp | 53 +++++++++++- src/script/api/ai/ai_station.hpp.sq | 2 +- src/script/api/game/game_station.hpp.sq | 2 +- src/script/api/script_order.cpp | 5 +- src/script/api/script_station.hpp | 4 +- src/ship_cmd.cpp | 42 +++++++++- src/station.cpp | 7 +- src/station_base.h | 5 +- src/station_cmd.cpp | 107 +++++++++++++++++------- src/station_type.h | 2 + 26 files changed, 412 insertions(+), 62 deletions(-) create mode 100644 src/dock.cpp create mode 100644 src/dock_base.h diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 605d5142dd..68d23481b3 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -333,6 +333,7 @@ + @@ -469,6 +470,7 @@ + @@ -610,6 +612,7 @@ + @@ -641,6 +644,7 @@ + @@ -771,6 +775,7 @@ + @@ -864,6 +869,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index da71857c38..83b434cb3a 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -195,6 +195,9 @@ Source Files + + Source Files + Source Files @@ -603,6 +606,9 @@ Header Files + + Header Files + Header Files @@ -1026,6 +1032,9 @@ Header Files + + Header Files + Header Files @@ -1119,6 +1128,9 @@ Header Files + + Header Files + Header Files @@ -1509,6 +1521,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code @@ -1788,6 +1803,9 @@ Command handlers + + Command handlers + Command handlers diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index 806003f8ab..db235a4328 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -350,6 +350,7 @@ + @@ -486,6 +487,7 @@ + @@ -627,6 +629,7 @@ + @@ -658,6 +661,7 @@ + @@ -788,6 +792,7 @@ + @@ -881,6 +886,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index da71857c38..83b434cb3a 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -195,6 +195,9 @@ Source Files + + Source Files + Source Files @@ -603,6 +606,9 @@ Header Files + + Header Files + Header Files @@ -1026,6 +1032,9 @@ Header Files + + Header Files + Header Files @@ -1119,6 +1128,9 @@ Header Files + + Header Files + Header Files @@ -1509,6 +1521,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code @@ -1788,6 +1803,9 @@ Command handlers + + Command handlers + Command handlers diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 230eea467c..722ec6f578 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -554,6 +554,10 @@ RelativePath=".\..\src\disaster_vehicle.cpp" > + + @@ -1102,6 +1106,10 @@ RelativePath=".\..\src\music\dmusic.h" > + + @@ -1666,6 +1674,10 @@ RelativePath=".\..\src\video\sdl_v.h" > + + @@ -1790,6 +1802,10 @@ RelativePath=".\..\src\string_func.h" > + + @@ -2318,6 +2334,10 @@ RelativePath=".\..\src\roadveh_gui.cpp" > + + @@ -2698,6 +2718,10 @@ RelativePath=".\..\src\roadveh_cmd.cpp" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index c161f47197..12672abb71 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -551,6 +551,10 @@ RelativePath=".\..\src\disaster_vehicle.cpp" > + + @@ -1099,6 +1103,10 @@ RelativePath=".\..\src\music\dmusic.h" > + + @@ -1663,6 +1671,10 @@ RelativePath=".\..\src\video\sdl_v.h" > + + @@ -1787,6 +1799,10 @@ RelativePath=".\..\src\string_func.h" > + + @@ -2315,6 +2331,10 @@ RelativePath=".\..\src\roadveh_gui.cpp" > + + @@ -2695,6 +2715,10 @@ RelativePath=".\..\src\roadveh_cmd.cpp" > + + diff --git a/source.list b/source.list index 3b36f0ee0f..27535eb1a1 100644 --- a/source.list +++ b/source.list @@ -30,6 +30,7 @@ dedicated.cpp departures.cpp depot.cpp disaster_vehicle.cpp +dock.cpp driver.cpp economy.cpp effectvehicle.cpp @@ -197,6 +198,7 @@ direction_func.h direction_type.h disaster_vehicle.h music/dmusic.h +dock_base.h driver.h economy_base.h economy_func.h diff --git a/src/base_station_base.h b/src/base_station_base.h index 6d6b20ba3c..1db167ade6 100644 --- a/src/base_station_base.h +++ b/src/base_station_base.h @@ -156,6 +156,16 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> { return (this->facilities & ~FACIL_WAYPOINT) != 0; } + /** + * Check whether the base station has given facilities. + * @param facilities The facilities to check. + * @return True if station has at least one of the given \a facilities. + */ + inline bool HasFacilities(StationFacility facilities) const + { + return (this->facilities & facilities) != 0; + } + static void PostDestructor(size_t index); }; diff --git a/src/dock.cpp b/src/dock.cpp new file mode 100644 index 0000000000..e37ca33d06 --- /dev/null +++ b/src/dock.cpp @@ -0,0 +1,37 @@ +/* $Id: dock.cpp $ */ + +/* +* 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 . +*/ + +/** @file dock.cpp Implementation of the dock base class. */ + +#include "stdafx.h" +#include "core/pool_func.hpp" +#include "dock_base.h" +#include "station_base.h" + +/** The pool of docks. */ +DockPool _dock_pool("Dock"); +INSTANTIATE_POOL_METHODS(Dock) + +/** +* Find a dock at a given tile. +* @param tile Tile with a dock. +* @return The dock in the given tile. +* @pre IsDockTile() +*/ +/* static */ Dock *Dock::GetByTile(TileIndex tile) +{ + const Station *st = Station::GetByTile(tile); + + for (Dock *d = st->GetPrimaryDock();; d = d->next) { + if (d->sloped == tile || d->flat == tile) return d; + assert(d->next != NULL); + } + + NOT_REACHED(); +} diff --git a/src/dock_base.h b/src/dock_base.h new file mode 100644 index 0000000000..95dae6e9ed --- /dev/null +++ b/src/dock_base.h @@ -0,0 +1,40 @@ +/* $Id: dock_base.h $ */ + +/* +* 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 . +*/ + +/** @file dock_base.h Base class for docks. */ + +#ifndef DOCK_BASE_H +#define DOCK_BASE_H + +#include "station_type.h" +#include "tile_type.h" +#include "core/pool_type.hpp" + +typedef Pool DockPool; +extern DockPool _dock_pool; + +/** A Dock structure. */ +struct Dock : DockPool::PoolItem<&_dock_pool> { + TileIndex sloped; ///< The sloped tile of the dock. + TileIndex flat; ///< Position on the map of the flat tile. + Dock *next; ///< Next dock of the given type at this station. + + Dock(TileIndex s = INVALID_TILE, TileIndex f = INVALID_TILE) : sloped(s), flat(f), next(NULL) { } + + ~Dock() {} + + inline Dock *GetNextDock() const { return this->next; } + + static Dock *GetByTile(TileIndex tile); +}; + +#define FOR_ALL_DOCKS_FROM(var, start) FOR_ALL_ITEMS_FROM(Dock, dock_index, var, start) +#define FOR_ALL_DOCKS(var) FOR_ALL_DOCKS_FROM(var, 0) + +#endif /* DOCK_BASE_H */ diff --git a/src/lang/english.txt b/src/lang/english.txt index 5b399e60de..3965eafb87 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4959,6 +4959,7 @@ STR_ERROR_TOO_MANY_BUS_STOPS :{WHITE}Too many STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Too many lorry stations STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION :{WHITE}Too close to another station/loading area STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Too close to another dock +STR_ERROR_TOO_MANY_DOCKS :{WHITE}Too many docks STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Too close to another airport STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Can't rename station... STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... this is a town owned road diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 510bc34ab9..9152ad8be3 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -2525,7 +2525,7 @@ bool ProcessOrders(Vehicle *v) /* If it is unchanged, keep it. */ if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) && - (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->dock_tile != INVALID_TILE)) { + (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->HasFacilities(FACIL_DOCK))) { return false; } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index d9395690ed..7ae2d417d2 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -30,6 +30,7 @@ #include "../station_base.h" #include "../waypoint_base.h" #include "../roadstop_base.h" +#include "../dock_base.h" #include "../tunnelbridge_map.h" #include "../pathfinder/yapf/yapf_cache.h" #include "../elrail_func.h" @@ -728,9 +729,9 @@ bool AfterLoadGame() /* no station is determined by 'tile == INVALID_TILE' now (instead of '0') */ Station *st; FOR_ALL_STATIONS(st) { - if (st->airport.tile == 0) st->airport.tile = INVALID_TILE; - if (st->dock_tile == 0) st->dock_tile = INVALID_TILE; - if (st->train_station.tile == 0) st->train_station.tile = INVALID_TILE; + if (st->airport.tile == 0) st->airport.tile = INVALID_TILE; + if (st->dock_station.tile == 0) st->dock_station.tile = INVALID_TILE; + if (st->train_station.tile == 0) st->train_station.tile = INVALID_TILE; } /* the same applies to Company::location_of_HQ */ @@ -3343,6 +3344,21 @@ bool AfterLoadGame() FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false); } + if (IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_18)) { + /* Dock type has changed. */ + Station *st; + FOR_ALL_STATIONS(st) { + if (st->dock_station.tile == INVALID_TILE) continue; + assert(Dock::CanAllocateItem()); + if (IsOilRig(st->dock_station.tile)) { + /* Set dock station tile to dest tile instead of station. */ + st->docks = new Dock(st->dock_station.tile, st->dock_station.tile + ToTileIndexDiff({1, 0})); + } else { /* A normal two-tiles dock. */ + st->docks = new Dock(st->dock_station.tile, TileAddByDiagDir(st->dock_station.tile, GetDockDirection(st->dock_station.tile))); + } + } + } + // setting moved from game settings to company settings if (SlXvIsFeaturePresent(XSLFI_ORDER_OCCUPANCY, 1, 1)) { Company *c; diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 0c57166816..907f4b2c45 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -728,7 +728,7 @@ static const OldChunks station_chunk[] = { OCL_NULL( 4 ), ///< bus/lorry tile OCL_SVAR( OC_TILE, Station, train_station.tile ), OCL_SVAR( OC_TILE, Station, airport.tile ), - OCL_SVAR( OC_TILE, Station, dock_tile ), + OCL_SVAR( OC_TILE, Station, dock_station.tile), OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Station, train_station.w ), OCL_NULL( 1 ), ///< sort-index, no longer in use diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 2b49459359..f4a2cbc1d5 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -24,6 +24,7 @@ #include "../stdafx.h" #include "../debug.h" #include "../station_base.h" +#include "../dock_base.h" #include "../thread/thread.h" #include "../town.h" #include "../network/network.h" @@ -1344,6 +1345,7 @@ static size_t ReferenceToInt(const void *obj, SLRefType rt) case REF_STORAGE: return ((const PersistentStorage*)obj)->index + 1; case REF_LINK_GRAPH: return ((const LinkGraph*)obj)->index + 1; case REF_LINK_GRAPH_JOB: return ((const LinkGraphJob*)obj)->index + 1; + case REF_DOCKS: return ((const Dock*)obj)->index + 1; default: NOT_REACHED(); } } @@ -1409,6 +1411,10 @@ static void *IntToReference(size_t index, SLRefType rt) if (RoadStop::IsValidID(index)) return RoadStop::Get(index); SlErrorCorrupt("Referencing invalid RoadStop"); + case REF_DOCKS: + if (Dock::IsValidID(index)) return Dock::Get(index); + SlErrorCorrupt("Referencing invalid Dock"); + case REF_ENGINE_RENEWS: if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index); SlErrorCorrupt("Referencing invalid EngineRenew"); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index c866919d39..08a19b0690 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -81,19 +81,20 @@ struct NullStruct { /** Type of reference (#SLE_REF, #SLE_CONDREF). */ enum SLRefType { - REF_ORDER = 0, ///< Load/save a reference to an order. - REF_VEHICLE = 1, ///< Load/save a reference to a vehicle. - REF_STATION = 2, ///< Load/save a reference to a station. - REF_TOWN = 3, ///< Load/save a reference to a town. - REF_VEHICLE_OLD = 4, ///< Load/save an old-style reference to a vehicle (for pre-4.4 savegames). - REF_ROADSTOPS = 5, ///< Load/save a reference to a bus/truck stop. - REF_ENGINE_RENEWS = 6, ///< Load/save a reference to an engine renewal (autoreplace). - REF_CARGO_PACKET = 7, ///< Load/save a reference to a cargo packet. - REF_ORDERLIST = 8, ///< Load/save a reference to an orderlist. - REF_STORAGE = 9, ///< Load/save a reference to a persistent storage. - REF_LINK_GRAPH = 10, ///< Load/save a reference to a link graph. - REF_LINK_GRAPH_JOB = 11, ///< Load/save a reference to a link graph job. - REF_TEMPLATE_VEHICLE = 12, ///< Load/save a reference to a template vehicle + REF_ORDER = 0, ///< Load/save a reference to an order. + REF_VEHICLE = 1, ///< Load/save a reference to a vehicle. + REF_STATION = 2, ///< Load/save a reference to a station. + REF_TOWN = 3, ///< Load/save a reference to a town. + REF_VEHICLE_OLD = 4, ///< Load/save an old-style reference to a vehicle (for pre-4.4 savegames). + REF_ROADSTOPS = 5, ///< Load/save a reference to a bus/truck stop. + REF_ENGINE_RENEWS = 6, ///< Load/save a reference to an engine renewal (autoreplace). + REF_CARGO_PACKET = 7, ///< Load/save a reference to a cargo packet. + REF_ORDERLIST = 8, ///< Load/save a reference to an orderlist. + REF_STORAGE = 9, ///< Load/save a reference to a persistent storage. + REF_LINK_GRAPH = 10, ///< Load/save a reference to a link graph. + REF_LINK_GRAPH_JOB = 11, ///< Load/save a reference to a link graph job. + REF_TEMPLATE_VEHICLE = 12, ///< Load/save a reference to a template vehicle + REF_DOCKS = 13, ///< Load/save a reference to a dock. }; /** Highest possible savegame version. */ diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index af95c4944a..2958075577 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -13,6 +13,7 @@ #include "../station_base.h" #include "../waypoint_base.h" #include "../roadstop_base.h" +#include "../dock_base.h" #include "../vehicle_base.h" #include "../newgrf_station.h" @@ -123,6 +124,11 @@ void AfterLoadStations() Station *sta = Station::From(st); for (const RoadStop *rs = sta->bus_stops; rs != NULL; rs = rs->next) sta->bus_station.Add(rs->xy); for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy); + + for (const Dock *d = sta->docks; d != NULL; d = d->next) { + sta->dock_station.Add(d->sloped); + sta->dock_station.Add(d->flat); + } } StationUpdateCachedTriggers(st); @@ -166,6 +172,14 @@ static const SaveLoad _roadstop_desc[] = { SLE_END() }; +static const SaveLoad _dock_desc[] = { + SLE_VAR(Dock, sloped, SLE_UINT32), + SLE_VAR(Dock, flat, SLE_UINT32), + SLE_REF(Dock, next, REF_DOCKS), + + SLE_END() +}; + static const SaveLoad _old_station_desc[] = { SLE_CONDVAR(Station, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), SLE_CONDVAR(Station, xy, SLE_UINT32, 6, SL_MAX_VERSION), @@ -174,8 +188,8 @@ static const SaveLoad _old_station_desc[] = { SLE_CONDVAR(Station, train_station.tile, SLE_UINT32, 6, SL_MAX_VERSION), SLE_CONDVAR(Station, airport.tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), SLE_CONDVAR(Station, airport.tile, SLE_UINT32, 6, SL_MAX_VERSION), - SLE_CONDVAR(Station, dock_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), - SLE_CONDVAR(Station, dock_tile, SLE_UINT32, 6, SL_MAX_VERSION), + SLE_CONDVAR(Station, dock_station.tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), + SLE_CONDVAR(Station, dock_station.tile, SLE_UINT32, 6, SL_MAX_VERSION), SLE_REF(Station, town, REF_TOWN), SLE_VAR(Station, train_station.w, SLE_FILE_U8 | SLE_VAR_U16), SLE_CONDVAR(Station, train_station.h, SLE_FILE_U8 | SLE_VAR_U16, 2, SL_MAX_VERSION), @@ -425,7 +439,8 @@ static const SaveLoad _station_desc[] = { SLE_REF(Station, bus_stops, REF_ROADSTOPS), SLE_REF(Station, truck_stops, REF_ROADSTOPS), - SLE_VAR(Station, dock_tile, SLE_UINT32), + SLE_CONDVAR(Station, dock_station.tile, SLE_UINT32, 0, SL_PATCH_PACK_1_18 - 1), + SLE_CONDREF(Station, docks, REF_DOCKS, SL_PATCH_PACK_1_18, SL_MAX_VERSION), SLE_VAR(Station, airport.tile, SLE_UINT32), SLE_CONDVAR(Station, airport.w, SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION), SLE_CONDVAR(Station, airport.h, SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION), @@ -638,8 +653,38 @@ static void Ptrs_ROADSTOP() } } +static void Save_DOCK() +{ + Dock *d; + + FOR_ALL_DOCKS(d) { + SlSetArrayIndex(d->index); + SlObject(d, _dock_desc); + } +} + +static void Load_DOCK() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + Dock *d = new (index) Dock(); + + SlObject(d, _dock_desc); + } +} + +static void Ptrs_DOCK() +{ + Dock *d; + FOR_ALL_DOCKS(d) { + SlObject(d, _dock_desc); + } +} + extern const ChunkHandler _station_chunk_handlers[] = { { 'STNS', NULL, Load_STNS, Ptrs_STNS, NULL, CH_ARRAY }, { 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, NULL, CH_ARRAY }, - { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, NULL, CH_ARRAY | CH_LAST}, + { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, NULL, CH_ARRAY}, + { 'DOCK', Save_DOCK, Load_DOCK, Ptrs_DOCK, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/script/api/ai/ai_station.hpp.sq b/src/script/api/ai/ai_station.hpp.sq index af7012d354..9248493195 100644 --- a/src/script/api/ai/ai_station.hpp.sq +++ b/src/script/api/ai/ai_station.hpp.sq @@ -34,10 +34,10 @@ void SQAIStation_Register(Squirrel *engine) ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); - ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_STATIONS_LOADING, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_TRUCK_STOPS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_BUS_STOPS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); + ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_DOCKS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT, ScriptStation::ERR_STATION_TOO_MANY_STATIONS_IN_TOWN); ScriptError::RegisterErrorMapString(ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION, "ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION"); diff --git a/src/script/api/game/game_station.hpp.sq b/src/script/api/game/game_station.hpp.sq index e3a7425caa..fa5f98e40c 100644 --- a/src/script/api/game/game_station.hpp.sq +++ b/src/script/api/game/game_station.hpp.sq @@ -34,10 +34,10 @@ void SQGSStation_Register(Squirrel *engine) ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); - ScriptError::RegisterErrorMap(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK, ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_STATIONS_LOADING, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_TRUCK_STOPS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_BUS_STOPS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); + ScriptError::RegisterErrorMap(STR_ERROR_TOO_MANY_DOCKS, ScriptStation::ERR_STATION_TOO_MANY_STATIONS); ScriptError::RegisterErrorMap(STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT, ScriptStation::ERR_STATION_TOO_MANY_STATIONS_IN_TOWN); ScriptError::RegisterErrorMapString(ScriptStation::ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION, "ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION"); diff --git a/src/script/api/script_order.cpp b/src/script/api/script_order.cpp index 676262dc77..20ba33e5fc 100644 --- a/src/script/api/script_order.cpp +++ b/src/script/api/script_order.cpp @@ -17,6 +17,7 @@ #include "../../debug.h" #include "../../vehicle_base.h" #include "../../roadstop_base.h" +#include "../../dock_base.h" #include "../../depot_base.h" #include "../../station_base.h" #include "../../waypoint_base.h" @@ -260,8 +261,8 @@ static int ScriptOrderPositionToRealOrderPosition(VehicleID vehicle_id, ScriptOr TILE_AREA_LOOP(t, st->train_station) { if (st->TileBelongsToRailStation(t)) return t; } - } else if (st->dock_tile != INVALID_TILE) { - return st->dock_tile; + } else if (st->docks != NULL) { + return st->docks->flat; } else if (st->bus_stops != NULL) { return st->bus_stops->xy; } else if (st->truck_stops != NULL) { diff --git a/src/script/api/script_station.hpp b/src/script/api/script_station.hpp index 8561cd9bdd..05a555a30b 100644 --- a/src/script/api/script_station.hpp +++ b/src/script/api/script_station.hpp @@ -30,10 +30,10 @@ public: ERR_STATION_BASE = ScriptError::ERR_CAT_STATION << ScriptError::ERR_CAT_BIT_SIZE, /** The station is build too close to another station, airport or dock */ - ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION, // [STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT, STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION, STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK] + ERR_STATION_TOO_CLOSE_TO_ANOTHER_STATION, // [STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT, STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION] /** There are too many stations, airports and docks in the game */ - ERR_STATION_TOO_MANY_STATIONS, // [STR_ERROR_TOO_MANY_STATIONS_LOADING, STR_ERROR_TOO_MANY_TRUCK_STOPS, STR_ERROR_TOO_MANY_BUS_STOPS] + ERR_STATION_TOO_MANY_STATIONS, // [STR_ERROR_TOO_MANY_STATIONS_LOADING, STR_ERROR_TOO_MANY_TRUCK_STOPS, STR_ERROR_TOO_MANY_BUS_STOPS, STR_ERROR_TOO_MANY_DOCKS] /** There are too many stations, airports of docks in a town */ ERR_STATION_TOO_MANY_STATIONS_IN_TOWN, // [STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT] diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index d57054af8d..1c3d0f5e8f 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" #include "ship.h" +#include "dock_base.h" #include "landscape.h" #include "timetable.h" #include "news_func.h" @@ -285,13 +286,50 @@ void Ship::PlayLeaveStationSound() const PlayShipSound(this); } +/** + * Of all the docks a station has, return the best destination for a ship. + * @param v The ship. + * @param st Station the ship \a v is heading for. + * @return The free and closest (if none is free, just closest) dock of station \a st to ship \a v. + */ +const Dock* GetBestDock(const Ship *v, const Station *st) +{ + assert(st != NULL && st->HasFacilities(FACIL_DOCK) && st->docks != NULL); + if (st->docks->next == NULL) return st->docks; + + Dock *best_dock = NULL; + uint best_distance = UINT_MAX; + + for (Dock *dock = st->docks; dock != NULL; dock = dock->next) { + uint new_distance = DistanceManhattan(v->tile, dock->flat); + + if (new_distance < best_distance) { + best_dock = dock; + best_distance = new_distance; + } + } + + assert(best_dock != NULL); + + return best_dock; +} + TileIndex Ship::GetOrderStationLocation(StationID station) { if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION; const Station *st = Station::Get(station); - if (st->dock_tile != INVALID_TILE) { - return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile))); + if (st->HasFacilities(FACIL_DOCK)) { + if (st->docks == NULL) { + return st->xy; // A buoy + } else { + const Dock* dock = GetBestDock(this, st); + + DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(dock->sloped)); + direction = ReverseDiagDir(direction); + + return dock->flat + TileOffsByDiagDir(direction); + } } else { this->IncrementRealOrderIndex(); return 0; diff --git a/src/station.cpp b/src/station.cpp index f0124f1f99..e2597c8442 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -22,6 +22,7 @@ #include "core/pool_func.hpp" #include "station_base.h" #include "roadstop_base.h" +#include "dock_base.h" #include "industry.h" #include "core/random_func.hpp" #include "linkgraph/linkgraph.h" @@ -59,7 +60,7 @@ Station::Station(TileIndex tile) : SpecializedStation(tile), bus_station(INVALID_TILE, 0, 0), truck_station(INVALID_TILE, 0, 0), - dock_tile(INVALID_TILE), + dock_station(INVALID_TILE, 0, 0), indtype(IT_INVALID), time_since_load(255), time_since_unload(255), @@ -280,10 +281,10 @@ uint Station::GetCatchmentRadius() const if (this->bus_stops != NULL) ret = max(ret, CA_BUS); if (this->truck_stops != NULL) ret = max(ret, CA_TRUCK); if (this->train_station.tile != INVALID_TILE) ret = max(ret, CA_TRAIN); - if (this->dock_tile != INVALID_TILE) ret = max(ret, CA_DOCK); + if (this->docks != NULL) ret = max(ret, CA_DOCK); if (this->airport.tile != INVALID_TILE) ret = max(ret, this->airport.GetSpec()->catchment); } else { - if (this->bus_stops != NULL || this->truck_stops != NULL || this->train_station.tile != INVALID_TILE || this->dock_tile != INVALID_TILE || this->airport.tile != INVALID_TILE) { + if (this->bus_stops != NULL || this->truck_stops != NULL || this->train_station.tile != INVALID_TILE || this->docks != NULL || this->airport.tile != INVALID_TILE) { ret = CA_UNMODIFIED; } } diff --git a/src/station_base.h b/src/station_base.h index c9fa6f8cb3..1b752924d8 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -458,9 +458,10 @@ public: TileArea bus_station; ///< Tile area the bus 'station' part covers RoadStop *truck_stops; ///< All the truck stops TileArea truck_station; ///< Tile area the truck 'station' part covers + Dock *docks; ///< All the docks + TileArea dock_station; ///< Tile area dock 'station' part covers Airport airport; ///< Tile area the airport covers - TileIndex dock_tile; ///< The location of the dock IndustryType indtype; ///< Industry type to get the name from @@ -490,6 +491,8 @@ public: void RecomputeIndustriesNear(); static void RecomputeIndustriesNearForAll(); + Dock *GetPrimaryDock() const { return docks; } + uint GetCatchmentRadius() const; Rect GetCatchmentRectUsingRadius(uint radius) const; inline Rect GetCatchmentRect() const diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 9c8ec41dce..90a9b1eb22 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -38,6 +38,7 @@ #include "elrail_func.h" #include "station_base.h" #include "roadstop_base.h" +#include "dock_base.h" #include "newgrf_railtype.h" #include "waypoint_base.h" #include "waypoint_func.h" @@ -399,7 +400,7 @@ void Station::GetTileArea(TileArea *ta, StationType type) const case STATION_DOCK: case STATION_OILRIG: - ta->tile = this->dock_tile; + *ta = this->dock_station; break; default: NOT_REACHED(); @@ -2599,41 +2600,43 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR; - DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile)); + TileIndex slope_tile = tile; + + DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(slope_tile)); if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE); direction = ReverseDiagDir(direction); + TileIndex flat_tile = slope_tile + TileOffsByDiagDir(direction); + /* Docks cannot be placed on rapids */ - if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE); + if (HasTileWaterGround(slope_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE); - CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags); + CommandCost ret = CheckIfAuthorityAllowsNewStation(slope_tile, flags); if (ret.Failed()) return ret; - if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (IsBridgeAbove(slope_tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); - ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + ret = DoCommand(slope_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; - TileIndex tile_cur = tile + TileOffsByDiagDir(direction); - - if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) { + if (!IsTileType(flat_tile, MP_WATER) || !IsTileFlat(flat_tile)) { return_cmd_error(STR_ERROR_SITE_UNSUITABLE); } - if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (IsBridgeAbove(flat_tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); /* Get the water class of the water tile before it is cleared.*/ - WaterClass wc = GetWaterClass(tile_cur); + WaterClass wc = GetWaterClass(flat_tile); - ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + ret = DoCommand(flat_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; - tile_cur += TileOffsByDiagDir(direction); - if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) { + TileIndex adjacent_tile = flat_tile + TileOffsByDiagDir(direction); + if (!IsTileType(adjacent_tile, MP_WATER) || !IsTileFlat(adjacent_tile)) { return_cmd_error(STR_ERROR_SITE_UNSUITABLE); } - TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), + TileArea dock_area = TileArea(slope_tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), _dock_w_chk[direction], _dock_h_chk[direction]); /* middle */ @@ -2644,14 +2647,20 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* Distant join */ if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join); + if (!Dock::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_DOCKS); + ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK); if (ret.Failed()) return ret; - if (st != NULL && st->dock_tile != INVALID_TILE) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK); - if (flags & DC_EXEC) { - st->dock_tile = tile; - st->AddFacility(FACIL_DOCK, tile); + /* Create the dock and insert it into the list of docks. */ + Dock *dock = new Dock(slope_tile, flat_tile); + dock->next = st->docks; + st->docks = dock; + + st->dock_station.Add(slope_tile); + st->dock_station.Add(flat_tile); + st->AddFacility(FACIL_DOCK, slope_tile); st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY); @@ -2663,7 +2672,7 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 Company::Get(st->owner)->infrastructure.station += 2; DirtyCompanyInfrastructureWindows(st->owner); - MakeDock(tile, st->owner, st->index, direction, wc); + MakeDock(slope_tile, st->owner, st->index, direction, wc); st->UpdateVirtCoord(); UpdateStationAcceptance(st, false); @@ -2689,10 +2698,16 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags) CommandCost ret = CheckOwnership(st->owner); if (ret.Failed()) return ret; - TileIndex docking_location = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile))); + Dock *removing_dock = Dock::GetByTile(tile); + assert(removing_dock != NULL); - TileIndex tile1 = st->dock_tile; - TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1)); + TileIndex tile1 = removing_dock->sloped; + TileIndex tile2 = removing_dock->flat; + + DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(removing_dock->sloped)); + direction = ReverseDiagDir(direction); + + TileIndex docking_location = removing_dock->flat + TileOffsByDiagDir(direction); ret = EnsureNoVehicleOnGround(tile1); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2); @@ -2700,6 +2715,26 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags) if (flags & DC_EXEC) { ZoningMarkDirtyStationCoverageArea(st); + + st->catchment.AfterRemoveTile(tile1, CA_DOCK); + st->catchment.AfterRemoveTile(tile2, CA_DOCK); + + if (st->docks == removing_dock) { + /* The first dock in the list is removed. */ + st->docks = removing_dock->next; + /* Last dock is removed. */ + if (st->docks == NULL) { + st->facilities &= ~FACIL_DOCK; + } + } else { + /* Tell the predecessor in the list to skip this dock. */ + Dock *pred = st->docks; + while (pred->next != removing_dock) pred = pred->next; + pred->next = removing_dock->next; + } + + delete removing_dock; + DoClearSquare(tile1); MarkTileDirtyByTile(tile1); MakeWaterKeepingClass(tile2, st->owner); @@ -2707,8 +2742,11 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags) st->rect.AfterRemoveTile(st, tile1); st->rect.AfterRemoveTile(st, tile2); - st->dock_tile = INVALID_TILE; - st->facilities &= ~FACIL_DOCK; + st->dock_station.Clear(); + for (Dock *dock = st->docks; dock != NULL; dock = dock->next) { + st->dock_station.Add(dock->flat); + st->dock_station.Add(dock->sloped); + } Company::Get(st->owner)->infrastructure.station -= 2; DirtyCompanyInfrastructureWindows(st->owner); @@ -4028,8 +4066,17 @@ void BuildOilRig(TileIndex tile) st->owner = OWNER_NONE; st->airport.type = AT_OILRIG; st->airport.Add(tile); - st->dock_tile = tile; - st->facilities = FACIL_AIRPORT | FACIL_DOCK; + st->dock_station.tile = tile; + st->facilities = FACIL_AIRPORT; + + if (!Dock::CanAllocateItem()) { + DEBUG(misc, 0, "Can't allocate dock for oilrig at 0x%X, reverting to oilrig with airport only", tile); + } else { + st->docks = new Dock(tile, tile + ToTileIndexDiff({1, 0})); + st->dock_station.tile = tile; + st->facilities |= FACIL_DOCK; + } + st->build_date = _date; st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE); @@ -4047,7 +4094,11 @@ void DeleteOilRig(TileIndex tile) MakeWaterKeepingClass(tile, OWNER_NONE); - st->dock_tile = INVALID_TILE; + st->dock_station.tile = INVALID_TILE; + if (st->docks != NULL) { + delete st->docks; + st->docks = NULL; + } st->airport.Clear(); st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK); st->airport.flags = 0; diff --git a/src/station_type.h b/src/station_type.h index f5e7a8af84..038ab1abbf 100644 --- a/src/station_type.h +++ b/src/station_type.h @@ -19,10 +19,12 @@ typedef uint16 StationID; typedef uint16 RoadStopID; +typedef uint16 DockID; struct BaseStation; struct Station; struct RoadStop; +struct Dock; struct StationSpec; struct Waypoint; From e3b33b45c934dd43681a4b03692c24dd669b6520 Mon Sep 17 00:00:00 2001 From: keldorkatarn Date: Tue, 12 Sep 2017 04:53:59 +0200 Subject: [PATCH 2/5] Simplify direction lookup to also work for oil rigs. (cherry picked from commit acbff5528b6aa5a01d17b814a44b6d884ee03f69) --- src/ship_cmd.cpp | 4 +--- src/station_cmd.cpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 1c3d0f5e8f..41f2fe7343 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -325,9 +325,7 @@ TileIndex Ship::GetOrderStationLocation(StationID station) } else { const Dock* dock = GetBestDock(this, st); - DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(dock->sloped)); - direction = ReverseDiagDir(direction); - + DiagDirection direction = DiagdirBetweenTiles(dock->sloped, dock->flat); return dock->flat + TileOffsByDiagDir(direction); } } else { diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 90a9b1eb22..257318bada 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2704,9 +2704,7 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags) TileIndex tile1 = removing_dock->sloped; TileIndex tile2 = removing_dock->flat; - DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(removing_dock->sloped)); - direction = ReverseDiagDir(direction); - + DiagDirection direction = DiagdirBetweenTiles(removing_dock->sloped, removing_dock->flat); TileIndex docking_location = removing_dock->flat + TileOffsByDiagDir(direction); ret = EnsureNoVehicleOnGround(tile1); From 06abeb45709b8bdb2cfe9b3dd17af7b047231df7 Mon Sep 17 00:00:00 2001 From: keldorkatarn Date: Tue, 12 Sep 2017 06:03:17 +0200 Subject: [PATCH 3/5] Move dock creation code in afterload further up so it runs before the catchment area is created, since that code checks for the presence of the new docks. (cherry picked from commit 80cf10dc0788644ed844b313e5c73dc634f7b43a) # Conflicts: # src/saveload/afterload.cpp --- src/saveload/afterload.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 7ae2d417d2..b8fa99763a 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1016,6 +1016,22 @@ bool AfterLoadGame() } } + if (IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_18)) { + /* Dock type has changed. */ + Station *st; + FOR_ALL_STATIONS(st) { + if (st->dock_station.tile == INVALID_TILE) continue; + assert(Dock::CanAllocateItem()); + if (IsOilRig(st->dock_station.tile)) { + /* Set dock station tile to dest tile instead of station. */ + st->docks = new Dock(st->dock_station.tile, st->dock_station.tile + ToTileIndexDiff({ 1, 0 })); + } + else { /* A normal two-tiles dock. */ + st->docks = new Dock(st->dock_station.tile, TileAddByDiagDir(st->dock_station.tile, GetDockDirection(st->dock_station.tile))); + } + } + } + for (TileIndex t = 0; t < map_size; t++) { switch (GetTileType(t)) { case MP_STATION: { @@ -3344,21 +3360,6 @@ bool AfterLoadGame() FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false); } - if (IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_18)) { - /* Dock type has changed. */ - Station *st; - FOR_ALL_STATIONS(st) { - if (st->dock_station.tile == INVALID_TILE) continue; - assert(Dock::CanAllocateItem()); - if (IsOilRig(st->dock_station.tile)) { - /* Set dock station tile to dest tile instead of station. */ - st->docks = new Dock(st->dock_station.tile, st->dock_station.tile + ToTileIndexDiff({1, 0})); - } else { /* A normal two-tiles dock. */ - st->docks = new Dock(st->dock_station.tile, TileAddByDiagDir(st->dock_station.tile, GetDockDirection(st->dock_station.tile))); - } - } - } - // setting moved from game settings to company settings if (SlXvIsFeaturePresent(XSLFI_ORDER_OCCUPANCY, 1, 1)) { Company *c; From be37aad4703a5b922ed1459676bbd08c863c55dd Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 20 Sep 2017 19:50:53 +0100 Subject: [PATCH 4/5] Update multiple docks to use savegame framework, fix merge conflicts --- src/saveload/afterload.cpp | 6 +++--- src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/saveload/station_sl.cpp | 4 ++-- src/station_cmd.cpp | 3 --- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index b8fa99763a..3a9c22d7a5 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -878,7 +878,7 @@ bool AfterLoadGame() if (st->airport.tile == INVALID_TILE) continue; StringID err = INVALID_STRING_ID; if (st->airport.type == 9) { - if (st->dock_tile != INVALID_TILE && IsOilRig(st->dock_tile)) { + if (st->dock_station.tile != INVALID_TILE && IsOilRig(st->dock_station.tile)) { /* this airport is probably an oil rig, not a huge airport */ } else { err = STR_GAME_SAVELOAD_ERROR_HUGE_AIRPORTS_PRESENT; @@ -905,7 +905,7 @@ bool AfterLoadGame() Aircraft *v; FOR_ALL_AIRCRAFT(v) { Station *st = GetTargetAirportIfValid(v); - if (st != NULL && ((st->dock_tile != INVALID_TILE && IsOilRig(st->dock_tile)) || st->airport.type == AT_OILRIG)) { + if (st != NULL && ((st->dock_station.tile != INVALID_TILE && IsOilRig(st->dock_station.tile)) || st->airport.type == AT_OILRIG)) { /* aircraft is on approach to an oil rig, bail out now */ SetSaveLoadError(STR_GAME_SAVELOAD_ERROR_HELI_OILRIG_BUG); /* Restore the signals */ @@ -1016,7 +1016,7 @@ bool AfterLoadGame() } } - if (IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_18)) { + if (SlXvIsFeatureMissing(XSLFI_MULTIPLE_DOCKS)) { /* Dock type has changed. */ Station *st; FOR_ALL_STATIONS(st) { diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index eebf8dd91c..a0861ab7a1 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -78,6 +78,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_CHUNNEL, XSCF_NULL, 1, 1, "chunnel", NULL, NULL, "TUNN" }, { XSLFI_SCHEDULED_DISPATCH, XSCF_NULL, 1, 1, "scheduled_dispatch", NULL, NULL, NULL }, { XSLFI_MORE_TOWN_GROWTH_RATES, XSCF_NULL, 1, 1, "more_town_growth_rates", NULL, NULL, NULL }, + { XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 1, 1, "multiple_docks", NULL, NULL, "DOCK" }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index dbd0b7e7c8..89c84fe346 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -52,6 +52,7 @@ enum SlXvFeatureIndex { XSLFI_CHUNNEL, ///< Tunnels under water (channel tunnel) XSLFI_SCHEDULED_DISPATCH, ///< Scheduled vehicle dispatching XSLFI_MORE_TOWN_GROWTH_RATES, ///< More town growth rates + XSLFI_MULTIPLE_DOCKS, ///< Multiple docks XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 2958075577..20e4b111eb 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -439,8 +439,8 @@ static const SaveLoad _station_desc[] = { SLE_REF(Station, bus_stops, REF_ROADSTOPS), SLE_REF(Station, truck_stops, REF_ROADSTOPS), - SLE_CONDVAR(Station, dock_station.tile, SLE_UINT32, 0, SL_PATCH_PACK_1_18 - 1), - SLE_CONDREF(Station, docks, REF_DOCKS, SL_PATCH_PACK_1_18, SL_MAX_VERSION), + SLE_CONDVAR_X(Station, dock_station.tile, SLE_UINT32, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_MULTIPLE_DOCKS, 0, 0)), + SLE_CONDREF_X(Station, docks, REF_DOCKS, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_MULTIPLE_DOCKS, 1)), SLE_VAR(Station, airport.tile, SLE_UINT32), SLE_CONDVAR(Station, airport.w, SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION), SLE_CONDVAR(Station, airport.h, SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION), diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 257318bada..cfb464f09f 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2714,9 +2714,6 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags) if (flags & DC_EXEC) { ZoningMarkDirtyStationCoverageArea(st); - st->catchment.AfterRemoveTile(tile1, CA_DOCK); - st->catchment.AfterRemoveTile(tile2, CA_DOCK); - if (st->docks == removing_dock) { /* The first dock in the list is removed. */ st->docks = removing_dock->next; From a9ca7c1eadec6badb698bd69198ac2a4b30e057d Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 20 Sep 2017 19:51:25 +0100 Subject: [PATCH 5/5] Fix crash when loading old savegames with buoys --- src/saveload/afterload.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 3a9c22d7a5..b2ce60b052 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1025,9 +1025,13 @@ bool AfterLoadGame() if (IsOilRig(st->dock_station.tile)) { /* Set dock station tile to dest tile instead of station. */ st->docks = new Dock(st->dock_station.tile, st->dock_station.tile + ToTileIndexDiff({ 1, 0 })); - } - else { /* A normal two-tiles dock. */ + } else if (IsDock(st->dock_station.tile)) { + /* A normal two-tiles dock. */ st->docks = new Dock(st->dock_station.tile, TileAddByDiagDir(st->dock_station.tile, GetDockDirection(st->dock_station.tile))); + } else if (IsBuoy(st->dock_station.tile)) { + /* A buoy. */ + } else { + NOT_REACHED(); } } }