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..b2ce60b052 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 */
@@ -877,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;
@@ -904,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 */
@@ -1015,6 +1016,26 @@ bool AfterLoadGame()
}
}
+ if (SlXvIsFeatureMissing(XSLFI_MULTIPLE_DOCKS)) {
+ /* 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 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();
+ }
+ }
+ }
+
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_STATION: {
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/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..20e4b111eb 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_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),
@@ -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..41f2fe7343 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,48 @@ 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 = DiagdirBetweenTiles(dock->sloped, dock->flat);
+ 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..cfb464f09f 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,14 @@ 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 = removing_dock->sloped;
+ TileIndex tile2 = removing_dock->flat;
- TileIndex tile1 = st->dock_tile;
- TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
+ DiagDirection direction = DiagdirBetweenTiles(removing_dock->sloped, removing_dock->flat);
+ TileIndex docking_location = removing_dock->flat + TileOffsByDiagDir(direction);
ret = EnsureNoVehicleOnGround(tile1);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
@@ -2700,6 +2713,23 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
if (flags & DC_EXEC) {
ZoningMarkDirtyStationCoverageArea(st);
+
+ 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 +2737,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 +4061,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 +4089,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;