236 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* $Id$ */
 | |
| 
 | |
| /*
 | |
|  * This file is part of OpenTTD.
 | |
|  * 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.
 | |
|  * 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.
 | |
|  * 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/>.
 | |
|  */
 | |
| 
 | |
| /** @file airport.cpp Functions related to airports. */
 | |
| 
 | |
| #include "stdafx.h"
 | |
| #include "station_base.h"
 | |
| #include "table/strings.h"
 | |
| #include "table/airport_movement.h"
 | |
| #include "table/airporttile_ids.h"
 | |
| 
 | |
| #include "safeguards.h"
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Define a generic airport.
 | |
|  * @param name Suffix of the names of the airport data.
 | |
|  * @param terminals The terminals.
 | |
|  * @param num_helipads Number of heli pads.
 | |
|  * @param flags Information about the class of FTA.
 | |
|  * @param delta_z Height of the airport above the land.
 | |
|  */
 | |
| #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
 | |
| 	static const AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
 | |
| 			num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
 | |
| 
 | |
| /**
 | |
|  * Define an airport.
 | |
|  * @param name Suffix of the names of the airport data.
 | |
|  * @param num_helipads Number of heli pads.
 | |
|  * @param short_strip Airport has a short land/take-off strip.
 | |
|  */
 | |
| #define AIRPORT(name, num_helipads, short_strip) \
 | |
| 	AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
 | |
| 
 | |
| /**
 | |
|  * Define a heliport.
 | |
|  * @param name Suffix of the names of the helipad data.
 | |
|  * @param num_helipads Number of heli pads.
 | |
|  * @param delta_z Height of the airport above the land.
 | |
|  */
 | |
| #define HELIPORT(name, num_helipads, delta_z) \
 | |
| 	AIRPORT_GENERIC(name, NULL, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
 | |
| 
 | |
| AIRPORT(country, 0, true)
 | |
| AIRPORT(city, 0, false)
 | |
| HELIPORT(heliport, 1, 60)
 | |
| AIRPORT(metropolitan, 0, false)
 | |
| AIRPORT(international, 2, false)
 | |
| AIRPORT(commuter, 2, true)
 | |
| HELIPORT(helidepot, 1, 0)
 | |
| AIRPORT(intercontinental, 2, false)
 | |
| HELIPORT(helistation, 3, 0)
 | |
| HELIPORT(oilrig, 1, 54)
 | |
| AIRPORT_GENERIC(dummy, NULL, 0, AirportFTAClass::ALL, 0)
 | |
| 
 | |
| #undef HELIPORT
 | |
| #undef AIRPORT
 | |
| #undef AIRPORT_GENERIC
 | |
| 
 | |
| #include "table/airport_defaults.h"
 | |
| 
 | |
| 
 | |
| static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
 | |
| static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Rotate the airport moving data to another rotation.
 | |
|  * @param orig Pointer to the moving data to rotate.
 | |
|  * @param rotation How to rotate the moving data.
 | |
|  * @param num_tiles_x Number of tiles in x direction.
 | |
|  * @param num_tiles_y Number of tiles in y direction.
 | |
|  * @return The rotated moving data.
 | |
|  */
 | |
| AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
 | |
| {
 | |
| 	AirportMovingData amd;
 | |
| 	amd.flag = orig->flag;
 | |
| 	amd.direction = ChangeDir(orig->direction, (DirDiff)rotation);
 | |
| 	switch (rotation) {
 | |
| 		case DIR_N:
 | |
| 			amd.x = orig->x;
 | |
| 			amd.y = orig->y;
 | |
| 			break;
 | |
| 
 | |
| 		case DIR_E:
 | |
| 			amd.x = orig->y;
 | |
| 			amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
 | |
| 			break;
 | |
| 
 | |
| 		case DIR_S:
 | |
| 			amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
 | |
| 			amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
 | |
| 			break;
 | |
| 
 | |
| 		case DIR_W:
 | |
| 			amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
 | |
| 			amd.y = orig->x;
 | |
| 			break;
 | |
| 
 | |
| 		default: NOT_REACHED();
 | |
| 	}
 | |
| 	return amd;
 | |
| }
 | |
| 
 | |
| AirportFTAClass::AirportFTAClass(
 | |
| 	const AirportMovingData *moving_data_,
 | |
| 	const byte *terminals_,
 | |
| 	const byte num_helipads_,
 | |
| 	const byte *entry_points_,
 | |
| 	Flags flags_,
 | |
| 	const AirportFTAbuildup *apFA,
 | |
| 	byte delta_z_
 | |
| ) :
 | |
| 	moving_data(moving_data_),
 | |
| 	terminals(terminals_),
 | |
| 	num_helipads(num_helipads_),
 | |
| 	flags(flags_),
 | |
| 	nofelements(AirportGetNofElements(apFA)),
 | |
| 	entry_points(entry_points_),
 | |
| 	delta_z(delta_z_)
 | |
| {
 | |
| 	/* Build the state machine itself */
 | |
| 	this->layout = AirportBuildAutomata(this->nofelements, apFA);
 | |
| }
 | |
| 
 | |
| AirportFTAClass::~AirportFTAClass()
 | |
| {
 | |
| 	for (uint i = 0; i < nofelements; i++) {
 | |
| 		AirportFTA *current = layout[i].next;
 | |
| 		while (current != NULL) {
 | |
| 			AirportFTA *next = current->next;
 | |
| 			free(current);
 | |
| 			current = next;
 | |
| 		}
 | |
| 	}
 | |
| 	free(layout);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get the number of elements of a source Airport state automata
 | |
|  * Since it is actually just a big array of AirportFTA types, we only
 | |
|  * know one element from the other by differing 'position' identifiers
 | |
|  */
 | |
| static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
 | |
| {
 | |
| 	uint16 nofelements = 0;
 | |
| 	int temp = apFA[0].position;
 | |
| 
 | |
| 	for (uint i = 0; i < MAX_ELEMENTS; i++) {
 | |
| 		if (temp != apFA[i].position) {
 | |
| 			nofelements++;
 | |
| 			temp = apFA[i].position;
 | |
| 		}
 | |
| 		if (apFA[i].position == MAX_ELEMENTS) break;
 | |
| 	}
 | |
| 	return nofelements;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Construct the FTA given a description.
 | |
|  * @param nofelements The number of elements in the FTA.
 | |
|  * @param apFA The description of the FTA.
 | |
|  * @return The FTA describing the airport.
 | |
|  */
 | |
| static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
 | |
| {
 | |
| 	AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
 | |
| 	uint16 internalcounter = 0;
 | |
| 
 | |
| 	for (uint i = 0; i < nofelements; i++) {
 | |
| 		AirportFTA *current = &FAutomata[i];
 | |
| 		current->position      = apFA[internalcounter].position;
 | |
| 		current->heading       = apFA[internalcounter].heading;
 | |
| 		current->block         = apFA[internalcounter].block;
 | |
| 		current->next_position = apFA[internalcounter].next;
 | |
| 
 | |
| 		/* outgoing nodes from the same position, create linked list */
 | |
| 		while (current->position == apFA[internalcounter + 1].position) {
 | |
| 			AirportFTA *newNode = MallocT<AirportFTA>(1);
 | |
| 
 | |
| 			newNode->position      = apFA[internalcounter + 1].position;
 | |
| 			newNode->heading       = apFA[internalcounter + 1].heading;
 | |
| 			newNode->block         = apFA[internalcounter + 1].block;
 | |
| 			newNode->next_position = apFA[internalcounter + 1].next;
 | |
| 			/* create link */
 | |
| 			current->next = newNode;
 | |
| 			current = current->next;
 | |
| 			internalcounter++;
 | |
| 		}
 | |
| 		current->next = NULL;
 | |
| 		internalcounter++;
 | |
| 	}
 | |
| 	return FAutomata;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get the finite state machine of an airport type.
 | |
|  * @param airport_type %Airport type to query FTA from. @see AirportTypes
 | |
|  * @return Finite state machine of the airport.
 | |
|  */
 | |
| const AirportFTAClass *GetAirport(const byte airport_type)
 | |
| {
 | |
| 	if (airport_type == AT_DUMMY) return &_airportfta_dummy;
 | |
| 	return AirportSpec::Get(airport_type)->fsm;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get the vehicle position when an aircraft is build at the given tile
 | |
|  * @param hangar_tile The tile on which the vehicle is build
 | |
|  * @return The position (index in airport node array) where the aircraft ends up
 | |
|  */
 | |
| byte GetVehiclePosOnBuild(TileIndex hangar_tile)
 | |
| {
 | |
| 	const Station *st = Station::GetByTile(hangar_tile);
 | |
| 	const AirportFTAClass *apc = st->airport.GetFTA();
 | |
| 	/* When we click on hangar we know the tile it is on. By that we know
 | |
| 	 * its position in the array of depots the airport has.....we can search
 | |
| 	 * layout for #th position of depot. Since layout must start with a listing
 | |
| 	 * of all depots, it is simple */
 | |
| 	for (uint i = 0;; i++) {
 | |
| 		if (st->airport.GetHangarTile(i) == hangar_tile) {
 | |
| 			assert(apc->layout[i].heading == HANGAR);
 | |
| 			return apc->layout[i].position;
 | |
| 		}
 | |
| 	}
 | |
| 	NOT_REACHED();
 | |
| }
 | 
