# 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
    00019 #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
    00020   static AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
    00021       num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
    00022
    00029 #define AIRPORT(name, num_helipads, short_strip) \
    00030   AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
    00031
    00038 #define HELIPORT(name, num_helipads, delta_z) \
    00039   AIRPORT_GENERIC(name, NULL, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
    00040
    00041 AIRPORT(country, 0, true)
    00042 AIRPORT(city, 0, false)
    00043 HELIPORT(heliport, 1, 60)
    00044 AIRPORT(metropolitan, 0, false)
    00045 AIRPORT(international, 2, false)
    00046 AIRPORT(commuter, 2, true)
    00047 HELIPORT(helidepot, 1, 0)
    00048 AIRPORT(intercontinental, 2, false)
    00049 HELIPORT(helistation, 3, 0)
    00050 HELIPORT(oilrig, 1, 54)
    00051 AIRPORT_GENERIC(dummy, NULL, 0, AirportFTAClass::ALL, 0)
    00052
    00053 #undef HELIPORT
    00054 #undef AIRPORT
    00055 #undef AIRPORT_GENERIC
    00056
    00057 #include "table/airport_defaults.h"
    00058
    00059
    00060 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
    00061 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
    00062
    00063
    00072 AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
    00073 {
    00074   AirportMovingData amd;
    00075   amd.flag = orig->flag;
    00076   amd.direction = ChangeDir(orig->direction, (DirDiff)rotation);
    00077   switch (rotation) {
    00078     case DIR_N:
    00079       amd.x = orig->x;
    00080       amd.y = orig->y;
    00081       break;
    00082
    00083     case DIR_E:
    00084       amd.x = orig->y;
    00085       amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
    00086       break;
    00087
    00088     case DIR_S:
    00089       amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
    00090       amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
    00091       break;
    00092
    00093     case DIR_W:
    00094       amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
    00095       amd.y = orig->x;
    00096       break;
    00097
    00098     default: NOT_REACHED();
    00099   }
    00100   return amd;
    00101 }
    00102
    00103 AirportFTAClass::AirportFTAClass(
    00104   const AirportMovingData *moving_data_,
    00105   const byte *terminals_,
    00106   const byte num_helipads_,
    00107   const byte *entry_points_,
    00108   Flags flags_,
    00109   const AirportFTAbuildup *apFA,
    00110   byte delta_z_
    00111 ) :
    00112   moving_data(moving_data_),
    00113   terminals(terminals_),
    00114   num_helipads(num_helipads_),
    00115   flags(flags_),
    00116   nofelements(AirportGetNofElements(apFA)),
    00117   entry_points(entry_points_),
    00118   delta_z(delta_z_)
    00119 {
    00120   /* Build the state machine itself */
    00121   this->layout = AirportBuildAutomata(this->nofelements, apFA);
    00122 }
    00123
    00124 AirportFTAClass::~AirportFTAClass()
    00125 {
    00126   for (uint i = 0; i < nofelements; i++) {
    00127     AirportFTA *current = layout[i].next;
    00128     while (current != NULL) {
    00129       AirportFTA *next = current->next;
    00130       free(current);
    00131       current = next;
    00132     }
    00133   }
    00134   free(layout);
    00135 }
    00136
    00142 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
    00143 {
    00144   uint16 nofelements = 0;
    00145   int temp = apFA[0].position;
    00146
    00147   for (uint i = 0; i < MAX_ELEMENTS; i++) {
    00148     if (temp != apFA[i].position) {
    00149       nofelements++;
    00150       temp = apFA[i].position;
    00151     }
    00152     if (apFA[i].position == MAX_ELEMENTS) break;
    00153   }
    00154   return nofelements;
    00155 }
    00156
    00157
    00158 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
    00159 {
    00160   AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
    00161   uint16 internalcounter = 0;
    00162
    00163   for (uint i = 0; i < nofelements; i++) {
    00164     AirportFTA *current = &FAutomata[i];
    00165     current->position      = apFA[internalcounter].position;
    00166     current->heading       = apFA[internalcounter].heading;
    00167     current->block         = apFA[internalcounter].block;
    00168     current->next_position = apFA[internalcounter].next;
    00169
    00170     /* outgoing nodes from the same position, create linked list */
    00171     while (current->position == apFA[internalcounter + 1].position) {
    00172       AirportFTA *newNode = MallocT<AirportFTA>(1);
    00173
    00174       newNode->position      = apFA[internalcounter + 1].position;
    00175       newNode->heading       = apFA[internalcounter + 1].heading;
    00176       newNode->block         = apFA[internalcounter + 1].block;
    00177       newNode->next_position = apFA[internalcounter + 1].next;
    00178       /* create link */
    00179       current->next = newNode;
    00180       current = current->next;
    00181       internalcounter++;
    00182     }
    00183     current->next = NULL;
    00184     internalcounter++;
    00185   }
    00186   return FAutomata;
    00187 }
    00188
    00194 const AirportFTAClass *GetAirport(const byte airport_type)
    00195 {
    00196   if (airport_type == AT_DUMMY) return &_airportfta_dummy;
    00197   return AirportSpec::Get(airport_type)->fsm;
    00198 }
    00199
    00205 byte GetVehiclePosOnBuild(TileIndex hangar_tile)
    00206 {
    00207   const Station *st = Station::GetByTile(hangar_tile);
    00208   const AirportFTAClass *apc = st->airport.GetFTA();
    00209   /* When we click on hangar we know the tile it is on. By that we know
    00210    * its position in the array of depots the airport has.....we can search
    00211    * layout for #th position of depot. Since layout must start with a listing
    00212    * of all depots, it is simple */
    00213   for (uint i = 0;; i++) {
    00214     if (st->airport.GetHangarTile(i) == hangar_tile) {
    00215       assert(apc->layout[i].heading == HANGAR);
    00216       return apc->layout[i].position;
    00217     }
    00218   }
    00219   NOT_REACHED();
    00220 }