changeset 14256:82f1453a12d5 draft

(svn r18807) -Codechange: introduce AirportSpec and move several non-statemachine-related variables to there
author yexo <yexo@openttd.org>
date Fri, 15 Jan 2010 12:08:08 +0000
parents 6c9e788a2c57
children 40b920f51dd7
files projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/ai/api/ai_airport.cpp src/ai/api/ai_depotlist.cpp src/ai/api/ai_order.cpp src/aircraft_cmd.cpp src/airport.cpp src/airport.h src/airport_gui.cpp src/order_cmd.cpp src/station.cpp src/station_base.h src/station_cmd.cpp src/table/airport_defaults.h src/water_cmd.cpp
diffstat 16 files changed, 557 insertions(+), 287 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -2168,6 +2168,10 @@
 			Name="Tables"
 			>
 			<File
+				RelativePath=".\..\src\table\airport_defaults.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\table\airport_movement.h"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -2165,6 +2165,10 @@
 			Name="Tables"
 			>
 			<File
+				RelativePath=".\..\src\table\airport_defaults.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\table\airport_movement.h"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -472,6 +472,7 @@
 saveload/waypoint_sl.cpp
 
 # Tables
+table/airport_defaults.h
 table/airport_movement.h
 table/animcursors.h
 table/autorail.h
--- a/src/ai/api/ai_airport.cpp
+++ b/src/ai/api/ai_airport.cpp
@@ -17,7 +17,7 @@
 
 /* static */ bool AIAirport::IsValidAirportType(AirportType type)
 {
-	return IsAirportInformationAvailable(type) && ::GetAirport(type)->IsAvailable();
+	return IsAirportInformationAvailable(type) && ::AirportSpec::Get(type)->IsAvailable();
 }
 
 /* static */ bool AIAirport::IsAirportInformationAvailable(AirportType type)
@@ -29,8 +29,8 @@
 {
 	if (!IsValidAirportType(type)) return -1;
 
-	const AirportFTAClass *afc = ::GetAirport(type);
-	return _price[PR_BUILD_STATION_AIRPORT] * afc->size_x * afc->size_y;
+	const AirportSpec *as = ::AirportSpec::Get(type);
+	return _price[PR_BUILD_STATION_AIRPORT] * as->size_x * as->size_y;
 }
 
 /* static */ bool AIAirport::IsHangarTile(TileIndex tile)
@@ -51,21 +51,21 @@
 {
 	if (!IsAirportInformationAvailable(type)) return -1;
 
-	return ::GetAirport(type)->size_x;
+	return ::AirportSpec::Get(type)->size_x;
 }
 
 /* static */ int32 AIAirport::GetAirportHeight(AirportType type)
 {
 	if (!IsAirportInformationAvailable(type)) return -1;
 
-	return ::GetAirport(type)->size_y;
+	return ::AirportSpec::Get(type)->size_y;
 }
 
 /* static */ int32 AIAirport::GetAirportCoverageRadius(AirportType type)
 {
 	if (!IsAirportInformationAvailable(type)) return -1;
 
-	return _settings_game.station.modified_catchment ? ::GetAirport(type)->catchment : (uint)CA_UNMODIFIED;
+	return _settings_game.station.modified_catchment ? ::AirportSpec::Get(type)->catchment : (uint)CA_UNMODIFIED;
 }
 
 /* static */ bool AIAirport::BuildAirport(TileIndex tile, AirportType type, StationID station_id)
@@ -96,7 +96,7 @@
 	if (st->owner != _current_company) return -1;
 	if ((st->facilities & FACIL_AIRPORT) == 0) return -1;
 
-	return st->Airport()->nof_depots;
+	return st->GetAirportSpec()->nof_depots;
 }
 
 /* static */ TileIndex AIAirport::GetHangarOfAirport(TileIndex tile)
@@ -109,7 +109,7 @@
 	if (st->owner != _current_company) return INVALID_TILE;
 	if ((st->facilities & FACIL_AIRPORT) == 0) return INVALID_TILE;
 
-	return ::ToTileIndexDiff(st->Airport()->airport_depots[0]) + st->airport_tile;
+	return ::ToTileIndexDiff(st->GetAirportSpec()->depot_table[0]) + st->airport_tile;
 }
 
 /* static */ AIAirport::AirportType AIAirport::GetAirportType(TileIndex tile)
@@ -126,16 +126,16 @@
 
 /* static */ int AIAirport::GetNoiseLevelIncrease(TileIndex tile, AirportType type)
 {
-	extern Town *AirportGetNearestTown(const AirportFTAClass *afc, TileIndex airport_tile);
-	extern uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
+	extern Town *AirportGetNearestTown(const AirportSpec *as, TileIndex airport_tile);
+	extern uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, TileIndex town_tile, TileIndex tile);
 
 	if (!::IsValidTile(tile)) return -1;
 	if (!IsValidAirportType(type)) return -1;
 
 	if (_settings_game.economy.station_noise_level) {
-		const AirportFTAClass *afc = ::GetAirport(type);
-		const Town *t = AirportGetNearestTown(afc, tile);
-		return GetAirportNoiseLevelForTown(afc, t->xy, tile);
+		const AirportSpec *as = ::AirportSpec::Get(type);
+		const Town *t = AirportGetNearestTown(as, tile);
+		return GetAirportNoiseLevelForTown(as, t->xy, tile);
 	}
 
 	return 1;
@@ -143,10 +143,10 @@
 
 /* static */ TownID AIAirport::GetNearestTown(TileIndex tile, AirportType type)
 {
-	extern Town *AirportGetNearestTown(const AirportFTAClass *afc, TileIndex airport_tile);
+	extern Town *AirportGetNearestTown(const AirportSpec *as, TileIndex airport_tile);
 
 	if (!::IsValidTile(tile)) return INVALID_TOWN;
 	if (!IsAirportInformationAvailable(type)) return INVALID_TOWN;
 
-	return AirportGetNearestTown(GetAirport(type), tile)->index;
+	return AirportGetNearestTown(AirportSpec::Get(type), tile)->index;
 }
--- a/src/ai/api/ai_depotlist.cpp
+++ b/src/ai/api/ai_depotlist.cpp
@@ -29,9 +29,9 @@
 			const Station *st;
 			FOR_ALL_STATIONS(st) {
 				if (st->owner == ::_current_company) {
-					const AirportFTAClass *afc = st->Airport();
-					for (uint i = 0; i < afc->nof_depots; i++) {
-						this->AddItem(st->airport_tile + ToTileIndexDiff(afc->airport_depots[i]));
+					const AirportSpec *as = st->GetAirportSpec();
+					for (uint i = 0; i < as->nof_depots; i++) {
+						this->AddItem(st->airport_tile + ToTileIndexDiff(as->depot_table[i]));
 					}
 				}
 			}
--- a/src/ai/api/ai_order.cpp
+++ b/src/ai/api/ai_order.cpp
@@ -181,9 +181,9 @@
 			if (v->type != VEH_AIRCRAFT) return ::Depot::Get(order->GetDestination())->xy;
 			/* Aircraft's hangars are referenced by StationID, not DepotID */
 			const Station *st = ::Station::Get(order->GetDestination());
-			const AirportFTAClass *airport = st->Airport();
-			if (airport == NULL || airport->nof_depots == 0) return INVALID_TILE;
-			return st->airport_tile + ::ToTileIndexDiff(st->Airport()->airport_depots[0]);
+			const AirportSpec *as = st->GetAirportSpec();
+			if (as == NULL || as->nof_depots == 0) return INVALID_TILE;
+			return st->airport_tile + ::ToTileIndexDiff(as->depot_table[0]);
 		}
 
 		case OT_GOTO_STATION: {
@@ -200,8 +200,8 @@
 			} else if (st->truck_stops != NULL) {
 				return st->truck_stops->xy;
 			} else if (st->airport_tile != INVALID_TILE) {
-				const AirportFTAClass *fta = st->Airport();
-				TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile) {
+				const AirportSpec *as = st->GetAirportSpec();
+				TILE_LOOP(tile, as->size_x, as->size_y, st->airport_tile) {
 					if (!::IsHangar(tile)) return tile;
 				}
 			}
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -116,7 +116,8 @@
 		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
 
 		const AirportFTAClass *afc = st->Airport();
-		if (afc->nof_depots == 0 || (
+		const AirportSpec *as = st->GetAirportSpec();
+		if (as->nof_depots == 0 || (
 					/* don't crash the plane if we know it can't land at the airport */
 					(afc->flags & AirportFTAClass::SHORT_STRIP) &&
 					(avi->subtype & AIR_FAST) &&
@@ -332,10 +333,11 @@
 		 * of all depots, it is simple */
 		for (uint i = 0;; i++) {
 			const Station *st = Station::GetByTile(tile);
+			const AirportSpec *as = st->GetAirportSpec();
 			const AirportFTAClass *apc = st->Airport();
 
-			assert(i != apc->nof_depots);
-			if (st->airport_tile + ToTileIndexDiff(apc->airport_depots[i]) == tile) {
+			assert(i != as->nof_depots);
+			if (st->airport_tile + ToTileIndexDiff(as->depot_table[i]) == tile) {
 				assert(apc->layout[i].heading == HANGAR);
 				v->pos = apc->layout[i].position;
 				break;
@@ -436,7 +438,7 @@
 {
 	const Station *st = GetTargetAirportIfValid(this);
 	/* If the station is not a valid airport or if it has no hangars */
-	if (st == NULL || st->Airport()->nof_depots == 0) {
+	if (st == NULL || st->GetAirportSpec()->nof_depots == 0) {
 		/* the aircraft has to search for a hangar on its own */
 		StationID station = FindNearestHangar(this);
 
@@ -1474,7 +1476,7 @@
 			return;
 		default:  // orders have been deleted (no orders), goto depot and don't bother us
 			v->current_order.Free();
-			go_to_hangar = Station::Get(v->targetairport)->Airport()->nof_depots != 0;
+			go_to_hangar = Station::Get(v->targetairport)->GetAirportSpec()->nof_depots != 0;
 	}
 
 	if (go_to_hangar) {
@@ -1615,7 +1617,8 @@
 	if (v->current_order.IsType(OT_GOTO_STATION)) {
 		if (AirportFindFreeHelipad(v, apc)) return;
 	}
-	v->state = (apc->nof_depots != 0) ? HANGAR : HELITAKEOFF;
+	const AirportSpec *as = Station::Get(v->targetairport)->GetAirportSpec();
+	v->state = (as->nof_depots != 0) ? HANGAR : HELITAKEOFF;
 }
 
 typedef void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc);
--- a/src/airport.cpp
+++ b/src/airport.cpp
@@ -122,98 +122,9 @@
 	/* 141-143 used for flag animation */
 };
 
-/** Tiles for Country Airfield (small) */
-static const byte _airport_sections_country[] = {
-	APT_SMALL_BUILDING_1,     APT_SMALL_BUILDING_2,    APT_SMALL_BUILDING_3,    APT_SMALL_DEPOT_SE,
-	APT_GRASS_FENCE_NE_FLAG,  APT_GRASS_1,             APT_GRASS_2,             APT_GRASS_FENCE_SW,
-	APT_RUNWAY_SMALL_FAR_END, APT_RUNWAY_SMALL_MIDDLE, APT_RUNWAY_SMALL_MIDDLE, APT_RUNWAY_SMALL_NEAR_END
-};
-
-/** Tiles for City Airport (large) */
-static const byte _airport_sections_town[] = {
-	APT_BUILDING_1,           APT_APRON_FENCE_NW, APT_STAND_1,              APT_APRON_FENCE_NW,       APT_APRON_FENCE_NW, APT_DEPOT_SE,
-	APT_BUILDING_2,           APT_PIER,           APT_ROUND_TERMINAL,       APT_STAND_PIER_NE,        APT_APRON,          APT_APRON_FENCE_SW,
-	APT_BUILDING_3,           APT_STAND,          APT_PIER_NW_NE,           APT_APRON_S,              APT_APRON_HOR,      APT_APRON_N_FENCE_SW,
-	APT_RADIO_TOWER_FENCE_NE, APT_APRON_W,        APT_APRON_VER_CROSSING_S, APT_APRON_HOR_CROSSING_E, APT_ARPON_N,        APT_TOWER_FENCE_SW,
-	APT_EMPTY_FENCE_NE,       APT_APRON_S,        APT_APRON_HOR_CROSSING_W, APT_APRON_VER_CROSSING_N, APT_APRON_E,        APT_RADAR_GRASS_FENCE_SW,
-	APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_1,       APT_RUNWAY_2,             APT_RUNWAY_3,             APT_RUNWAY_4,       APT_RUNWAY_END_FENCE_SE
-};
-
-/** Tiles for Metropolitain Airport (large) - 2 runways */
-static const byte _airport_sections_metropolitan[] = {
-	APT_BUILDING_1,           APT_APRON_FENCE_NW, APT_STAND_1,        APT_APRON_FENCE_NW, APT_APRON_FENCE_NW, APT_DEPOT_SE,
-	APT_BUILDING_2,           APT_PIER,           APT_ROUND_TERMINAL, APT_STAND_PIER_NE,  APT_APRON,          APT_APRON_FENCE_SW,
-	APT_BUILDING_3,           APT_STAND,          APT_PIER_NW_NE,     APT_APRON_S,        APT_APRON_HOR,      APT_APRON_N_FENCE_SW,
-	APT_RADAR_FENCE_NE,       APT_APRON,          APT_APRON,          APT_APRON,          APT_APRON,          APT_TOWER_FENCE_SW,
-	APT_RUNWAY_END,           APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_END,
-	APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_END_FENCE_SE
-};
-
-/** Tiles for International Airport (large) - 2 runways */
-static const byte _airport_sections_international[] = {
-	APT_RUNWAY_END_FENCE_NW,  APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_END_FENCE_NW,
-	APT_RADIO_TOWER_FENCE_NE, APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_DEPOT_SE,
-	APT_BUILDING_3,           APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_APRON_FENCE_SW,
-	APT_DEPOT_SE,             APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_HELIPAD_1,
-	APT_APRON_FENCE_NE,       APT_APRON,           APT_STAND,           APT_TOWER,           APT_STAND,           APT_APRON,           APT_HELIPAD_1,
-	APT_APRON_FENCE_NE,       APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_RADAR_FENCE_SW,
-	APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE
-};
+#include "table/airport_defaults.h"
 
-/** Tiles for Intercontinental Airport (vlarge) - 4 runways */
-static const byte _airport_sections_intercontinental[] = {
-	APT_RADAR_FENCE_NE,         APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW,        APT_RUNWAY_END_FENCE_NW_SW,
-	APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_2,               APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE_SW, APT_APRON_FENCE_NE_SW,
-	APT_APRON_FENCE_NE,         APT_SMALL_BUILDING_1,       APT_APRON_FENCE_NE,  APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_RADIO_TOWER_FENCE_NE,   APT_APRON_FENCE_NE_SW,
-	APT_APRON_FENCE_NE,         APT_APRON_HALF_EAST,        APT_APRON_FENCE_NE,  APT_TOWER,           APT_HELIPAD_2,       APT_HELIPAD_2,       APT_APRON,           APT_APRON_FENCE_NW,         APT_APRON_FENCE_SW,
-	APT_APRON_FENCE_NE,         APT_APRON,                  APT_APRON,           APT_STAND,           APT_BUILDING_1,      APT_STAND,           APT_APRON,           APT_LOW_BUILDING,           APT_DEPOT_SE,
-	APT_DEPOT_SE,               APT_LOW_BUILDING,           APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_APRON,                  APT_APRON_FENCE_SW,
-	APT_APRON_FENCE_NE,         APT_APRON,                  APT_APRON,           APT_STAND,           APT_BUILDING_3,      APT_STAND,           APT_APRON,           APT_APRON,                  APT_APRON_FENCE_SW,
-	APT_APRON_FENCE_NE,         APT_APRON_FENCE_SE,         APT_APRON,           APT_STAND,           APT_ROUND_TERMINAL,  APT_STAND,           APT_APRON_FENCE_SW,  APT_APRON_HALF_WEST,        APT_APRON_FENCE_SW,
-	APT_APRON_FENCE_NE,         APT_GRASS_FENCE_NE_FLAG_2,  APT_APRON_FENCE_NE,  APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON_FENCE_SW,  APT_EMPTY,                  APT_APRON_FENCE_NE_SW,
-	APT_APRON_FENCE_NE,         APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW,        APT_RUNWAY_END_FENCE_SE_SW,
-	APT_RUNWAY_END_FENCE_NE_SE, APT_RUNWAY_2,               APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE_SW, APT_EMPTY
-};
-
-
-/** Tiles for Commuter Airfield (small) */
-static const byte _airport_sections_commuter[] = {
-	APT_TOWER,               APT_BUILDING_3, APT_HELIPAD_2_FENCE_NW, APT_HELIPAD_2_FENCE_NW, APT_DEPOT_SE,
-	APT_APRON_FENCE_NE,      APT_APRON,      APT_APRON,              APT_APRON,              APT_APRON_FENCE_SW,
-	APT_APRON_FENCE_NE,      APT_STAND,      APT_STAND,              APT_STAND,              APT_APRON_FENCE_SW,
-	APT_RUNWAY_END_FENCE_SE, APT_RUNWAY_2,   APT_RUNWAY_2,           APT_RUNWAY_2,           APT_RUNWAY_END_FENCE_SE
-};
-
-/** Tiles for Heliport */
-static const byte _airport_sections_heliport[] = {
-	APT_HELIPORT,
-};
-
-/** Tiles for Helidepot */
-static const byte _airport_sections_helidepot[] = {
-	APT_LOW_BUILDING_FENCE_N,  APT_DEPOT_SE,
-	APT_HELIPAD_2_FENCE_NE_SE, APT_APRON_FENCE_SE_SW
-};
-
-/** Tiles for Helistation */
-static const byte _airport_sections_helistation[] = {
-	APT_DEPOT_SE,          APT_LOW_BUILDING_FENCE_NW, APT_HELIPAD_3_FENCE_NW, APT_HELIPAD_3_FENCE_NW_SW,
-	APT_APRON_FENCE_NE_SE, APT_APRON_FENCE_SE,        APT_APRON_FENCE_SE,     APT_HELIPAD_3_FENCE_SE_SW
-};
-
-const byte * const _airport_sections[] = {
-	_airport_sections_country,           // Country Airfield (small)
-	_airport_sections_town,              // City Airport (large)
-	_airport_sections_heliport,          // Heliport
-	_airport_sections_metropolitan,      // Metropolitain Airport (large)
-	_airport_sections_international,     // International Airport (xlarge)
-	_airport_sections_commuter,          // Commuter Airport (small)
-	_airport_sections_helidepot,         // Helidepot
-	_airport_sections_intercontinental,  // Intercontinental Airport (xxlarge)
-	_airport_sections_helistation,       // Helistation
-};
-
-assert_compile(NUM_AIRPORTS == lengthof(_airport_sections));
+AirportSpec AirportSpec::dummy = {NULL, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR};
 
 /* Uncomment this to print out a full report of the airport-structure
  * You should either use
@@ -244,12 +155,7 @@
 		_airport_entries_dummy,
 		AirportFTAClass::ALL,
 		_airport_fta_dummy,
-		NULL,
-		0,
-		0, 0, 0,
-		0,
-		0,
-		MAX_YEAR + 1, MAX_YEAR + 1
+		0
 	);
 
 	_country_airport = new AirportFTAClass(
@@ -259,12 +165,7 @@
 		_airport_entries_country,
 		AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
 		_airport_fta_country,
-		_airport_depots_country,
-		lengthof(_airport_depots_country),
-		4, 3, 3,
-		0,
-		4,
-		0, 1959
+		0
 	);
 
 	_city_airport = new AirportFTAClass(
@@ -274,12 +175,7 @@
 		_airport_entries_city,
 		AirportFTAClass::ALL,
 		_airport_fta_city,
-		_airport_depots_city,
-		lengthof(_airport_depots_city),
-		6, 6, 5,
-		0,
-		5,
-		1955, MAX_YEAR
+		0
 	);
 
 	_metropolitan_airport = new AirportFTAClass(
@@ -289,12 +185,7 @@
 		_airport_entries_metropolitan,
 		AirportFTAClass::ALL,
 		_airport_fta_metropolitan,
-		_airport_depots_metropolitan,
-		lengthof(_airport_depots_metropolitan),
-		6, 6, 8,
-		0,
-		6,
-		1980, MAX_YEAR
+		0
 	);
 
 	_international_airport = new AirportFTAClass(
@@ -304,12 +195,7 @@
 		_airport_entries_international,
 		AirportFTAClass::ALL,
 		_airport_fta_international,
-		_airport_depots_international,
-		lengthof(_airport_depots_international),
-		7, 7, 17,
-		0,
-		8,
-		1990, MAX_YEAR
+		0
 	);
 
 	_intercontinental_airport = new AirportFTAClass(
@@ -319,12 +205,7 @@
 		_airport_entries_intercontinental,
 		AirportFTAClass::ALL,
 		_airport_fta_intercontinental,
-		_airport_depots_intercontinental,
-		lengthof(_airport_depots_intercontinental),
-		9, 11, 25,
-		0,
-		10,
-		2002, MAX_YEAR
+		0
 	);
 
 	_heliport = new AirportFTAClass(
@@ -334,12 +215,7 @@
 		_airport_entries_heliport_oilrig,
 		AirportFTAClass::HELICOPTERS,
 		_airport_fta_heliport_oilrig,
-		NULL,
-		0,
-		1, 1, 1,
-		60,
-		4,
-		1963, MAX_YEAR
+		60
 	);
 
 	_oilrig = new AirportFTAClass(
@@ -349,12 +225,7 @@
 		_airport_entries_heliport_oilrig,
 		AirportFTAClass::HELICOPTERS,
 		_airport_fta_heliport_oilrig,
-		NULL,
-		0,
-		1, 1, 0,
-		54,
-		3,
-		MAX_YEAR + 1, MAX_YEAR + 1
+		54
 	);
 
 	_commuter_airport = new AirportFTAClass(
@@ -364,12 +235,7 @@
 		_airport_entries_commuter,
 		AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
 		_airport_fta_commuter,
-		_airport_depots_commuter,
-		lengthof(_airport_depots_commuter),
-		5, 4, 4,
-		0,
-		4,
-		1983, MAX_YEAR
+		0
 	);
 
 	_heli_depot = new AirportFTAClass(
@@ -379,12 +245,7 @@
 		_airport_entries_helidepot,
 		AirportFTAClass::HELICOPTERS,
 		_airport_fta_helidepot,
-		_airport_depots_helidepot,
-		lengthof(_airport_depots_helidepot),
-		2, 2, 2,
-		0,
-		4,
-		1976, MAX_YEAR
+		0
 	);
 
 	_heli_station = new AirportFTAClass(
@@ -394,12 +255,7 @@
 		_airport_entries_helistation,
 		AirportFTAClass::HELICOPTERS,
 		_airport_fta_helistation,
-		_airport_depots_helistation,
-		lengthof(_airport_depots_helistation),
-		4, 2, 3,
-		0,
-		4,
-		1980, MAX_YEAR
+		0
 	);
 }
 
@@ -435,31 +291,15 @@
 	const byte *entry_points_,
 	Flags flags_,
 	const AirportFTAbuildup *apFA,
-	const TileIndexDiffC *depots_,
-	const byte nof_depots_,
-	uint size_x_,
-	uint size_y_,
-	byte noise_level_,
-	byte delta_z_,
-	byte catchment_,
-	Year first_available_,
-	Year last_available_
+	byte delta_z_
 ) :
 	moving_data(moving_data_),
 	terminals(terminals_),
 	helipads(helipads_),
-	airport_depots(depots_),
 	flags(flags_),
-	nof_depots(nof_depots_),
 	nofelements(AirportGetNofElements(apFA)),
 	entry_points(entry_points_),
-	size_x(size_x_),
-	size_y(size_y_),
-	noise_level(noise_level_),
-	delta_z(delta_z_),
-	catchment(catchment_),
-	first_available(first_available_),
-	last_available(last_available_)
+	delta_z(delta_z_)
 {
 	byte nofterminalgroups, nofhelipadgroups;
 
@@ -519,11 +359,11 @@
 	free(layout);
 }
 
-bool AirportFTAClass::IsAvailable() const
+bool AirportSpec::IsAvailable() const
 {
-	if (_cur_year < this->first_available) return false;
+	if (_cur_year < this->min_year) return false;
 	if (_settings_game.station.never_expire_airports) return true;
-	return _cur_year <= this->last_available;
+	return _cur_year <= this->max_year;
 }
 
 /** Get the number of elements of a source Airport state automata
--- a/src/airport.h
+++ b/src/airport.h
@@ -40,6 +40,40 @@
 	AT_DUMMY         = 255
 };
 
+/* Copy from station_map.h */
+typedef byte StationGfx;
+
+struct AirportTileTable {
+	TileIndexDiffC ti;
+	StationGfx gfx;
+};
+
+/**
+ * Defines the data structure for an airport.
+ */
+struct AirportSpec {
+	const AirportTileTable * const *table; ///< list of the tiles composing the airport
+	const TileIndexDiffC *depot_table;     ///< gives the position of the depots on the airports
+	byte nof_depots;                       ///< the number of depots in this airport
+	byte size_x;                           ///< size of airport in x direction
+	byte size_y;                           ///< size of airport in y direction
+	byte noise_level;                      ///< noise that this airport generates
+	byte catchment;                        ///< catchment area of this airport
+	Year min_year;                         ///< first year the airport is available
+	Year max_year;                         ///< last year the airport is available
+
+	static AirportSpec *Get(byte type)
+	{
+		assert(type < NUM_AIRPORTS);
+		extern AirportSpec _origin_airport_specs[NUM_AIRPORTS];
+		return &_origin_airport_specs[type];
+	}
+
+	bool IsAvailable() const;
+
+	static AirportSpec dummy;
+};
+
 
 enum {
 	AMED_NOSPDCLAMP = 1 << 0,
@@ -153,15 +187,7 @@
 		const byte *entry_points,
 		Flags flags,
 		const AirportFTAbuildup *apFA,
-		const TileIndexDiffC *depots,
-		byte nof_depots,
-		uint size_x,
-		uint size_y,
-		uint8 noise_level,
-		byte delta_z,
-		byte catchment,
-		Year first_available,
-		Year last_available
+		byte delta_z
 	);
 
 	~AirportFTAClass();
@@ -172,25 +198,14 @@
 		return &moving_data[position];
 	}
 
-	/** Is this airport available at this date? */
-	bool IsAvailable() const;
-
 	const AirportMovingData *moving_data;
 	struct AirportFTA *layout;            ///< state machine for airport
 	const byte *terminals;
 	const byte *helipads;
-	const TileIndexDiffC *airport_depots; ///< gives the position of the depots on the airports
 	Flags flags;
-	byte nof_depots;                      ///< number of depots this airport has
 	byte nofelements;                     ///< number of positions the airport consists of
 	const byte *entry_points;             ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
-	byte size_x;
-	byte size_y;
-	uint8 noise_level;                    ///< noise that this airport generates
 	byte delta_z;                         ///< Z adjustment for helicopter pads
-	byte catchment;
-	Year first_available;                 ///< the year this airport becomes available
-	Year last_available;                  ///< the year this airport expires
 };
 
 DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags)
--- a/src/airport_gui.cpp
+++ b/src/airport_gui.cpp
@@ -202,8 +202,8 @@
 	{
 		this->DrawWidgets();
 
-		const AirportFTAClass *airport = GetAirport(_selected_airport_type);
-		int rad = _settings_game.station.modified_catchment ? airport->catchment : (uint)CA_UNMODIFIED;
+		const AirportSpec *as = AirportSpec::Get(_selected_airport_type);
+		int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
 
 		uint16 top = this->GetWidget<NWidgetBase>(BAW_BTN_DOHILIGHT)->pos_y + this->GetWidget<NWidgetBase>(BAW_BTN_DOHILIGHT)->current_y + WD_PAR_VSEP_NORMAL;
 		NWidgetBase *panel_nwi = this->GetWidget<NWidgetBase>(BAW_BOTTOMPANEL);
@@ -212,7 +212,7 @@
 		/* only show the station (airport) noise, if the noise option is activated */
 		if (_settings_game.economy.station_noise_level) {
 			/* show the noise of the selected airport */
-			SetDParam(0, airport->noise_level);
+			SetDParam(0, as->noise_level);
 			DrawString(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_STATION_BUILD_NOISE);
 			top += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
 		}
@@ -232,10 +232,10 @@
 		_selected_airport_type = airport_id;
 		this->LowerWidget(airport_id + BAW_SMALL_AIRPORT);
 
-		const AirportFTAClass *airport = GetAirport(airport_id);
-		SetTileSelectSize(airport->size_x, airport->size_y);
+		const AirportSpec *as = AirportSpec::Get(airport_id);
+		SetTileSelectSize(as->size_x, as->size_y);
 
-		int rad = _settings_game.station.modified_catchment ? airport->catchment : (uint)CA_UNMODIFIED;
+		int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
 		if (_settings_client.gui.station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
 
 		this->SetDirty();
@@ -243,16 +243,16 @@
 
 	virtual void OnInvalidateData(int data = 0)
 	{
-		if (!GetAirport(_selected_airport_type)->IsAvailable()) {
+		if (!AirportSpec::Get(_selected_airport_type)->IsAvailable()) {
 			for (int i = 0; i < BAW_AIRPORT_COUNT; i++) {
-				if (GetAirport(i)->IsAvailable()) {
+				if (AirportSpec::Get(i)->IsAvailable()) {
 					this->SelectOtherAirport(i);
 					break;
 				}
 			}
 		}
 		for (int i = 0; i < BAW_AIRPORT_COUNT; i++) {
-			this->SetWidgetDisabledState(i + BAW_SMALL_AIRPORT, !GetAirport(i)->IsAvailable());
+			this->SetWidgetDisabledState(i + BAW_SMALL_AIRPORT, !AirportSpec::Get(i)->IsAvailable());
 		}
 	}
 
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -510,7 +510,7 @@
 
 					if (st == NULL || !CheckOwnership(st->owner) ||
 							!CanVehicleUseStation(v, st) ||
-							st->Airport()->nof_depots == 0) {
+							st->GetAirportSpec()->nof_depots == 0) {
 						return CMD_ERROR;
 					}
 				} else {
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -222,7 +222,7 @@
 		if (this->truck_stops        != NULL)         ret = max<uint>(ret, CA_TRUCK);
 		if (this->train_station.tile != INVALID_TILE) ret = max<uint>(ret, CA_TRAIN);
 		if (this->dock_tile          != INVALID_TILE) ret = max<uint>(ret, CA_DOCK);
-		if (this->airport_tile       != INVALID_TILE) ret = max<uint>(ret, this->Airport()->catchment);
+		if (this->airport_tile       != INVALID_TILE) ret = max<uint>(ret, this->GetAirportSpec()->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) {
 			ret = CA_UNMODIFIED;
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -66,6 +66,12 @@
 		return GetAirport(airport_type);
 	}
 
+	const AirportSpec *GetAirportSpec() const
+	{
+		if (airport_tile == INVALID_TILE) return &AirportSpec::dummy;
+		return AirportSpec::Get(this->airport_type);
+	}
+
 	RoadStop *bus_stops;    ///< All the road stops
 	TileArea bus_station;   ///< Tile area the bus 'station' part covers
 	RoadStop *truck_stops;  ///< All the truck stops
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -62,10 +62,10 @@
 	if (!IsAirport(t)) return false;
 
 	const Station *st = Station::GetByTile(t);
-	const AirportFTAClass *apc = st->Airport();
-
-	for (uint i = 0; i < apc->nof_depots; i++) {
-		if (st->airport_tile + ToTileIndexDiff(apc->airport_depots[i]) == t) return true;
+	const AirportSpec *as = st->GetAirportSpec();
+
+	for (uint i = 0; i < as->nof_depots; i++) {
+		if (st->airport_tile + ToTileIndexDiff(as->depot_table[i]) == t) return true;
 	}
 
 	return false;
@@ -380,8 +380,8 @@
 
 		case STATION_AIRPORT:
 			ta->tile = this->airport_tile;
-			ta->w    = this->Airport()->size_x;
-			ta->h    = this->Airport()->size_y;
+			ta->w    = this->GetAirportSpec()->size_x;
+			ta->h    = this->GetAirportSpec()->size_y;
 			return;
 
 		case STATION_TRUCK:
@@ -1795,12 +1795,12 @@
 
 /**
  * Computes the minimal distance from town's xy to any airport's tile.
- * @param afc airport's description
+ * @param as airport's description
  * @param town_tile town's tile (t->xy)
  * @param airport_tile st->airport_tile
  * @return minimal manhattan distance from town_tile to any airport's tile
  */
-static uint GetMinimalAirportDistanceToTile(const AirportFTAClass *afc, TileIndex town_tile, TileIndex airport_tile)
+static uint GetMinimalAirportDistanceToTile(const AirportSpec *as, TileIndex town_tile, TileIndex airport_tile)
 {
 	uint ttx = TileX(town_tile); // X, Y of town
 	uint tty = TileY(town_tile);
@@ -1808,8 +1808,8 @@
 	uint atx = TileX(airport_tile); // X, Y of northern airport corner
 	uint aty = TileY(airport_tile);
 
-	uint btx = TileX(airport_tile) + afc->size_x - 1; // X, Y of southern corner
-	uint bty = TileY(airport_tile) + afc->size_y - 1;
+	uint btx = TileX(airport_tile) + as->size_x - 1; // X, Y of southern corner
+	uint bty = TileY(airport_tile) + as->size_y - 1;
 
 	/* if ttx < atx, dx = atx - ttx
 	 * if atx <= ttx <= btx, dx = 0
@@ -1823,18 +1823,18 @@
 /** Get a possible noise reduction factor based on distance from town center.
  * The further you get, the less noise you generate.
  * So all those folks at city council can now happily slee...  work in their offices
- * @param afc AirportFTAClass pointer of the class being proposed
+ * @param as airport information
  * @param town_tile TileIndex of town's center, the one who will receive the airport's candidature
  * @param tile TileIndex of northern tile of an airport (present or to-be-built), NOT the station tile
  * @return the noise that will be generated, according to distance
  */
-uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile)
+uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, TileIndex town_tile, TileIndex tile)
 {
 	/* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
 	 * So no need to go any further*/
-	if (afc->noise_level < 2) return afc->noise_level;
-
-	uint distance = GetMinimalAirportDistanceToTile(afc, town_tile, tile);
+	if (as->noise_level < 2) return as->noise_level;
+
+	uint distance = GetMinimalAirportDistanceToTile(as, town_tile, tile);
 
 	/* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
 	 * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
@@ -1848,24 +1848,24 @@
 
 	/* If the noise reduction equals the airport noise itself, don't give it for free.
 	 * Otherwise, simply reduce the airport's level. */
-	return noise_reduction >= afc->noise_level ? 1 : afc->noise_level - noise_reduction;
+	return noise_reduction >= as->noise_level ? 1 : as->noise_level - noise_reduction;
 }
 
 /**
  * Finds the town nearest to given airport. Based on minimal manhattan distance to any airport's tile.
  * If two towns have the same distance, town with lower index is returned.
- * @param afc airport's description
+ * @param as airport's description
  * @param airport_tile st->airport_tile
  * @return nearest town to airport
  */
-Town *AirportGetNearestTown(const AirportFTAClass *afc, TileIndex airport_tile)
+Town *AirportGetNearestTown(const AirportSpec *as, TileIndex airport_tile)
 {
 	Town *t, *nearest = NULL;
-	uint add = afc->size_x + afc->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
+	uint add = as->size_x + as->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
 	uint mindist = UINT_MAX - add; // prevent overflow
 	FOR_ALL_TOWNS(t) {
 		if (DistanceManhattan(t->xy, airport_tile) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
-			uint dist = GetMinimalAirportDistanceToTile(afc, t->xy, airport_tile);
+			uint dist = GetMinimalAirportDistanceToTile(as, t->xy, airport_tile);
 			if (dist < mindist) {
 				nearest = t;
 				mindist = dist;
@@ -1887,9 +1887,9 @@
 
 	FOR_ALL_STATIONS(st) {
 		if (st->airport_tile != INVALID_TILE) {
-			const AirportFTAClass *afc = GetAirport(st->airport_type);
-			Town *nearest = AirportGetNearestTown(afc, st->airport_tile);
-			nearest->noise_reached += GetAirportNoiseLevelForTown(afc, nearest->xy, st->airport_tile);
+			const AirportSpec *as = st->GetAirportSpec();
+			Town *nearest = AirportGetNearestTown(as, st->airport_tile);
+			nearest->noise_reached += GetAirportNoiseLevelForTown(as, nearest->xy, st->airport_tile);
 		}
 	}
 }
@@ -1921,12 +1921,12 @@
 	}
 
 	/* Check if a valid, buildable airport was chosen for construction */
-	const AirportFTAClass *afc = GetAirport(p1);
-	if (!afc->IsAvailable()) return CMD_ERROR;
+	const AirportSpec *as = AirportSpec::Get(p1);
+	if (!as->IsAvailable()) return CMD_ERROR;
 
 	Town *t = ClosestTownFromTile(tile, UINT_MAX);
-	int w = afc->size_x;
-	int h = afc->size_y;
+	int w = as->size_x;
+	int h = as->size_y;
 
 	if (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread) {
 		_error_message = STR_ERROR_STATION_TOO_SPREAD_OUT;
@@ -1937,8 +1937,8 @@
 	if (CmdFailed(cost)) return cost;
 
 	/* Go get the final noise level, that is base noise minus factor from distance to town center */
-	Town *nearest = AirportGetNearestTown(afc, tile);
-	uint newnoise_level = GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
+	Town *nearest = AirportGetNearestTown(as, tile);
+	uint newnoise_level = GetAirportNoiseLevelForTown(as, nearest->xy, tile);
 
 	/* Check if local auth would allow a new airport */
 	StringID authority_refuse_message = STR_NULL;
@@ -1994,7 +1994,7 @@
 			st = new Station(tile);
 
 			st->town = t;
-			st->string_id = GenerateStationName(st, tile, !(afc->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT);
+			st->string_id = GenerateStationName(st, tile, !(GetAirport(p1)->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT);
 
 			if (Company::IsValidID(_current_company)) {
 				SetBit(st->town->have_ratings, _current_company);
@@ -2024,14 +2024,11 @@
 		 */
 		if (airport_upgrade) UpdateAirplanesOnNewStation(st);
 
-		{
-			const byte *b = _airport_sections[p1];
-
-			TILE_LOOP(tile_cur, w, h, tile) {
-				MakeAirport(tile_cur, st->owner, st->index, *b);
-				b++;
-			}
-		}
+		const AirportTileTable *it = as->table[0];
+		do {
+			TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
+			MakeAirport(cur_tile, st->owner, st->index, it->gfx);
+		} while ((++it)->ti.x != -0x80);
 
 		st->UpdateVirtCoord();
 		UpdateStationAcceptance(st, false);
@@ -2064,9 +2061,9 @@
 
 	tile = st->airport_tile;
 
-	const AirportFTAClass *afc = st->Airport();
-	int w = afc->size_x;
-	int h = afc->size_y;
+	const AirportSpec *as = st->GetAirportSpec();
+	int w = as->size_x;
+	int h = as->size_y;
 
 	CommandCost cost(EXPENSES_CONSTRUCTION, w * h * _price[PR_CLEAR_STATION_AIRPORT]);
 
@@ -2086,17 +2083,17 @@
 	}
 
 	if (flags & DC_EXEC) {
-		for (uint i = 0; i < afc->nof_depots; ++i) {
+		for (uint i = 0; i < as->nof_depots; ++i) {
 			DeleteWindowById(
-				WC_VEHICLE_DEPOT, tile + ToTileIndexDiff(afc->airport_depots[i])
+				WC_VEHICLE_DEPOT, tile + ToTileIndexDiff(as->depot_table[i])
 			);
 		}
 
 		/* Go get the final noise level, that is base noise minus factor from distance to town center.
 		 * And as for construction, always remove it, even if the setting is not set, in order to avoid the
 		 * need of recalculation */
-		Town *nearest = AirportGetNearestTown(afc, tile);
-		nearest->noise_reached -= GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
+		Town *nearest = AirportGetNearestTown(as, tile);
+		nearest->noise_reached -= GetAirportNoiseLevelForTown(as, nearest->xy, tile);
 
 		st->rect.AfterRemoveRect(st, tile, w, h);
 
new file mode 100644
--- /dev/null
+++ b/src/table/airport_defaults.h
@@ -0,0 +1,400 @@
+/* $Id$ */
+
+/** @file airport_defaults.h Tables with default values for airports and airport tiles. */
+
+#ifndef AIRPORT_DEFAULTS_H
+#define AIRPORT_DEFAULTS_H
+
+/**
+ * Definition of an airport tiles layout.
+ * @param x offset x of this tile
+ * @param y offset y of this tile
+ * @param m AirportGfx of the tile
+ * @see _airport_specs
+ * @see AirportTileTable
+ */
+#define MK(x, y, m) {{x, y}, m}
+
+/**
+ * Terminator of airport tiles layout definition
+ */
+#define MKEND {{-0x80, 0}, 0}
+
+/** Tiles for Country Airfield (small) */
+static AirportTileTable _tile_table_country_0[] = {
+	MK(0, 0, APT_SMALL_BUILDING_1),
+	MK(1, 0, APT_SMALL_BUILDING_2),
+	MK(2, 0, APT_SMALL_BUILDING_3),
+	MK(3, 0, APT_SMALL_DEPOT_SE),
+	MK(0, 1, APT_GRASS_FENCE_NE_FLAG),
+	MK(1, 1, APT_GRASS_1),
+	MK(2, 1, APT_GRASS_2),
+	MK(3, 1, APT_GRASS_FENCE_SW),
+	MK(0, 2, APT_RUNWAY_SMALL_FAR_END),
+	MK(1, 2, APT_RUNWAY_SMALL_MIDDLE),
+	MK(2, 2, APT_RUNWAY_SMALL_MIDDLE),
+	MK(3, 2, APT_RUNWAY_SMALL_NEAR_END),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_country[] = {
+	_tile_table_country_0,
+};
+
+/** Tiles for Commuter Airfield (small) */
+static AirportTileTable _tile_table_commuter_0[] = {
+	MK(0, 0, APT_TOWER),
+	MK(1, 0, APT_BUILDING_3),
+	MK(2, 0, APT_HELIPAD_2_FENCE_NW),
+	MK(3, 0, APT_HELIPAD_2_FENCE_NW),
+	MK(4, 0, APT_DEPOT_SE),
+	MK(0, 1, APT_APRON_FENCE_NE),
+	MK(1, 1, APT_APRON),
+	MK(2, 1, APT_APRON),
+	MK(3, 1, APT_APRON),
+	MK(4, 1, APT_APRON_FENCE_SW),
+	MK(0, 2, APT_APRON_FENCE_NE),
+	MK(1, 2, APT_STAND),
+	MK(2, 2, APT_STAND),
+	MK(3, 2, APT_STAND),
+	MK(4, 2, APT_APRON_FENCE_SW),
+	MK(0, 3, APT_RUNWAY_END_FENCE_SE),
+	MK(1, 3, APT_RUNWAY_2),
+	MK(2, 3, APT_RUNWAY_2),
+	MK(3, 3, APT_RUNWAY_2),
+	MK(4, 3, APT_RUNWAY_END_FENCE_SE),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_commuter[] = {
+	_tile_table_commuter_0,
+};
+
+/** Tiles for City Airport (large) */
+static AirportTileTable _tile_table_city_0[] = {
+	MK(0, 0, APT_BUILDING_1),
+	MK(1, 0, APT_APRON_FENCE_NW),
+	MK(2, 0, APT_STAND_1),
+	MK(3, 0, APT_APRON_FENCE_NW),
+	MK(4, 0, APT_APRON_FENCE_NW),
+	MK(5, 0, APT_DEPOT_SE),
+	MK(0, 1, APT_BUILDING_2),
+	MK(1, 1, APT_PIER),
+	MK(2, 1, APT_ROUND_TERMINAL),
+	MK(3, 1, APT_STAND_PIER_NE),
+	MK(4, 1, APT_APRON),
+	MK(5, 1, APT_APRON_FENCE_SW),
+	MK(0, 2, APT_BUILDING_3),
+	MK(1, 2, APT_STAND),
+	MK(2, 2, APT_PIER_NW_NE),
+	MK(3, 2, APT_APRON_S),
+	MK(4, 2, APT_APRON_HOR),
+	MK(5, 2, APT_APRON_N_FENCE_SW),
+	MK(0, 3, APT_RADIO_TOWER_FENCE_NE),
+	MK(1, 3, APT_APRON_W),
+	MK(2, 3, APT_APRON_VER_CROSSING_S),
+	MK(3, 3, APT_APRON_HOR_CROSSING_E),
+	MK(4, 3, APT_ARPON_N),
+	MK(5, 3, APT_TOWER_FENCE_SW),
+	MK(0, 4, APT_EMPTY_FENCE_NE),
+	MK(1, 4, APT_APRON_S),
+	MK(2, 4, APT_APRON_HOR_CROSSING_W),
+	MK(3, 4, APT_APRON_VER_CROSSING_N),
+	MK(4, 4, APT_APRON_E),
+	MK(5, 4, APT_RADAR_GRASS_FENCE_SW),
+	MK(0, 5, APT_RUNWAY_END_FENCE_SE),
+	MK(1, 5, APT_RUNWAY_1),
+	MK(2, 5, APT_RUNWAY_2),
+	MK(3, 5, APT_RUNWAY_3),
+	MK(4, 5, APT_RUNWAY_4),
+	MK(5, 5, APT_RUNWAY_END_FENCE_SE),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_city[] = {
+	_tile_table_city_0,
+};
+
+/** Tiles for Metropolitain Airport (large) - 2 runways */
+static AirportTileTable _tile_table_metropolitan_0[] = {
+	MK(0, 0, APT_BUILDING_1),
+	MK(1, 0, APT_APRON_FENCE_NW),
+	MK(2, 0, APT_STAND_1),
+	MK(3, 0, APT_APRON_FENCE_NW),
+	MK(4, 0, APT_APRON_FENCE_NW),
+	MK(5, 0, APT_DEPOT_SE),
+	MK(0, 1, APT_BUILDING_2),
+	MK(1, 1, APT_PIER),
+	MK(2, 1, APT_ROUND_TERMINAL),
+	MK(3, 1, APT_STAND_PIER_NE),
+	MK(4, 1, APT_APRON),
+	MK(5, 1, APT_APRON_FENCE_SW),
+	MK(0, 2, APT_BUILDING_3),
+	MK(1, 2, APT_STAND),
+	MK(2, 2, APT_PIER_NW_NE),
+	MK(3, 2, APT_APRON_S),
+	MK(4, 2, APT_APRON_HOR),
+	MK(5, 2, APT_APRON_N_FENCE_SW),
+	MK(0, 3, APT_RADAR_FENCE_NE),
+	MK(1, 3, APT_APRON),
+	MK(2, 3, APT_APRON),
+	MK(3, 3, APT_APRON),
+	MK(4, 3, APT_APRON),
+	MK(5, 3, APT_TOWER_FENCE_SW),
+	MK(0, 4, APT_RUNWAY_END),
+	MK(1, 4, APT_RUNWAY_5),
+	MK(2, 4, APT_RUNWAY_5),
+	MK(3, 4, APT_RUNWAY_5),
+	MK(4, 4, APT_RUNWAY_5),
+	MK(5, 4, APT_RUNWAY_END),
+	MK(0, 5, APT_RUNWAY_END_FENCE_SE),
+	MK(1, 5, APT_RUNWAY_2),
+	MK(2, 5, APT_RUNWAY_2),
+	MK(3, 5, APT_RUNWAY_2),
+	MK(4, 5, APT_RUNWAY_2),
+	MK(5, 5, APT_RUNWAY_END_FENCE_SE),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_metropolitan[] = {
+	_tile_table_metropolitan_0,
+};
+
+/** Tiles for International Airport (large) - 2 runways */
+static AirportTileTable _tile_table_international_0[] = {
+	MK(0, 0, APT_RUNWAY_END_FENCE_NW),
+	MK(1, 0, APT_RUNWAY_FENCE_NW),
+	MK(2, 0, APT_RUNWAY_FENCE_NW),
+	MK(3, 0, APT_RUNWAY_FENCE_NW),
+	MK(4, 0, APT_RUNWAY_FENCE_NW),
+	MK(5, 0, APT_RUNWAY_FENCE_NW),
+	MK(6, 0, APT_RUNWAY_END_FENCE_NW),
+	MK(0, 1, APT_RADIO_TOWER_FENCE_NE),
+	MK(1, 1, APT_APRON),
+	MK(2, 1, APT_APRON),
+	MK(3, 1, APT_APRON),
+	MK(4, 1, APT_APRON),
+	MK(5, 1, APT_APRON),
+	MK(6, 1, APT_DEPOT_SE),
+	MK(0, 2, APT_BUILDING_3),
+	MK(1, 2, APT_APRON),
+	MK(2, 2, APT_STAND),
+	MK(3, 2, APT_BUILDING_2),
+	MK(4, 2, APT_STAND),
+	MK(5, 2, APT_APRON),
+	MK(6, 2, APT_APRON_FENCE_SW),
+	MK(0, 3, APT_DEPOT_SE),
+	MK(1, 3, APT_APRON),
+	MK(2, 3, APT_STAND),
+	MK(3, 3, APT_BUILDING_2),
+	MK(4, 3, APT_STAND),
+	MK(5, 3, APT_APRON),
+	MK(6, 3, APT_HELIPAD_1),
+	MK(0, 4, APT_APRON_FENCE_NE),
+	MK(1, 4, APT_APRON),
+	MK(2, 4, APT_STAND),
+	MK(3, 4, APT_TOWER),
+	MK(4, 4, APT_STAND),
+	MK(5, 4, APT_APRON),
+	MK(6, 4, APT_HELIPAD_1),
+	MK(0, 5, APT_APRON_FENCE_NE),
+	MK(1, 5, APT_APRON),
+	MK(2, 5, APT_APRON),
+	MK(3, 5, APT_APRON),
+	MK(4, 5, APT_APRON),
+	MK(5, 5, APT_APRON),
+	MK(6, 5, APT_RADAR_FENCE_SW),
+	MK(0, 6, APT_RUNWAY_END_FENCE_SE),
+	MK(1, 6, APT_RUNWAY_2),
+	MK(2, 6, APT_RUNWAY_2),
+	MK(3, 6, APT_RUNWAY_2),
+	MK(4, 6, APT_RUNWAY_2),
+	MK(5, 6, APT_RUNWAY_2),
+	MK(6, 6, APT_RUNWAY_END_FENCE_SE),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_international[] = {
+	_tile_table_international_0,
+};
+
+/** Tiles for International Airport (large) - 2 runways */
+static AirportTileTable _tile_table_intercontinental_0[] = {
+	MK(0, 0, APT_RADAR_FENCE_NE),
+	MK(1, 0, APT_RUNWAY_END_FENCE_NE_NW),
+	MK(2, 0, APT_RUNWAY_FENCE_NW),
+	MK(3, 0, APT_RUNWAY_FENCE_NW),
+	MK(4, 0, APT_RUNWAY_FENCE_NW),
+	MK(5, 0, APT_RUNWAY_FENCE_NW),
+	MK(6, 0, APT_RUNWAY_FENCE_NW),
+	MK(7, 0, APT_RUNWAY_FENCE_NW),
+	MK(8, 0, APT_RUNWAY_END_FENCE_NW_SW),
+	MK(0, 1, APT_RUNWAY_END_FENCE_NE_NW),
+	MK(1, 1, APT_RUNWAY_2),
+	MK(2, 1, APT_RUNWAY_2),
+	MK(3, 1, APT_RUNWAY_2),
+	MK(4, 1, APT_RUNWAY_2),
+	MK(5, 1, APT_RUNWAY_2),
+	MK(6, 1, APT_RUNWAY_2),
+	MK(7, 1, APT_RUNWAY_END_FENCE_SE_SW),
+	MK(8, 1, APT_APRON_FENCE_NE_SW),
+	MK(0, 2, APT_APRON_FENCE_NE),
+	MK(1, 2, APT_SMALL_BUILDING_1),
+	MK(2, 2, APT_APRON_FENCE_NE),
+	MK(3, 2, APT_APRON),
+	MK(4, 2, APT_APRON),
+	MK(5, 2, APT_APRON),
+	MK(6, 2, APT_APRON),
+	MK(7, 2, APT_RADIO_TOWER_FENCE_NE),
+	MK(8, 2, APT_APRON_FENCE_NE_SW),
+	MK(0, 3, APT_APRON_FENCE_NE),
+	MK(1, 3, APT_APRON_HALF_EAST),
+	MK(2, 3, APT_APRON_FENCE_NE),
+	MK(3, 3, APT_TOWER),
+	MK(4, 3, APT_HELIPAD_2),
+	MK(5, 3, APT_HELIPAD_2),
+	MK(6, 3, APT_APRON),
+	MK(7, 3, APT_APRON_FENCE_NW),
+	MK(8, 3, APT_APRON_FENCE_SW),
+	MK(0, 4, APT_APRON_FENCE_NE),
+	MK(1, 4, APT_APRON),
+	MK(2, 4, APT_APRON),
+	MK(3, 4, APT_STAND),
+	MK(4, 4, APT_BUILDING_1),
+	MK(5, 4, APT_STAND),
+	MK(6, 4, APT_APRON),
+	MK(7, 4, APT_LOW_BUILDING),
+	MK(8, 4, APT_DEPOT_SE),
+	MK(0, 5, APT_DEPOT_SE),
+	MK(1, 5, APT_LOW_BUILDING),
+	MK(2, 5, APT_APRON),
+	MK(3, 5, APT_STAND),
+	MK(4, 5, APT_BUILDING_2),
+	MK(5, 5, APT_STAND),
+	MK(6, 5, APT_APRON),
+	MK(7, 5, APT_APRON),
+	MK(8, 5, APT_APRON_FENCE_SW),
+	MK(0, 6, APT_APRON_FENCE_NE),
+	MK(1, 6, APT_APRON),
+	MK(2, 6, APT_APRON),
+	MK(3, 6, APT_STAND),
+	MK(4, 6, APT_BUILDING_3),
+	MK(5, 6, APT_STAND),
+	MK(6, 6, APT_APRON),
+	MK(7, 6, APT_APRON),
+	MK(8, 6, APT_APRON_FENCE_SW),
+	MK(0, 7, APT_APRON_FENCE_NE),
+	MK(1, 7, APT_APRON_FENCE_SE),
+	MK(2, 7, APT_APRON),
+	MK(3, 7, APT_STAND),
+	MK(4, 7, APT_ROUND_TERMINAL),
+	MK(5, 7, APT_STAND),
+	MK(6, 7, APT_APRON_FENCE_SW),
+	MK(7, 7, APT_APRON_HALF_WEST),
+	MK(8, 7, APT_APRON_FENCE_SW),
+	MK(0, 8, APT_APRON_FENCE_NE),
+	MK(1, 8, APT_GRASS_FENCE_NE_FLAG_2),
+	MK(2, 8, APT_APRON_FENCE_NE),
+	MK(3, 8, APT_APRON),
+	MK(4, 8, APT_APRON),
+	MK(5, 8, APT_APRON),
+	MK(6, 8, APT_APRON_FENCE_SW),
+	MK(7, 8, APT_EMPTY),
+	MK(8, 8, APT_APRON_FENCE_NE_SW),
+	MK(0, 9, APT_APRON_FENCE_NE),
+	MK(1, 9, APT_RUNWAY_END_FENCE_NE_NW),
+	MK(2, 9, APT_RUNWAY_FENCE_NW),
+	MK(3, 9, APT_RUNWAY_FENCE_NW),
+	MK(4, 9, APT_RUNWAY_FENCE_NW),
+	MK(5, 9, APT_RUNWAY_FENCE_NW),
+	MK(6, 9, APT_RUNWAY_FENCE_NW),
+	MK(7, 9, APT_RUNWAY_FENCE_NW),
+	MK(8, 9, APT_RUNWAY_END_FENCE_SE_SW),
+	MK(0, 10, APT_RUNWAY_END_FENCE_NE_SE),
+	MK(1, 10, APT_RUNWAY_2),
+	MK(2, 10, APT_RUNWAY_2),
+	MK(3, 10, APT_RUNWAY_2),
+	MK(4, 10, APT_RUNWAY_2),
+	MK(5, 10, APT_RUNWAY_2),
+	MK(6, 10, APT_RUNWAY_2),
+	MK(7, 10, APT_RUNWAY_END_FENCE_SE_SW),
+	MK(8, 10, APT_EMPTY),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_intercontinental[] = {
+	_tile_table_intercontinental_0,
+};
+
+/** Tiles for Heliport */
+static AirportTileTable _tile_table_heliport_0[] = {
+	MK(0, 0, APT_HELIPORT),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_heliport[] = {
+	_tile_table_heliport_0,
+};
+
+/** Tiles for Helidepot */
+static AirportTileTable _tile_table_helidepot_0[] = {
+	MK(0, 0, APT_LOW_BUILDING_FENCE_N),
+	MK(1, 0, APT_DEPOT_SE),
+	MK(0, 1, APT_HELIPAD_2_FENCE_NE_SE),
+	MK(1, 1, APT_APRON_FENCE_SE_SW),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_helidepot[] = {
+	_tile_table_helidepot_0,
+};
+
+/** Tiles for Helistation */
+static AirportTileTable _tile_table_helistation_0[] = {
+	MK(0, 0, APT_DEPOT_SE),
+	MK(1, 0, APT_LOW_BUILDING_FENCE_NW),
+	MK(2, 0, APT_HELIPAD_3_FENCE_NW),
+	MK(3, 0, APT_HELIPAD_3_FENCE_NW_SW),
+	MK(0, 1, APT_APRON_FENCE_NE_SE),
+	MK(1, 1, APT_APRON_FENCE_SE),
+	MK(2, 1, APT_APRON_FENCE_SE),
+	MK(3, 1, APT_HELIPAD_3_FENCE_SE_SW),
+	MKEND
+};
+
+static AirportTileTable *_tile_table_helistation[] = {
+	_tile_table_helistation_0,
+};
+
+#undef MK
+#undef MKEND
+
+/** General AirportSpec definition. */
+#define AS_GENERIC(att, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year) \
+	{att, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year}
+
+/** AirportSpec definition for airports without any depot. */
+#define AS_ND(ap_name, size_x, size_y, min_year, max_year, catchment, noise) \
+	AS_GENERIC(_tile_table_##ap_name, NULL, 0, size_x, size_y, noise, catchment, min_year, max_year)
+
+/** AirportSpec definition for airports with at least one depot. */
+#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise) \
+	AS_GENERIC(_tile_table_##ap_name, _airport_depots_##ap_name, lengthof(_airport_depots_##ap_name), size_x, size_y, noise, catchment, min_year, max_year)
+
+AirportSpec _origin_airport_specs[NUM_AIRPORTS] = {
+	AS(country, 4, 3, 0, 1959, 4, 3),
+	AS(city, 6, 6, 1960, MAX_YEAR, 5, 5),
+	AS_ND(heliport, 1, 1, 1963, MAX_YEAR, 4, 1),
+	AS(metropolitan, 6, 6, 1980, MAX_YEAR, 6, 8),
+	AS(international, 7, 7, 1990, MAX_YEAR, 8, 17),
+	AS(commuter, 5, 4, 1983, MAX_YEAR, 4, 4),
+	AS(helidepot, 2, 2, 1976, MAX_YEAR, 4, 2),
+	AS(intercontinental, 9, 11, 2002, MAX_YEAR, 10, 25),
+	AS(helistation, 4, 2, 1980, MAX_YEAR, 4, 3),
+};
+
+#undef AS
+#undef AS_ND
+#undef AS_GENERIC
+
+#endif /* AIRPORT_DEFAULTS_H */
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -732,10 +732,10 @@
 
 	if (IsTileType(tile, MP_STATION) && IsAirport(tile)) {
 		const Station *st = Station::GetByTile(tile);
-		const AirportFTAClass *airport = st->Airport();
-		z = 1 + airport->delta_z;
-		for (uint x = 0; x < airport->size_x; x++) {
-			for (uint y = 0; y < airport->size_y; y++) {
+		const AirportSpec *as = st->GetAirportSpec();
+		z = 1 + st->Airport()->delta_z;
+		for (uint x = 0; x < as->size_x; x++) {
+			for (uint y = 0; y < as->size_y; y++) {
 				tile = TILE_ADDXY(st->airport_tile, x, y);
 				FindVehicleOnPos(tile, &z, &FloodVehicleProc);
 			}