2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file airport.cpp Functions related to airports. */
11 #include "station_base.h"
12 #include "table/strings.h"
13 #include "table/airport_movement.h"
14 #include "table/airporttile_ids.h"
16 #include "safeguards.h"
20 * Define a generic airport.
21 * @param name Suffix of the names of the airport data.
22 * @param terminals The terminals.
23 * @param num_helipads Number of heli pads.
24 * @param flags Information about the class of FTA.
25 * @param delta_z Height of the airport above the land.
27 #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
28 static const AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
29 num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
33 * @param name Suffix of the names of the airport data.
34 * @param num_helipads Number of heli pads.
35 * @param short_strip Airport has a short land/take-off strip.
37 #define AIRPORT(name, num_helipads, short_strip) \
38 AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
42 * @param name Suffix of the names of the helipad data.
43 * @param num_helipads Number of heli pads.
44 * @param delta_z Height of the airport above the land.
46 #define HELIPORT(name, num_helipads, delta_z) \
47 AIRPORT_GENERIC(name, nullptr, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
49 AIRPORT(country
, 0, true)
50 AIRPORT(city
, 0, false)
51 HELIPORT(heliport
, 1, 60)
52 AIRPORT(metropolitan
, 0, false)
53 AIRPORT(international
, 2, false)
54 AIRPORT(commuter
, 2, true)
55 HELIPORT(helidepot
, 1, 0)
56 AIRPORT(intercontinental
, 2, false)
57 HELIPORT(helistation
, 3, 0)
58 HELIPORT(oilrig
, 1, 54)
59 AIRPORT_GENERIC(dummy
, nullptr, 0, AirportFTAClass::ALL
, 0)
63 #undef AIRPORT_GENERIC
65 #include "table/airport_defaults.h"
68 static uint16
AirportGetNofElements(const AirportFTAbuildup
*apFA
);
69 static AirportFTA
*AirportBuildAutomata(uint nofelements
, const AirportFTAbuildup
*apFA
);
73 * Rotate the airport moving data to another rotation.
74 * @param orig Pointer to the moving data to rotate.
75 * @param rotation How to rotate the moving data.
76 * @param num_tiles_x Number of tiles in x direction.
77 * @param num_tiles_y Number of tiles in y direction.
78 * @return The rotated moving data.
80 AirportMovingData
RotateAirportMovingData(const AirportMovingData
*orig
, Direction rotation
, uint num_tiles_x
, uint num_tiles_y
)
82 AirportMovingData amd
;
83 amd
.flag
= orig
->flag
;
84 amd
.direction
= ChangeDir(orig
->direction
, (DirDiff
)rotation
);
93 amd
.y
= num_tiles_y
* TILE_SIZE
- orig
->x
- 1;
97 amd
.x
= num_tiles_x
* TILE_SIZE
- orig
->x
- 1;
98 amd
.y
= num_tiles_y
* TILE_SIZE
- orig
->y
- 1;
102 amd
.x
= num_tiles_x
* TILE_SIZE
- orig
->y
- 1;
106 default: NOT_REACHED();
111 AirportFTAClass::AirportFTAClass(
112 const AirportMovingData
*moving_data_
,
113 const byte
*terminals_
,
114 const byte num_helipads_
,
115 const byte
*entry_points_
,
117 const AirportFTAbuildup
*apFA
,
120 moving_data(moving_data_
),
121 terminals(terminals_
),
122 num_helipads(num_helipads_
),
124 nofelements(AirportGetNofElements(apFA
)),
125 entry_points(entry_points_
),
128 /* Build the state machine itself */
129 this->layout
= AirportBuildAutomata(this->nofelements
, apFA
);
132 AirportFTAClass::~AirportFTAClass()
134 for (uint i
= 0; i
< nofelements
; i
++) {
135 AirportFTA
*current
= layout
[i
].next
;
136 while (current
!= nullptr) {
137 AirportFTA
*next
= current
->next
;
146 * Get the number of elements of a source Airport state automata
147 * Since it is actually just a big array of AirportFTA types, we only
148 * know one element from the other by differing 'position' identifiers
150 static uint16
AirportGetNofElements(const AirportFTAbuildup
*apFA
)
152 uint16 nofelements
= 0;
153 int temp
= apFA
[0].position
;
155 for (uint i
= 0; i
< MAX_ELEMENTS
; i
++) {
156 if (temp
!= apFA
[i
].position
) {
158 temp
= apFA
[i
].position
;
160 if (apFA
[i
].position
== MAX_ELEMENTS
) break;
166 * Construct the FTA given a description.
167 * @param nofelements The number of elements in the FTA.
168 * @param apFA The description of the FTA.
169 * @return The FTA describing the airport.
171 static AirportFTA
*AirportBuildAutomata(uint nofelements
, const AirportFTAbuildup
*apFA
)
173 AirportFTA
*FAutomata
= MallocT
<AirportFTA
>(nofelements
);
174 uint16 internalcounter
= 0;
176 for (uint i
= 0; i
< nofelements
; i
++) {
177 AirportFTA
*current
= &FAutomata
[i
];
178 current
->position
= apFA
[internalcounter
].position
;
179 current
->heading
= apFA
[internalcounter
].heading
;
180 current
->block
= apFA
[internalcounter
].block
;
181 current
->next_position
= apFA
[internalcounter
].next
;
183 /* outgoing nodes from the same position, create linked list */
184 while (current
->position
== apFA
[internalcounter
+ 1].position
) {
185 AirportFTA
*newNode
= MallocT
<AirportFTA
>(1);
187 newNode
->position
= apFA
[internalcounter
+ 1].position
;
188 newNode
->heading
= apFA
[internalcounter
+ 1].heading
;
189 newNode
->block
= apFA
[internalcounter
+ 1].block
;
190 newNode
->next_position
= apFA
[internalcounter
+ 1].next
;
192 current
->next
= newNode
;
193 current
= current
->next
;
196 current
->next
= nullptr;
203 * Get the finite state machine of an airport type.
204 * @param airport_type %Airport type to query FTA from. @see AirportTypes
205 * @return Finite state machine of the airport.
207 const AirportFTAClass
*GetAirport(const byte airport_type
)
209 if (airport_type
== AT_DUMMY
) return &_airportfta_dummy
;
210 return AirportSpec::Get(airport_type
)->fsm
;
214 * Get the vehicle position when an aircraft is build at the given tile
215 * @param hangar_tile The tile on which the vehicle is build
216 * @return The position (index in airport node array) where the aircraft ends up
218 byte
GetVehiclePosOnBuild(TileIndex hangar_tile
)
220 const Station
*st
= Station::GetByTile(hangar_tile
);
221 const AirportFTAClass
*apc
= st
->airport
.GetFTA();
222 /* When we click on hangar we know the tile it is on. By that we know
223 * its position in the array of depots the airport has.....we can search
224 * layout for #th position of depot. Since layout must start with a listing
225 * of all depots, it is simple */
226 for (uint i
= 0;; i
++) {
227 if (st
->airport
.GetHangarTile(i
) == hangar_tile
) {
228 assert(apc
->layout
[i
].heading
== HANGAR
);
229 return apc
->layout
[i
].position
;