Fix 03cc0d6: Mark level crossings dirty when removing road from them, not from bridge...
[openttd-github.git] / src / airport.cpp
blob808d14d6ba25a08a8e9a769d4d0b7e35c9cfa1e9
1 /*
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/>.
6 */
8 /** @file airport.cpp Functions related to airports. */
10 #include "stdafx.h"
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"
19 /**
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);
31 /**
32 * Define an airport.
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)
40 /**
41 * Define a heliport.
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)
61 #undef HELIPORT
62 #undef AIRPORT
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);
72 /**
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);
85 switch (rotation) {
86 case DIR_N:
87 amd.x = orig->x;
88 amd.y = orig->y;
89 break;
91 case DIR_E:
92 amd.x = orig->y;
93 amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
94 break;
96 case DIR_S:
97 amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
98 amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
99 break;
101 case DIR_W:
102 amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
103 amd.y = orig->x;
104 break;
106 default: NOT_REACHED();
108 return amd;
111 AirportFTAClass::AirportFTAClass(
112 const AirportMovingData *moving_data_,
113 const byte *terminals_,
114 const byte num_helipads_,
115 const byte *entry_points_,
116 Flags flags_,
117 const AirportFTAbuildup *apFA,
118 byte delta_z_
120 moving_data(moving_data_),
121 terminals(terminals_),
122 num_helipads(num_helipads_),
123 flags(flags_),
124 nofelements(AirportGetNofElements(apFA)),
125 entry_points(entry_points_),
126 delta_z(delta_z_)
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;
138 free(current);
139 current = next;
142 free(layout);
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) {
157 nofelements++;
158 temp = apFA[i].position;
160 if (apFA[i].position == MAX_ELEMENTS) break;
162 return nofelements;
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;
191 /* create link */
192 current->next = newNode;
193 current = current->next;
194 internalcounter++;
196 current->next = nullptr;
197 internalcounter++;
199 return FAutomata;
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;
232 NOT_REACHED();