# airport.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "station_base.h"
    00014 #include "table/strings.h"
    00015 #include "table/airport_movement.h"
    00016 #include "table/airporttile_ids.h"
    00017
    00018
    00027 #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
    00028   static AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
    00029       num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
    00030
    00037 #define AIRPORT(name, num_helipads, short_strip) \
    00038   AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
    00039
    00046 #define HELIPORT(name, num_helipads, delta_z) \
    00047   AIRPORT_GENERIC(name, NULL, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
    00048
    00049 AIRPORT(country, 0, true)
    00050 AIRPORT(city, 0, false)
    00051 HELIPORT(heliport, 1, 60)
    00052 AIRPORT(metropolitan, 0, false)
    00053 AIRPORT(international, 2, false)
    00054 AIRPORT(commuter, 2, true)
    00055 HELIPORT(helidepot, 1, 0)
    00056 AIRPORT(intercontinental, 2, false)
    00057 HELIPORT(helistation, 3, 0)
    00058 HELIPORT(oilrig, 1, 54)
    00059 AIRPORT_GENERIC(dummy, NULL, 0, AirportFTAClass::ALL, 0)
    00060
    00061 #undef HELIPORT
    00062 #undef AIRPORT
    00063 #undef AIRPORT_GENERIC
    00064
    00065 #include "table/airport_defaults.h"
    00066
    00067
    00068 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
    00069 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
    00070
    00071
    00080 AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
    00081 {
    00082   AirportMovingData amd;
    00083   amd.flag = orig->flag;
    00084   amd.direction = ChangeDir(orig->direction, (DirDiff)rotation);
    00085   switch (rotation) {
    00086     case DIR_N:
    00087       amd.x = orig->x;
    00088       amd.y = orig->y;
    00089       break;
    00090
    00091     case DIR_E:
    00092       amd.x = orig->y;
    00093       amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
    00094       break;
    00095
    00096     case DIR_S:
    00097       amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
    00098       amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
    00099       break;
    00100
    00101     case DIR_W:
    00102       amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
    00103       amd.y = orig->x;
    00104       break;
    00105
    00106     default: NOT_REACHED();
    00107   }
    00108   return amd;
    00109 }
    00110
    00111 AirportFTAClass::AirportFTAClass(
    00112   const AirportMovingData *moving_data_,
    00113   const byte *terminals_,
    00114   const byte num_helipads_,
    00115   const byte *entry_points_,
    00116   Flags flags_,
    00117   const AirportFTAbuildup *apFA,
    00118   byte delta_z_
    00119 ) :
    00120   moving_data(moving_data_),
    00121   terminals(terminals_),
    00122   num_helipads(num_helipads_),
    00123   flags(flags_),
    00124   nofelements(AirportGetNofElements(apFA)),
    00125   entry_points(entry_points_),
    00126   delta_z(delta_z_)
    00127 {
    00128   /* Build the state machine itself */
    00129   this->layout = AirportBuildAutomata(this->nofelements, apFA);
    00130 }
    00131
    00132 AirportFTAClass::~AirportFTAClass()
    00133 {
    00134   for (uint i = 0; i < nofelements; i++) {
    00135     AirportFTA *current = layout[i].next;
    00136     while (current != NULL) {
    00137       AirportFTA *next = current->next;
    00138       free(current);
    00139       current = next;
    00140     }
    00141   }
    00142   free(layout);
    00143 }
    00144
    00150 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
    00151 {
    00152   uint16 nofelements = 0;
    00153   int temp = apFA[0].position;
    00154
    00155   for (uint i = 0; i < MAX_ELEMENTS; i++) {
    00156     if (temp != apFA[i].position) {
    00157       nofelements++;
    00158       temp = apFA[i].position;
    00159     }
    00160     if (apFA[i].position == MAX_ELEMENTS) break;
    00161   }
    00162   return nofelements;
    00163 }
    00164
    00171 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
    00172 {
    00173   AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
    00174   uint16 internalcounter = 0;
    00175
    00176   for (uint i = 0; i < nofelements; i++) {
    00177     AirportFTA *current = &FAutomata[i];
    00178     current->position      = apFA[internalcounter].position;
    00179     current->heading       = apFA[internalcounter].heading;
    00180     current->block         = apFA[internalcounter].block;
    00181     current->next_position = apFA[internalcounter].next;
    00182
    00183     /* outgoing nodes from the same position, create linked list */
    00184     while (current->position == apFA[internalcounter + 1].position) {
    00185       AirportFTA *newNode = MallocT<AirportFTA>(1);
    00186
    00187       newNode->position      = apFA[internalcounter + 1].position;
    00188       newNode->heading       = apFA[internalcounter + 1].heading;
    00189       newNode->block         = apFA[internalcounter + 1].block;
    00190       newNode->next_position = apFA[internalcounter + 1].next;
    00191       /* create link */
    00192       current->next = newNode;
    00193       current = current->next;
    00194       internalcounter++;
    00195     }
    00196     current->next = NULL;
    00197     internalcounter++;
    00198   }
    00199   return FAutomata;
    00200 }
    00201
    00207 const AirportFTAClass *GetAirport(const byte airport_type)
    00208 {
    00209   if (airport_type == AT_DUMMY) return &_airportfta_dummy;
    00210   return AirportSpec::Get(airport_type)->fsm;
    00211 }
    00212
    00218 byte GetVehiclePosOnBuild(TileIndex hangar_tile)
    00219 {
    00220   const Station *st = Station::GetByTile(hangar_tile);
    00221   const AirportFTAClass *apc = st->airport.GetFTA();
    00222   /* When we click on hangar we know the tile it is on. By that we know
    00223    * its position in the array of depots the airport has.....we can search
    00224    * layout for #th position of depot. Since layout must start with a listing
    00225    * of all depots, it is simple */
    00226   for (uint i = 0;; i++) {
    00227     if (st->airport.GetHangarTile(i) == hangar_tile) {
    00228       assert(apc->layout[i].heading == HANGAR);
    00229       return apc->layout[i].position;
    00230     }
    00231   }
    00232   NOT_REACHED();
    00233 }