Fix crash when setting separation mode for vehicles with no orders list.
[openttd-joker.git] / src / airport.cpp
blob15e18035f092819673dd380834c7f025440c561d
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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 */
10 /** @file airport.cpp Functions related to airports. */
12 #include "stdafx.h"
13 #include "station_base.h"
14 #include "table/strings.h"
15 #include "table/airport_movement.h"
16 #include "table/airporttile_ids.h"
18 #include "safeguards.h"
21 /**
22 * Define a generic airport.
23 * @param name Suffix of the names of the airport data.
24 * @param terminals The terminals.
25 * @param num_helipads Number of heli pads.
26 * @param flags Information about the class of FTA.
27 * @param delta_z Height of the airport above the land.
29 #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
30 static const AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
31 num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
33 /**
34 * Define an airport.
35 * @param name Suffix of the names of the airport data.
36 * @param num_helipads Number of heli pads.
37 * @param short_strip Airport has a short land/take-off strip.
39 #define AIRPORT(name, num_helipads, short_strip) \
40 AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
42 /**
43 * Define a heliport.
44 * @param name Suffix of the names of the helipad data.
45 * @param num_helipads Number of heli pads.
46 * @param delta_z Height of the airport above the land.
48 #define HELIPORT(name, num_helipads, delta_z) \
49 AIRPORT_GENERIC(name, nullptr, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
51 AIRPORT(country, 0, true)
52 AIRPORT(city, 0, false)
53 HELIPORT(heliport, 1, 60)
54 AIRPORT(metropolitan, 0, false)
55 AIRPORT(international, 2, false)
56 AIRPORT(commuter, 2, true)
57 HELIPORT(helidepot, 1, 0)
58 AIRPORT(intercontinental, 2, false)
59 HELIPORT(helistation, 3, 0)
60 HELIPORT(oilrig, 1, 54)
61 AIRPORT_GENERIC(dummy, nullptr, 0, AirportFTAClass::ALL, 0)
63 #undef HELIPORT
64 #undef AIRPORT
65 #undef AIRPORT_GENERIC
67 #include "table/airport_defaults.h"
70 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
71 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
74 /**
75 * Rotate the airport moving data to another rotation.
76 * @param orig Pointer to the moving data to rotate.
77 * @param rotation How to rotate the moving data.
78 * @param num_tiles_x Number of tiles in x direction.
79 * @param num_tiles_y Number of tiles in y direction.
80 * @return The rotated moving data.
82 AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
84 AirportMovingData amd;
85 amd.flag = orig->flag;
86 amd.direction = ChangeDir(orig->direction, (DirDiff)rotation);
87 switch (rotation) {
88 case DIR_N:
89 amd.x = orig->x;
90 amd.y = orig->y;
91 break;
93 case DIR_E:
94 amd.x = orig->y;
95 amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
96 break;
98 case DIR_S:
99 amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
100 amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
101 break;
103 case DIR_W:
104 amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
105 amd.y = orig->x;
106 break;
108 default: NOT_REACHED();
110 return amd;
113 AirportFTAClass::AirportFTAClass(
114 const AirportMovingData *moving_data_,
115 const byte *terminals_,
116 const byte num_helipads_,
117 const byte *entry_points_,
118 Flags flags_,
119 const AirportFTAbuildup *apFA,
120 byte delta_z_
122 moving_data(moving_data_),
123 terminals(terminals_),
124 num_helipads(num_helipads_),
125 flags(flags_),
126 nofelements(AirportGetNofElements(apFA)),
127 entry_points(entry_points_),
128 delta_z(delta_z_)
130 /* Build the state machine itself */
131 this->layout = AirportBuildAutomata(this->nofelements, apFA);
134 AirportFTAClass::~AirportFTAClass()
136 for (uint i = 0; i < nofelements; i++) {
137 AirportFTA *current = layout[i].next;
138 while (current != nullptr) {
139 AirportFTA *next = current->next;
140 free(current);
141 current = next;
144 free(layout);
148 * Get the number of elements of a source Airport state automata
149 * Since it is actually just a big array of AirportFTA types, we only
150 * know one element from the other by differing 'position' identifiers
152 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
154 uint16 nofelements = 0;
155 int temp = apFA[0].position;
157 for (uint i = 0; i < MAX_ELEMENTS; i++) {
158 if (temp != apFA[i].position) {
159 nofelements++;
160 temp = apFA[i].position;
162 if (apFA[i].position == MAX_ELEMENTS) break;
164 return nofelements;
168 * Construct the FTA given a description.
169 * @param nofelements The number of elements in the FTA.
170 * @param apFA The description of the FTA.
171 * @return The FTA describing the airport.
173 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
175 AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
176 uint16 internalcounter = 0;
178 for (uint i = 0; i < nofelements; i++) {
179 AirportFTA *current = &FAutomata[i];
180 current->position = apFA[internalcounter].position;
181 current->heading = apFA[internalcounter].heading;
182 current->block = apFA[internalcounter].block;
183 current->next_position = apFA[internalcounter].next;
185 /* outgoing nodes from the same position, create linked list */
186 while (current->position == apFA[internalcounter + 1].position) {
187 AirportFTA *newNode = MallocT<AirportFTA>(1);
189 newNode->position = apFA[internalcounter + 1].position;
190 newNode->heading = apFA[internalcounter + 1].heading;
191 newNode->block = apFA[internalcounter + 1].block;
192 newNode->next_position = apFA[internalcounter + 1].next;
193 /* create link */
194 current->next = newNode;
195 current = current->next;
196 internalcounter++;
198 current->next = nullptr;
199 internalcounter++;
201 return FAutomata;
205 * Get the finite state machine of an airport type.
206 * @param airport_type %Airport type to query FTA from. @see AirportTypes
207 * @return Finite state machine of the airport.
209 const AirportFTAClass *GetAirport(const byte airport_type)
211 if (airport_type == AT_DUMMY) return &_airportfta_dummy;
212 return AirportSpec::Get(airport_type)->fsm;
216 * Get the vehicle position when an aircraft is build at the given tile
217 * @param hangar_tile The tile on which the vehicle is build
218 * @return The position (index in airport node array) where the aircraft ends up
220 byte GetVehiclePosOnBuild(TileIndex hangar_tile)
222 const Station *st = Station::GetByTile(hangar_tile);
223 const AirportFTAClass *apc = st->airport.GetFTA();
224 /* When we click on hangar we know the tile it is on. By that we know
225 * its position in the array of depots the airport has.....we can search
226 * layout for #th position of depot. Since layout must start with a listing
227 * of all depots, it is simple */
228 for (uint i = 0;; i++) {
229 if (st->airport.GetHangarTile(i) == hangar_tile) {
230 assert(apc->layout[i].heading == HANGAR);
231 return apc->layout[i].position;
234 NOT_REACHED();