src/aircraft_cmd.cpp
changeset 6123 04eb770ec17e
parent 6117 6507b2a7e71d
child 6153 eb35b73b300a
equal deleted inserted replaced
6122:3359af5a1f54 6123:04eb770ec17e
    29 #include "newgrf_text.h"
    29 #include "newgrf_text.h"
    30 #include "newgrf_sound.h"
    30 #include "newgrf_sound.h"
    31 #include "date.h"
    31 #include "date.h"
    32 #include "spritecache.h"
    32 #include "spritecache.h"
    33 
    33 
    34 // this maps the terminal to its corresponding state and block flag
    34 /** this maps the terminal to its corresponding state and block flag
    35 // currently set for 10 terms, 4 helipads
    35  *  currently set for 10 terms, 4 helipads */
    36 static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
    36 static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
    37 static const byte _airport_terminal_flag[] =  {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25};
    37 static const byte _airport_terminal_flag[] =  {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25};
    38 
    38 
    39 static bool AirportMove(Vehicle *v, const AirportFTAClass *apc);
    39 static bool AirportMove(Vehicle *v, const AirportFTAClass *apc);
    40 static bool AirportSetBlocks(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
    40 static bool AirportSetBlocks(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
    54 	0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
    54 	0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
    55 	0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
    55 	0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
    56 	0x0EBD, 0x0EC5
    56 	0x0EBD, 0x0EC5
    57 };
    57 };
    58 
    58 
    59 /* Helicopter rotor animation states */
    59 /** Helicopter rotor animation states */
    60 enum HelicopterRotorStates {
    60 enum HelicopterRotorStates {
    61 	HRS_ROTOR_STOPPED,
    61 	HRS_ROTOR_STOPPED,
    62 	HRS_ROTOR_MOVING_1,
    62 	HRS_ROTOR_MOVING_1,
    63 	HRS_ROTOR_MOVING_2,
    63 	HRS_ROTOR_MOVING_2,
    64 	HRS_ROTOR_MOVING_3,
    64 	HRS_ROTOR_MOVING_3,
    65 };
    65 };
    66 
    66 
    67 /* Find the nearest hangar to v
    67 /** Find the nearest hangar to v
    68  * INVALID_STATION is returned, if the player does not have any suitable
    68  * INVALID_STATION is returned, if the player does not have any suitable
    69  * airports (like helipads only)
    69  * airports (like helipads only)
       
    70  * @param v vehicle looking for a hangar
       
    71  * @return the StationID if one is found, otherwise, INVALID_STATION
    70  */
    72  */
    71 static StationID FindNearestHangar(const Vehicle *v)
    73 static StationID FindNearestHangar(const Vehicle *v)
    72 {
    74 {
    73 	const Station *st;
    75 	const Station *st;
    74 	uint best = 0;
    76 	uint best = 0;
    86 					!_cheats.no_jetcrash.value
    88 					!_cheats.no_jetcrash.value
    87 				)) {
    89 				)) {
    88 			continue;
    90 			continue;
    89 		}
    91 		}
    90 
    92 
    91 		// v->tile can't be used here, when aircraft is flying v->tile is set to 0
    93 		/* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */
    92 		uint distance = DistanceSquare(vtile, st->airport_tile);
    94 		uint distance = DistanceSquare(vtile, st->airport_tile);
    93 		if (distance < best || index == INVALID_STATION) {
    95 		if (distance < best || index == INVALID_STATION) {
    94 			best = distance;
    96 			best = distance;
    95 			index = st->index;
    97 			index = st->index;
    96 		}
    98 		}
    97 	}
    99 	}
    98 	return index;
   100 	return index;
    99 }
   101 }
   100 
   102 
   101 #if 0
   103 #if 0
   102 // returns true if vehicle v have an airport in the schedule, that has a hangar
   104 /** Check if given vehicle has a goto hangar in his orders
       
   105  * @param v vehicle to inquiry
       
   106  * @return true if vehicle v has an airport in the schedule, that has a hangar */
   103 static bool HaveHangarInOrderList(Vehicle *v)
   107 static bool HaveHangarInOrderList(Vehicle *v)
   104 {
   108 {
   105 	const Order *order;
   109 	const Order *order;
   106 
   110 
   107 	FOR_VEHICLE_ORDERS(v, order) {
   111 	FOR_VEHICLE_ORDERS(v, order) {
   108 		const Station *st = GetStation(order->station);
   112 		const Station *st = GetStation(order->station);
   109 		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
   113 		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
   110 			// If an airport doesn't have a hangar, skip it
   114 			/* If an airport doesn't have a hangar, skip it */
   111 			if (st->Airport()->nof_depots != 0)
   115 			if (st->Airport()->nof_depots != 0)
   112 				return true;
   116 				return true;
   113 		}
   117 		}
   114 	}
   118 	}
   115 
   119 
   224 }
   228 }
   225 
   229 
   226 
   230 
   227 /** Build an aircraft.
   231 /** Build an aircraft.
   228  * @param tile tile of depot where aircraft is built
   232  * @param tile tile of depot where aircraft is built
       
   233  * @param flags for command
   229  * @param p1 aircraft type being built (engine)
   234  * @param p1 aircraft type being built (engine)
   230  * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number
   235  * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number
       
   236  * return result of operation.  Could be cost, error
   231  */
   237  */
   232 int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   238 int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   233 {
   239 {
   234 	if (!IsEngineBuildable(p1, VEH_Aircraft, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   240 	if (!IsEngineBuildable(p1, VEH_Aircraft, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   235 
   241 
   236 	const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
   242 	const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
   237 	int32 value = EstimateAircraftCost(avi);
   243 	int32 value = EstimateAircraftCost(avi);
   238 
   244 
   239 	// to just query the cost, it is not neccessary to have a valid tile (automation/AI)
   245 	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
   240 	if (flags & DC_QUERY_COST) return value;
   246 	if (flags & DC_QUERY_COST) return value;
   241 
   247 
   242 	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
   248 	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
   243 
   249 
   244 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   250 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   245 
   251 
   246 	// Prevent building aircraft types at places which can't handle them
   252 	/* Prevent building aircraft types at places which can't handle them */
   247 	const Station* st = GetStationByTile(tile);
   253 	const Station* st = GetStationByTile(tile);
   248 	const AirportFTAClass* apc = st->Airport();
   254 	const AirportFTAClass* apc = st->Airport();
   249 	if (!(apc->flags & (avi->subtype & AIR_CTOL ? AirportFTAClass::AIRPLANES : AirportFTAClass::HELICOPTERS))) {
   255 	if (!(apc->flags & (avi->subtype & AIR_CTOL ? AirportFTAClass::AIRPLANES : AirportFTAClass::HELICOPTERS))) {
   250 		return CMD_ERROR;
   256 		return CMD_ERROR;
   251 	}
   257 	}
   385 		u->random_bits = VehicleRandomBits();
   391 		u->random_bits = VehicleRandomBits();
   386 
   392 
   387 		VehiclePositionChanged(v);
   393 		VehiclePositionChanged(v);
   388 		VehiclePositionChanged(u);
   394 		VehiclePositionChanged(u);
   389 
   395 
   390 		// Aircraft with 3 vehicles (chopper)?
   396 		/* Aircraft with 3 vehicles (chopper)? */
   391 		if (v->subtype == AIR_HELICOPTER) {
   397 		if (v->subtype == AIR_HELICOPTER) {
   392 			Vehicle *w = vl[2];
   398 			Vehicle *w = vl[2];
   393 
   399 
   394 			u->next = w;
   400 			u->next = w;
   395 
   401 
   435 	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   441 	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
   436 }
   442 }
   437 
   443 
   438 /** Sell an aircraft.
   444 /** Sell an aircraft.
   439  * @param tile unused
   445  * @param tile unused
       
   446  * @param flags for command type
   440  * @param p1 vehicle ID to be sold
   447  * @param p1 vehicle ID to be sold
   441  * @param p2 unused
   448  * @param p2 unused
       
   449  * @return result of operation.  Error or sold value
   442  */
   450  */
   443 int32 CmdSellAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   451 int32 CmdSellAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   444 {
   452 {
   445 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   453 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   446 
   454 
   460 	return -(int32)v->value;
   468 	return -(int32)v->value;
   461 }
   469 }
   462 
   470 
   463 /** Start/Stop an aircraft.
   471 /** Start/Stop an aircraft.
   464  * @param tile unused
   472  * @param tile unused
       
   473  * @param flags for command type
   465  * @param p1 aircraft ID to start/stop
   474  * @param p1 aircraft ID to start/stop
   466  * @param p2 unused
   475  * @param p2 unused
       
   476  * @return result of operation.  Nothing if everything went well
   467  */
   477  */
   468 int32 CmdStartStopAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   478 int32 CmdStartStopAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   469 {
   479 {
   470 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   480 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
   471 
   481 
   472 	Vehicle *v = GetVehicle(p1);
   482 	Vehicle *v = GetVehicle(p1);
   473 
   483 
   474 	if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
   484 	if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
   475 
   485 
   476 	// cannot stop airplane when in flight, or when taking off / landing
   486 	/* cannot stop airplane when in flight, or when taking off / landing */
   477 	if (v->u.air.state >= STARTTAKEOFF && v->u.air.state < TERM7)
   487 	if (v->u.air.state >= STARTTAKEOFF && v->u.air.state < TERM7)
   478 		return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
   488 		return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
   479 
   489 
   480 	/* Check if this aircraft can be started/stopped. The callback will fail or
   490 	/* Check if this aircraft can be started/stopped. The callback will fail or
   481 	 * return 0xFF if it can. */
   491 	 * return 0xFF if it can. */
   499 	return 0;
   509 	return 0;
   500 }
   510 }
   501 
   511 
   502 /** Send an aircraft to the hangar.
   512 /** Send an aircraft to the hangar.
   503  * @param tile unused
   513  * @param tile unused
       
   514  * @param flags for command type
   504  * @param p1 vehicle ID to send to the hangar
   515  * @param p1 vehicle ID to send to the hangar
   505  * @param p2 various bitmasked elements
   516  * @param p2 various bitmasked elements
   506  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
   517  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
   507  * - p2 bit 8-10 - VLW flag (for mass goto depot)
   518  * - p2 bit 8-10 - VLW flag (for mass goto depot)
       
   519  * @return o if everything went well
   508  */
   520  */
   509 int32 CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   521 int32 CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   510 {
   522 {
   511 	if (p2 & DEPOT_MASS_SEND) {
   523 	if (p2 & DEPOT_MASS_SEND) {
   512 		/* Mass goto depot requested */
   524 		/* Mass goto depot requested */
   543 		bool next_airport_has_hangar = true;
   555 		bool next_airport_has_hangar = true;
   544 		StationID next_airport_index = v->u.air.targetairport;
   556 		StationID next_airport_index = v->u.air.targetairport;
   545 		const Station *st = GetStation(next_airport_index);
   557 		const Station *st = GetStation(next_airport_index);
   546 		/* If the station is not a valid airport or if it has no hangars */
   558 		/* If the station is not a valid airport or if it has no hangars */
   547 		if (!st->IsValid() || st->airport_tile == 0 || st->Airport()->nof_depots == 0) {
   559 		if (!st->IsValid() || st->airport_tile == 0 || st->Airport()->nof_depots == 0) {
   548 			// the aircraft has to search for a hangar on its own
   560 			/* the aircraft has to search for a hangar on its own */
   549 			StationID station = FindNearestHangar(v);
   561 			StationID station = FindNearestHangar(v);
   550 
   562 
   551 			next_airport_has_hangar = false;
   563 			next_airport_has_hangar = false;
   552 			if (station == INVALID_STATION) return CMD_ERROR;
   564 			if (station == INVALID_STATION) return CMD_ERROR;
   553 			next_airport_index = station;
   565 			next_airport_index = station;
   571 }
   583 }
   572 
   584 
   573 
   585 
   574 /** Refits an aircraft to the specified cargo type.
   586 /** Refits an aircraft to the specified cargo type.
   575  * @param tile unused
   587  * @param tile unused
       
   588  * @param flags for command type
   576  * @param p1 vehicle ID of the aircraft to refit
   589  * @param p1 vehicle ID of the aircraft to refit
   577  * @param p2 various bitstuffed elements
   590  * @param p2 various bitstuffed elements
   578  * - p2 = (bit 0-7) - the new cargo type to refit to
   591  * - p2 = (bit 0-7) - the new cargo type to refit to
   579  * - p2 = (bit 8-15) - the new cargo subtype to refit to
   592  * - p2 = (bit 8-15) - the new cargo subtype to refit to
       
   593  * @return cost of refit or error
   580  */
   594  */
   581 int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   595 int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   582 {
   596 {
   583 	byte new_subtype = GB(p2, 8, 8);
   597 	byte new_subtype = GB(p2, 8, 8);
   584 
   598 
   668 		VehicleServiceInDepot(v);
   682 		VehicleServiceInDepot(v);
   669 		return;
   683 		return;
   670 	}
   684 	}
   671 
   685 
   672 	const Station *st = GetStation(v->current_order.dest);
   686 	const Station *st = GetStation(v->current_order.dest);
   673 	// only goto depot if the target airport has terminals (eg. it is airport)
   687 	/* only goto depot if the target airport has terminals (eg. it is airport) */
   674 	if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
   688 	if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
   675 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
   689 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
   676 //		v->u.air.targetairport = st->index;
   690 //		v->u.air.targetairport = st->index;
   677 		v->current_order.type = OT_GOTO_DEPOT;
   691 		v->current_order.type = OT_GOTO_DEPOT;
   678 		v->current_order.flags = OF_NON_STOP;
   692 		v->current_order.flags = OF_NON_STOP;
   736 {
   750 {
   737 	Vehicle *u = v->next->next;
   751 	Vehicle *u = v->next->next;
   738 
   752 
   739 	if (u->vehstatus & VS_HIDDEN) return;
   753 	if (u->vehstatus & VS_HIDDEN) return;
   740 
   754 
   741 	// if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
   755 	/* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
   742 	// loading/unloading at a terminal or stopped
   756 	 * loading/unloading at a terminal or stopped */
   743 	if (v->current_order.type == OT_LOADING || (v->vehstatus & VS_STOPPED)) {
   757 	if (v->current_order.type == OT_LOADING || (v->vehstatus & VS_STOPPED)) {
   744 		if (u->cur_speed != 0) {
   758 		if (u->cur_speed != 0) {
   745 			u->cur_speed++;
   759 			u->cur_speed++;
   746 			if (u->cur_speed >= 0x80 && u->u.air.state == HRS_ROTOR_MOVING_3) {
   760 			if (u->cur_speed >= 0x80 && u->u.air.state == HRS_ROTOR_MOVING_3) {
   747 				u->cur_speed = 0;
   761 				u->cur_speed = 0;
   860 
   874 
   861 	v->subspeed = (t=v->subspeed) + (byte)spd;
   875 	v->subspeed = (t=v->subspeed) + (byte)spd;
   862 	if (speed_limit == SPEED_LIMIT_NONE) speed_limit = v->max_speed;
   876 	if (speed_limit == SPEED_LIMIT_NONE) speed_limit = v->max_speed;
   863 	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
   877 	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
   864 
   878 
   865 	// adjust speed for broken vehicles
   879 	/* adjust speed for broken vehicles */
   866 	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
   880 	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
   867 
   881 
   868 	//updates statusbar only if speed have changed to save CPU time
   882 	/* updates statusbar only if speed have changed to save CPU time */
   869 	if (spd != v->cur_speed) {
   883 	if (spd != v->cur_speed) {
   870 		v->cur_speed = spd;
   884 		v->cur_speed = spd;
   871 		if (_patches.vehicle_speed)
   885 		if (_patches.vehicle_speed)
   872 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   886 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   873 	}
   887 	}
   919 
   933 
   920 static bool AircraftController(Vehicle *v)
   934 static bool AircraftController(Vehicle *v)
   921 {
   935 {
   922 	const Station *st = GetStation(v->u.air.targetairport);
   936 	const Station *st = GetStation(v->u.air.targetairport);
   923 
   937 
   924 	// prevent going to 0,0 if airport is deleted.
   938 	/* prevent going to 0,0 if airport is deleted. */
   925 	TileIndex tile = st->airport_tile;
   939 	TileIndex tile = st->airport_tile;
   926 	if (tile == 0) tile = st->xy;
   940 	if (tile == 0) tile = st->xy;
   927 	int x = TileX(tile) * TILE_SIZE;
   941 	int x = TileX(tile) * TILE_SIZE;
   928 	int y = TileY(tile) * TILE_SIZE;
   942 	int y = TileY(tile) * TILE_SIZE;
   929 
   943 
   930 	// get airport moving data
   944 	/*  get airport moving data */
   931 	const AirportFTAClass *afc = st->Airport();
   945 	const AirportFTAClass *afc = st->Airport();
   932 	const AirportMovingData *amd = afc->MovingData(v->u.air.pos);
   946 	const AirportMovingData *amd = afc->MovingData(v->u.air.pos);
   933 
   947 
   934 	// Helicopter raise
   948 	/* Helicopter raise */
   935 	if (amd->flag & AMED_HELI_RAISE) {
   949 	if (amd->flag & AMED_HELI_RAISE) {
   936 		Vehicle *u = v->next->next;
   950 		Vehicle *u = v->next->next;
   937 
   951 
   938 		// Make sure the rotors don't rotate too fast
   952 		/* Make sure the rotors don't rotate too fast */
   939 		if (u->cur_speed > 32) {
   953 		if (u->cur_speed > 32) {
   940 			v->cur_speed = 0;
   954 			v->cur_speed = 0;
   941 			if (--u->cur_speed == 32) SndPlayVehicleFx(SND_18_HELICOPTER, v);
   955 			if (--u->cur_speed == 32) SndPlayVehicleFx(SND_18_HELICOPTER, v);
   942 		} else {
   956 		} else {
   943 			u->cur_speed = 32;
   957 			u->cur_speed = 32;
   944 			if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) {
   958 			if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) {
   945 				v->tile = 0;
   959 				v->tile = 0;
   946 
   960 
   947 				// Reached altitude?
   961 				/* Reached altitude? */
   948 				if (v->z_pos >= 184) {
   962 				if (v->z_pos >= 184) {
   949 					v->cur_speed = 0;
   963 					v->cur_speed = 0;
   950 					return true;
   964 					return true;
   951 				}
   965 				}
   952 				SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1);
   966 				SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos+1);
   953 			}
   967 			}
   954 		}
   968 		}
   955 		return false;
   969 		return false;
   956 	}
   970 	}
   957 
   971 
   958 	// Helicopter landing.
   972 	/* Helicopter landing. */
   959 	if (amd->flag & AMED_HELI_LOWER) {
   973 	if (amd->flag & AMED_HELI_LOWER) {
   960 		if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) {
   974 		if (UpdateAircraftSpeed(v, SPEED_LIMIT_NONE)) {
   961 			if (st->airport_tile == 0) {
   975 			if (st->airport_tile == 0) {
   962 				// FIXME - AircraftController -> if station no longer exists, do not land
   976 				/* FIXME - AircraftController -> if station no longer exists, do not land
   963 				// helicopter will circle until sign disappears, then go to next order
   977 				 * helicopter will circle until sign disappears, then go to next order
   964 				// * what to do when it is the only order left, right now it just stays in 1 place
   978 				 * what to do when it is the only order left, right now it just stays in 1 place */
   965 				v->u.air.state = FLYING;
   979 				v->u.air.state = FLYING;
   966 				AircraftNextAirportPos_and_Order(v);
   980 				AircraftNextAirportPos_and_Order(v);
   967 				return false;
   981 				return false;
   968 			}
   982 			}
   969 
   983 
   970 			// Vehicle is now at the airport.
   984 			/* Vehicle is now at the airport. */
   971 			v->tile = st->airport_tile;
   985 			v->tile = st->airport_tile;
   972 
   986 
   973 			// Find altitude of landing position.
   987 			/* Find altitude of landing position. */
   974 			uint z = GetSlopeZ(x, y) + 1 + afc->delta_z;
   988 			uint z = GetSlopeZ(x, y) + 1 + afc->delta_z;
   975 
   989 
   976 			if (z == v->z_pos) {
   990 			if (z == v->z_pos) {
   977 				Vehicle *u = v->next->next;
   991 				Vehicle *u = v->next->next;
   978 
   992 
   979 				// Increase speed of rotors. When speed is 80, we've landed.
   993 				/*  Increase speed of rotors. When speed is 80, we've landed. */
   980 				if (u->cur_speed >= 80) return true;
   994 				if (u->cur_speed >= 80) return true;
   981 				u->cur_speed += 4;
   995 				u->cur_speed += 4;
   982 			} else if (v->z_pos > z) {
   996 			} else if (v->z_pos > z) {
   983 				SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos-1);
   997 				SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos-1);
   984 			} else {
   998 			} else {
   986 			}
  1000 			}
   987 		}
  1001 		}
   988 		return false;
  1002 		return false;
   989 	}
  1003 	}
   990 
  1004 
   991 	// Get distance from destination pos to current pos.
  1005 	/* Get distance from destination pos to current pos. */
   992 	uint dist = myabs(x + amd->x - v->x_pos) +  myabs(y + amd->y - v->y_pos);
  1006 	uint dist = myabs(x + amd->x - v->x_pos) +  myabs(y + amd->y - v->y_pos);
   993 
  1007 
   994 	// Need exact position?
  1008 	/* Need exact position? */
   995 	if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U))
  1009 	if (!(amd->flag & AMED_EXACTPOS) && dist <= (amd->flag & AMED_SLOWTURN ? 8U : 4U))
   996 		return true;
  1010 		return true;
   997 
  1011 
   998 	// At final pos?
  1012 	/* At final pos? */
   999 	if (dist == 0) {
  1013 	if (dist == 0) {
  1000 		// Change direction smoothly to final direction.
  1014 		/* Change direction smoothly to final direction. */
  1001 		DirDiff dirdiff = DirDifference(amd->direction, v->direction);
  1015 		DirDiff dirdiff = DirDifference(amd->direction, v->direction);
  1002 		// if distance is 0, and plane points in right direction, no point in calling
  1016 		/* if distance is 0, and plane points in right direction, no point in calling
  1003 		// UpdateAircraftSpeed(). So do it only afterwards
  1017 		 * UpdateAircraftSpeed(). So do it only afterwards */
  1004 		if (dirdiff == DIRDIFF_SAME) {
  1018 		if (dirdiff == DIRDIFF_SAME) {
  1005 			v->cur_speed = 0;
  1019 			v->cur_speed = 0;
  1006 			return true;
  1020 			return true;
  1007 		}
  1021 		}
  1008 
  1022 
  1017 
  1031 
  1018 	if (!UpdateAircraftSpeed(v, ((amd->flag & AMED_NOSPDCLAMP) == 0) ? SPEED_LIMIT_TAXI : SPEED_LIMIT_NONE)) return false;
  1032 	if (!UpdateAircraftSpeed(v, ((amd->flag & AMED_NOSPDCLAMP) == 0) ? SPEED_LIMIT_TAXI : SPEED_LIMIT_NONE)) return false;
  1019 
  1033 
  1020 	if (v->load_unload_time_rem != 0) v->load_unload_time_rem--;
  1034 	if (v->load_unload_time_rem != 0) v->load_unload_time_rem--;
  1021 
  1035 
  1022 	// Turn. Do it slowly if in the air.
  1036 	/* Turn. Do it slowly if in the air. */
  1023 	Direction newdir = GetDirectionTowards(v, x + amd->x, y + amd->y);
  1037 	Direction newdir = GetDirectionTowards(v, x + amd->x, y + amd->y);
  1024 	if (newdir != v->direction) {
  1038 	if (newdir != v->direction) {
  1025 		if (amd->flag & AMED_SLOWTURN) {
  1039 		if (amd->flag & AMED_SLOWTURN) {
  1026 			if (v->load_unload_time_rem == 0) v->load_unload_time_rem = 8;
  1040 			if (v->load_unload_time_rem == 0) v->load_unload_time_rem = 8;
  1027 			v->direction = newdir;
  1041 			v->direction = newdir;
  1029 			v->cur_speed >>= 1;
  1043 			v->cur_speed >>= 1;
  1030 			v->direction = newdir;
  1044 			v->direction = newdir;
  1031 		}
  1045 		}
  1032 	}
  1046 	}
  1033 
  1047 
  1034 	// Move vehicle.
  1048 	/* Move vehicle. */
  1035 	GetNewVehiclePosResult gp;
  1049 	GetNewVehiclePosResult gp;
  1036 	GetNewVehiclePos(v, &gp);
  1050 	GetNewVehiclePos(v, &gp);
  1037 	v->tile = gp.new_tile;
  1051 	v->tile = gp.new_tile;
  1038 
  1052 
  1039 	// If vehicle is in the air, use tile coordinate 0.
  1053 	/* If vehicle is in the air, use tile coordinate 0. */
  1040 	if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0;
  1054 	if (amd->flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0;
  1041 
  1055 
  1042 	// Adjust Z for land or takeoff?
  1056 	/* Adjust Z for land or takeoff? */
  1043 	uint z = v->z_pos;
  1057 	uint z = v->z_pos;
  1044 
  1058 
  1045 	if (amd->flag & AMED_TAKEOFF) {
  1059 	if (amd->flag & AMED_TAKEOFF) {
  1046 		z = min(z + 2, GetAircraftFlyingAltitude(v));
  1060 		z = min(z + 2, GetAircraftFlyingAltitude(v));
  1047 	}
  1061 	}
  1048 
  1062 
  1049 	if (amd->flag & AMED_LAND) {
  1063 	if (amd->flag & AMED_LAND) {
  1050 		if (st->airport_tile == 0) {
  1064 		if (st->airport_tile == 0) {
  1051 			v->u.air.state = FLYING;
  1065 			v->u.air.state = FLYING;
  1052 			AircraftNextAirportPos_and_Order(v);
  1066 			AircraftNextAirportPos_and_Order(v);
  1053 			// get aircraft back on running altitude
  1067 			/* get aircraft back on running altitude */
  1054 			SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
  1068 			SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
  1055 			return false;
  1069 			return false;
  1056 		}
  1070 		}
  1057 
  1071 
  1058 		uint curz = GetSlopeZ(x, y) + 1;
  1072 		uint curz = GetSlopeZ(x, y) + 1;
  1065 			z -= ((z - curz) + t - 1) / t;
  1079 			z -= ((z - curz) + t - 1) / t;
  1066 			if (z < curz) z = curz;
  1080 			if (z < curz) z = curz;
  1067 		}
  1081 		}
  1068 	}
  1082 	}
  1069 
  1083 
  1070 	// We've landed. Decrase speed when we're reaching end of runway.
  1084 	/* We've landed. Decrase speed when we're reaching end of runway. */
  1071 	if (amd->flag & AMED_BRAKE) {
  1085 	if (amd->flag & AMED_BRAKE) {
  1072 		uint curz = GetSlopeZ(x, y) + 1;
  1086 		uint curz = GetSlopeZ(x, y) + 1;
  1073 
  1087 
  1074 		if (z > curz) {
  1088 		if (z > curz) {
  1075 			z--;
  1089 			z--;
  1089 {
  1103 {
  1090 	v->u.air.crashed_counter++;
  1104 	v->u.air.crashed_counter++;
  1091 
  1105 
  1092 	Station *st = GetStation(v->u.air.targetairport);
  1106 	Station *st = GetStation(v->u.air.targetairport);
  1093 
  1107 
  1094 	// make aircraft crash down to the ground
  1108 	/* make aircraft crash down to the ground */
  1095 	if (v->u.air.crashed_counter < 500 && st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) {
  1109 	if (v->u.air.crashed_counter < 500 && st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) {
  1096 		uint z = GetSlopeZ(v->x_pos, v->y_pos);
  1110 		uint z = GetSlopeZ(v->x_pos, v->y_pos);
  1097 		v->z_pos -= 1;
  1111 		v->z_pos -= 1;
  1098 		if (v->z_pos == z) {
  1112 		if (v->z_pos == z) {
  1099 			v->u.air.crashed_counter = 500;
  1113 			v->u.air.crashed_counter = 500;
  1116 				GB(r, 4, 4) + 4,
  1130 				GB(r, 4, 4) + 4,
  1117 				GB(r, 8, 4),
  1131 				GB(r, 8, 4),
  1118 				EV_EXPLOSION_SMALL);
  1132 				EV_EXPLOSION_SMALL);
  1119 		}
  1133 		}
  1120 	} else if (v->u.air.crashed_counter >= 10000) {
  1134 	} else if (v->u.air.crashed_counter >= 10000) {
  1121 		// remove rubble of crashed airplane
  1135 		/*  remove rubble of crashed airplane */
  1122 
  1136 
  1123 		// clear runway-in on all airports, set by crashing plane
  1137 		/* clear runway-in on all airports, set by crashing plane
  1124 		// small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
  1138 		 * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
  1125 		// but they all share the same number
  1139 		 * but they all share the same number */
  1126 		CLRBITS(st->airport_flags, RUNWAY_IN_block);
  1140 		CLRBITS(st->airport_flags, RUNWAY_IN_block);
  1127 		CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport
  1141 		CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport
  1128 		CLRBITS(st->airport_flags, RUNWAY_IN2_block); // intercontinental
  1142 		CLRBITS(st->airport_flags, RUNWAY_IN2_block);    // intercontinental
  1129 
  1143 
  1130 		BeginVehicleMove(v);
  1144 		BeginVehicleMove(v);
  1131 		EndVehicleMove(v);
  1145 		EndVehicleMove(v);
  1132 
  1146 
  1133 		DoDeleteAircraft(v);
  1147 		DoDeleteAircraft(v);
  1215 			order->dest  == v->current_order.dest)
  1229 			order->dest  == v->current_order.dest)
  1216 		return;
  1230 		return;
  1217 
  1231 
  1218 	v->current_order = *order;
  1232 	v->current_order = *order;
  1219 
  1233 
  1220 	// orders are changed in flight, ensure going to the right station
  1234 	/* orders are changed in flight, ensure going to the right station */
  1221 	if (order->type == OT_GOTO_STATION && v->u.air.state == FLYING) {
  1235 	if (order->type == OT_GOTO_STATION && v->u.air.state == FLYING) {
  1222 		AircraftNextAirportPos_and_Order(v);
  1236 		AircraftNextAirportPos_and_Order(v);
  1223 	}
  1237 	}
  1224 
  1238 
  1225 	InvalidateVehicleOrder(v);
  1239 	InvalidateVehicleOrder(v);
  1308 
  1322 
  1309 static void MaybeCrashAirplane(Vehicle *v)
  1323 static void MaybeCrashAirplane(Vehicle *v)
  1310 {
  1324 {
  1311 	Station *st = GetStation(v->u.air.targetairport);
  1325 	Station *st = GetStation(v->u.air.targetairport);
  1312 
  1326 
  1313 	//FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports
  1327 	/* FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports */
  1314 	uint16 prob = 0x10000 / 1500;
  1328 	uint16 prob = 0x10000 / 1500;
  1315 	if (st->Airport()->flags & AirportFTAClass::SHORT_STRIP &&
  1329 	if (st->Airport()->flags & AirportFTAClass::SHORT_STRIP &&
  1316 			AircraftVehInfo(v->engine_type)->subtype & AIR_FAST &&
  1330 			AircraftVehInfo(v->engine_type)->subtype & AIR_FAST &&
  1317 			!_cheats.no_jetcrash.value) {
  1331 			!_cheats.no_jetcrash.value) {
  1318 		prob = 0x10000 / 20;
  1332 		prob = 0x10000 / 20;
  1319 	}
  1333 	}
  1320 
  1334 
  1321 	if (GB(Random(), 0, 16) > prob) return;
  1335 	if (GB(Random(), 0, 16) > prob) return;
  1322 
  1336 
  1323 	// Crash the airplane. Remove all goods stored at the station.
  1337 	/* Crash the airplane. Remove all goods stored at the station. */
  1324 	for (uint i = 0; i != NUM_CARGO; i++) {
  1338 	for (uint i = 0; i != NUM_CARGO; i++) {
  1325 		st->goods[i].rating = 1;
  1339 		st->goods[i].rating = 1;
  1326 		SB(st->goods[i].waiting_acceptance, 0, 12, 0);
  1340 		SB(st->goods[i].waiting_acceptance, 0, 12, 0);
  1327 	}
  1341 	}
  1328 
  1342 
  1329 	CrashAirplane(v);
  1343 	CrashAirplane(v);
  1330 }
  1344 }
  1331 
  1345 
  1332 // we've landed and just arrived at a terminal
  1346 /** we've landed and just arrived at a terminal */
  1333 static void AircraftEntersTerminal(Vehicle *v)
  1347 static void AircraftEntersTerminal(Vehicle *v)
  1334 {
  1348 {
  1335 	if (v->current_order.type == OT_GOTO_DEPOT) return;
  1349 	if (v->current_order.type == OT_GOTO_DEPOT) return;
  1336 
  1350 
  1337 	Station *st = GetStation(v->u.air.targetairport);
  1351 	Station *st = GetStation(v->u.air.targetairport);
  1341 	if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
  1355 	if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
  1342 		uint32 flags;
  1356 		uint32 flags;
  1343 
  1357 
  1344 		st->had_vehicle_of_type |= HVOT_AIRCRAFT;
  1358 		st->had_vehicle_of_type |= HVOT_AIRCRAFT;
  1345 		SetDParam(0, st->index);
  1359 		SetDParam(0, st->index);
  1346 		// show newsitem of celebrating citizens
  1360 		/* show newsitem of celebrating citizens */
  1347 		flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
  1361 		flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
  1348 		AddNewsItem(
  1362 		AddNewsItem(
  1349 			STR_A033_CITIZENS_CELEBRATE_FIRST,
  1363 			STR_A033_CITIZENS_CELEBRATE_FIRST,
  1350 			flags,
  1364 			flags,
  1351 			v->index,
  1365 			v->index,
  1418 	}
  1432 	}
  1419 	return apc->entry_points[dir];
  1433 	return apc->entry_points[dir];
  1420 }
  1434 }
  1421 
  1435 
  1422 
  1436 
  1423 // set the right pos when heading to other airports after takeoff
  1437 /** set the right pos when heading to other airports after takeoff */
  1424 static void AircraftNextAirportPos_and_Order(Vehicle *v)
  1438 static void AircraftNextAirportPos_and_Order(Vehicle *v)
  1425 {
  1439 {
  1426 	if (v->current_order.type == OT_GOTO_STATION ||
  1440 	if (v->current_order.type == OT_GOTO_STATION ||
  1427 			v->current_order.type == OT_GOTO_DEPOT)
  1441 			v->current_order.type == OT_GOTO_DEPOT)
  1428 		v->u.air.targetairport = v->current_order.dest;
  1442 		v->u.air.targetairport = v->current_order.dest;
  1440 	v->vehstatus &= ~VS_HIDDEN;
  1454 	v->vehstatus &= ~VS_HIDDEN;
  1441 	{
  1455 	{
  1442 		Vehicle *u = v->next;
  1456 		Vehicle *u = v->next;
  1443 		u->vehstatus &= ~VS_HIDDEN;
  1457 		u->vehstatus &= ~VS_HIDDEN;
  1444 
  1458 
  1445 		// Rotor blades
  1459 		/* Rotor blades */
  1446 		u = u->next;
  1460 		u = u->next;
  1447 		if (u != NULL) {
  1461 		if (u != NULL) {
  1448 			u->vehstatus &= ~VS_HIDDEN;
  1462 			u->vehstatus &= ~VS_HIDDEN;
  1449 			u->cur_speed = 80;
  1463 			u->cur_speed = 80;
  1450 		}
  1464 		}
  1470 {
  1484 {
  1471 	VehicleEnterDepot(v);
  1485 	VehicleEnterDepot(v);
  1472 	v->u.air.state = apc->layout[v->u.air.pos].heading;
  1486 	v->u.air.state = apc->layout[v->u.air.pos].heading;
  1473 }
  1487 }
  1474 
  1488 
  1475 // In an Airport Hangar
  1489 /** In an Airport Hangar */
  1476 static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *apc)
  1490 static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *apc)
  1477 {
  1491 {
  1478 	// if we just arrived, execute EnterHangar first
  1492 	/* if we just arrived, execute EnterHangar first */
  1479 	if (v->u.air.previous_pos != v->u.air.pos) {
  1493 	if (v->u.air.previous_pos != v->u.air.pos) {
  1480 		AircraftEventHandler_EnterHangar(v, apc);
  1494 		AircraftEventHandler_EnterHangar(v, apc);
  1481 		return;
  1495 		return;
  1482 	}
  1496 	}
  1483 
  1497 
  1484 	// if we were sent to the depot, stay there
  1498 	/* if we were sent to the depot, stay there */
  1485 	if (v->current_order.type == OT_GOTO_DEPOT && (v->vehstatus & VS_STOPPED)) {
  1499 	if (v->current_order.type == OT_GOTO_DEPOT && (v->vehstatus & VS_STOPPED)) {
  1486 		v->current_order.type = OT_NOTHING;
  1500 		v->current_order.type = OT_NOTHING;
  1487 		v->current_order.flags = 0;
  1501 		v->current_order.flags = 0;
  1488 		return;
  1502 		return;
  1489 	}
  1503 	}
  1490 
  1504 
  1491 	if (v->current_order.type != OT_GOTO_STATION &&
  1505 	if (v->current_order.type != OT_GOTO_STATION &&
  1492 			v->current_order.type != OT_GOTO_DEPOT)
  1506 			v->current_order.type != OT_GOTO_DEPOT)
  1493 		return;
  1507 		return;
  1494 
  1508 
  1495 	// if the block of the next position is busy, stay put
  1509 	/* if the block of the next position is busy, stay put */
  1496 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1510 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1497 
  1511 
  1498 	// We are already at the target airport, we need to find a terminal
  1512 	/* We are already at the target airport, we need to find a terminal */
  1499 	if (v->current_order.dest == v->u.air.targetairport) {
  1513 	if (v->current_order.dest == v->u.air.targetairport) {
  1500 		// FindFreeTerminal:
  1514 		/* FindFreeTerminal:
  1501 		// 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal
  1515 		 * 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
  1502 		if (v->subtype == AIR_HELICOPTER) {
  1516 		if (v->subtype == AIR_HELICOPTER) {
  1503 			if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
  1517 			if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
  1504 		} else {
  1518 		} else {
  1505 			if (!AirportFindFreeTerminal(v, apc)) return; // airplane
  1519 			if (!AirportFindFreeTerminal(v, apc)) return; // airplane
  1506 		}
  1520 		}
  1507 	} else { // Else prepare for launch.
  1521 	} else { // Else prepare for launch.
  1508 		// airplane goto state takeoff, helicopter to helitakeoff
  1522 		/* airplane goto state takeoff, helicopter to helitakeoff */
  1509 		v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
  1523 		v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
  1510 	}
  1524 	}
  1511 	AircraftLeaveHangar(v);
  1525 	AircraftLeaveHangar(v);
  1512 	AirportMove(v, apc);
  1526 	AirportMove(v, apc);
  1513 }
  1527 }
  1514 
  1528 
  1515 // At one of the Airport's Terminals
  1529 /** At one of the Airport's Terminals */
  1516 static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *apc)
  1530 static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *apc)
  1517 {
  1531 {
  1518 	// if we just arrived, execute EnterTerminal first
  1532 	/* if we just arrived, execute EnterTerminal first */
  1519 	if (v->u.air.previous_pos != v->u.air.pos) {
  1533 	if (v->u.air.previous_pos != v->u.air.pos) {
  1520 		AircraftEventHandler_EnterTerminal(v, apc);
  1534 		AircraftEventHandler_EnterTerminal(v, apc);
  1521 		// on an airport with helipads, a helicopter will always land there
  1535 		/* on an airport with helipads, a helicopter will always land there
  1522 		// and get serviced at the same time - patch setting
  1536 		 * and get serviced at the same time - patch setting */
  1523 		if (_patches.serviceathelipad) {
  1537 		if (_patches.serviceathelipad) {
  1524 			if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) {
  1538 			if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) {
  1525 				// an exerpt of ServiceAircraft, without the invisibility stuff
  1539 				/* an exerpt of ServiceAircraft, without the invisibility stuff */
  1526 				v->date_of_last_service = _date;
  1540 				v->date_of_last_service = _date;
  1527 				v->breakdowns_since_last_service = 0;
  1541 				v->breakdowns_since_last_service = 0;
  1528 				v->reliability = GetEngine(v->engine_type)->reliability;
  1542 				v->reliability = GetEngine(v->engine_type)->reliability;
  1529 				InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1543 				InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1530 			}
  1544 			}
  1532 		return;
  1546 		return;
  1533 	}
  1547 	}
  1534 
  1548 
  1535 	if (v->current_order.type == OT_NOTHING) return;
  1549 	if (v->current_order.type == OT_NOTHING) return;
  1536 
  1550 
  1537 	// if the block of the next position is busy, stay put
  1551 	/* if the block of the next position is busy, stay put */
  1538 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1552 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1539 
  1553 
  1540 	// airport-road is free. We either have to go to another airport, or to the hangar
  1554 	/* airport-road is free. We either have to go to another airport, or to the hangar
  1541 	// ---> start moving
  1555 	 * ---> start moving */
  1542 
  1556 
  1543 	switch (v->current_order.type) {
  1557 	switch (v->current_order.type) {
  1544 		case OT_GOTO_STATION: // ready to fly to another airport
  1558 		case OT_GOTO_STATION: // ready to fly to another airport
  1545 			// airplane goto state takeoff, helicopter to helitakeoff
  1559 			/* airplane goto state takeoff, helicopter to helitakeoff */
  1546 			v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
  1560 			v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
  1547 			break;
  1561 			break;
  1548 		case OT_GOTO_DEPOT:   // visit hangar for serivicing, sale, etc.
  1562 		case OT_GOTO_DEPOT:   // visit hangar for serivicing, sale, etc.
  1549 			if (v->current_order.dest == v->u.air.targetairport) {
  1563 			if (v->current_order.dest == v->u.air.targetairport) {
  1550 				v->u.air.state = HANGAR;
  1564 				v->u.air.state = HANGAR;
  1578 }
  1592 }
  1579 
  1593 
  1580 static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *apc)
  1594 static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *apc)
  1581 {
  1595 {
  1582 	v->u.air.state = FLYING;
  1596 	v->u.air.state = FLYING;
  1583 	// get the next position to go to, differs per airport
  1597 	/* get the next position to go to, differs per airport */
  1584 	AircraftNextAirportPos_and_Order(v);
  1598 	AircraftNextAirportPos_and_Order(v);
  1585 }
  1599 }
  1586 
  1600 
  1587 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc)
  1601 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc)
  1588 {
  1602 {
  1589 	const Player* p = GetPlayer(v->owner);
  1603 	const Player* p = GetPlayer(v->owner);
  1590 	v->sprite_width = v->sprite_height = 24; // ??? no idea what this is
  1604 	v->sprite_width = v->sprite_height = 24; // ??? no idea what this is
  1591 	v->u.air.state = FLYING;
  1605 	v->u.air.state = FLYING;
  1592 	// get the next position to go to, differs per airport
  1606 	/* get the next position to go to, differs per airport */
  1593 	AircraftNextAirportPos_and_Order(v);
  1607 	AircraftNextAirportPos_and_Order(v);
  1594 
  1608 
  1595 	// check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
  1609 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
  1596 	// unless it is due for renewal but the engine is no longer available
  1610 	 * unless it is due for renewal but the engine is no longer available */
  1597 	if (v->owner == _local_player && (
  1611 	if (v->owner == _local_player && (
  1598 				EngineHasReplacementForPlayer(p, v->engine_type) ||
  1612 				EngineHasReplacementForPlayer(p, v->engine_type) ||
  1599 				((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
  1613 				((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
  1600 				HASBIT(GetEngine(v->engine_type)->player_avail, _local_player))
  1614 				HASBIT(GetEngine(v->engine_type)->player_avail, _local_player))
  1601 			)) {
  1615 			)) {
  1607 
  1621 
  1608 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc)
  1622 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc)
  1609 {
  1623 {
  1610 	Station *st = GetStation(v->u.air.targetairport);
  1624 	Station *st = GetStation(v->u.air.targetairport);
  1611 
  1625 
  1612 	// runway busy or not allowed to use this airstation, circle
  1626 	/* runway busy or not allowed to use this airstation, circle */
  1613 	if (apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES) &&
  1627 	if (apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES) &&
  1614 			st->airport_tile != 0 &&
  1628 			st->airport_tile != 0 &&
  1615 			(st->owner == OWNER_NONE || st->owner == v->owner)) {
  1629 			(st->owner == OWNER_NONE || st->owner == v->owner)) {
  1616 		// {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
  1630 		// {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
  1617 		// if it is an airplane, look for LANDING, for helicopter HELILANDING
  1631 		// if it is an airplane, look for LANDING, for helicopter HELILANDING
  1618 		// it is possible to choose from multiple landing runways, so loop until a free one is found
  1632 		// it is possible to choose from multiple landing runways, so loop until a free one is found
  1619 		byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
  1633 		byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
  1620 		const AirportFTA *current = apc->layout[v->u.air.pos].next;
  1634 		const AirportFTA *current = apc->layout[v->u.air.pos].next;
  1621 		while (current != NULL) {
  1635 		while (current != NULL) {
  1622 			if (current->heading == landingtype) {
  1636 			if (current->heading == landingtype) {
  1623 				// save speed before, since if AirportHasBlock is false, it resets them to 0
  1637 				/* save speed before, since if AirportHasBlock is false, it resets them to 0
  1624 				// we don't want that for plane in air
  1638 				 * we don't want that for plane in air
  1625 				// hack for speed thingie
  1639 				 * hack for speed thingie */
  1626 				uint16 tcur_speed = v->cur_speed;
  1640 				uint16 tcur_speed = v->cur_speed;
  1627 				uint16 tsubspeed = v->subspeed;
  1641 				uint16 tsubspeed = v->subspeed;
  1628 				if (!AirportHasBlock(v, current, apc)) {
  1642 				if (!AirportHasBlock(v, current, apc)) {
  1629 					v->u.air.state = landingtype; // LANDING / HELILANDING
  1643 					v->u.air.state = landingtype; // LANDING / HELILANDING
  1630 					// it's a bit dirty, but I need to set position to next position, otherwise
  1644 					/* it's a bit dirty, but I need to set position to next position, otherwise
  1631 					// if there are multiple runways, plane won't know which one it took (because
  1645 					 * if there are multiple runways, plane won't know which one it took (because
  1632 					// they all have heading LANDING). And also occupy that block!
  1646 					 * they all have heading LANDING). And also occupy that block! */
  1633 					v->u.air.pos = current->next_position;
  1647 					v->u.air.pos = current->next_position;
  1634 					SETBITS(st->airport_flags, apc->layout[v->u.air.pos].block);
  1648 					SETBITS(st->airport_flags, apc->layout[v->u.air.pos].block);
  1635 					return;
  1649 					return;
  1636 				}
  1650 				}
  1637 				v->cur_speed = tcur_speed;
  1651 				v->cur_speed = tcur_speed;
  1646 
  1660 
  1647 static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *apc)
  1661 static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *apc)
  1648 {
  1662 {
  1649 	AircraftLandAirplane(v);  // maybe crash airplane
  1663 	AircraftLandAirplane(v);  // maybe crash airplane
  1650 	v->u.air.state = ENDLANDING;
  1664 	v->u.air.state = ENDLANDING;
  1651 	// check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
  1665 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
  1652 	if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) {
  1666 	if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) {
  1653 		// only the vehicle owner needs to calculate the rest (locally)
  1667 		/* only the vehicle owner needs to calculate the rest (locally) */
  1654 		const Player* p = GetPlayer(v->owner);
  1668 		const Player* p = GetPlayer(v->owner);
  1655 		if (EngineHasReplacementForPlayer(p, v->engine_type) ||
  1669 		if (EngineHasReplacementForPlayer(p, v->engine_type) ||
  1656 			(p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) {
  1670 			(p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) {
  1657 			// send the aircraft to the hangar at next airport
  1671 			/* send the aircraft to the hangar at next airport */
  1658 			_current_player = _local_player;
  1672 			_current_player = _local_player;
  1659 			DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
  1673 			DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
  1660 			_current_player = OWNER_NONE;
  1674 			_current_player = OWNER_NONE;
  1661 		}
  1675 		}
  1662 	}
  1676 	}
  1668 	v->u.air.state = HELIENDLANDING;
  1682 	v->u.air.state = HELIENDLANDING;
  1669 }
  1683 }
  1670 
  1684 
  1671 static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *apc)
  1685 static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *apc)
  1672 {
  1686 {
  1673 	// next block busy, don't do a thing, just wait
  1687 	/* next block busy, don't do a thing, just wait */
  1674 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1688 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1675 
  1689 
  1676 	// if going to terminal (OT_GOTO_STATION) choose one
  1690 	/* if going to terminal (OT_GOTO_STATION) choose one
  1677 	// 1. in case all terminals are busy AirportFindFreeTerminal() returns false or
  1691 	 * 1. in case all terminals are busy AirportFindFreeTerminal() returns false or
  1678 	// 2. not going for terminal (but depot, no order),
  1692 	 * 2. not going for terminal (but depot, no order),
  1679 	// --> get out of the way to the hangar.
  1693 	 * --> get out of the way to the hangar. */
  1680 	if (v->current_order.type == OT_GOTO_STATION) {
  1694 	if (v->current_order.type == OT_GOTO_STATION) {
  1681 		if (AirportFindFreeTerminal(v, apc)) return;
  1695 		if (AirportFindFreeTerminal(v, apc)) return;
  1682 	}
  1696 	}
  1683 	v->u.air.state = HANGAR;
  1697 	v->u.air.state = HANGAR;
  1684 
  1698 
  1685 }
  1699 }
  1686 
  1700 
  1687 static void AircraftEventHandler_HeliEndLanding(Vehicle *v, const AirportFTAClass *apc)
  1701 static void AircraftEventHandler_HeliEndLanding(Vehicle *v, const AirportFTAClass *apc)
  1688 {
  1702 {
  1689 	// next block busy, don't do a thing, just wait
  1703 	/*  next block busy, don't do a thing, just wait */
  1690 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1704 	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
  1691 
  1705 
  1692 	// if going to helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal
  1706 	/* if going to helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal
  1693 	// 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or
  1707 	 * 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or
  1694 	// 2. not going for terminal (but depot, no order),
  1708 	 * 2. not going for terminal (but depot, no order),
  1695 	// --> get out of the way to the hangar IF there are terminals on the airport.
  1709 	 * --> get out of the way to the hangar IF there are terminals on the airport.
  1696 	// --> else TAKEOFF
  1710 	 * --> else TAKEOFF
  1697 	// the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
  1711 	 * the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
  1698 	// must go to a hangar.
  1712 	 * must go to a hangar. */
  1699 	if (v->current_order.type == OT_GOTO_STATION) {
  1713 	if (v->current_order.type == OT_GOTO_STATION) {
  1700 		if (AirportFindFreeHelipad(v, apc)) return;
  1714 		if (AirportFindFreeHelipad(v, apc)) return;
  1701 	}
  1715 	}
  1702 	v->u.air.state = (apc->nof_depots != 0) ? HANGAR : HELITAKEOFF;
  1716 	v->u.air.state = (apc->nof_depots != 0) ? HANGAR : HELITAKEOFF;
  1703 }
  1717 }
  1729 	AircraftEventHandler_AtTerminal,     // HELIPAD4       = 22
  1743 	AircraftEventHandler_AtTerminal,     // HELIPAD4       = 22
  1730 };
  1744 };
  1731 
  1745 
  1732 static void AirportClearBlock(const Vehicle *v, const AirportFTAClass *apc)
  1746 static void AirportClearBlock(const Vehicle *v, const AirportFTAClass *apc)
  1733 {
  1747 {
  1734 	// we have left the previous block, and entered the new one. Free the previous block
  1748 	/* we have left the previous block, and entered the new one. Free the previous block */
  1735 	if (apc->layout[v->u.air.previous_pos].block != apc->layout[v->u.air.pos].block) {
  1749 	if (apc->layout[v->u.air.previous_pos].block != apc->layout[v->u.air.pos].block) {
  1736 		Station *st = GetStation(v->u.air.targetairport);
  1750 		Station *st = GetStation(v->u.air.targetairport);
  1737 
  1751 
  1738 		CLRBITS(st->airport_flags, apc->layout[v->u.air.previous_pos].block);
  1752 		CLRBITS(st->airport_flags, apc->layout[v->u.air.previous_pos].block);
  1739 	}
  1753 	}
  1740 }
  1754 }
  1741 
  1755 
  1742 static void AirportGoToNextPosition(Vehicle *v)
  1756 static void AirportGoToNextPosition(Vehicle *v)
  1743 {
  1757 {
  1744 	// if aircraft is not in position, wait until it is
  1758 	/* if aircraft is not in position, wait until it is */
  1745 	if (!AircraftController(v)) return;
  1759 	if (!AircraftController(v)) return;
  1746 
  1760 
  1747 	const AirportFTAClass *apc = GetStation(v->u.air.targetairport)->Airport();
  1761 	const AirportFTAClass *apc = GetStation(v->u.air.targetairport)->Airport();
  1748 
  1762 
  1749 	AirportClearBlock(v, apc);
  1763 	AirportClearBlock(v, apc);
  1750 	AirportMove(v, apc); // move aircraft to next position
  1764 	AirportMove(v, apc); // move aircraft to next position
  1751 }
  1765 }
  1752 
  1766 
  1753 // gets pos from vehicle and next orders
  1767 /* gets pos from vehicle and next orders */
  1754 static bool AirportMove(Vehicle *v, const AirportFTAClass *apc)
  1768 static bool AirportMove(Vehicle *v, const AirportFTAClass *apc)
  1755 {
  1769 {
  1756 	// error handling
  1770 	/* error handling */
  1757 	if (v->u.air.pos >= apc->nofelements) {
  1771 	if (v->u.air.pos >= apc->nofelements) {
  1758 		DEBUG(misc, 0, "[Ap] position %d is not valid for current airport. Max position is %d", v->u.air.pos, apc->nofelements-1);
  1772 		DEBUG(misc, 0, "[Ap] position %d is not valid for current airport. Max position is %d", v->u.air.pos, apc->nofelements-1);
  1759 		assert(v->u.air.pos < apc->nofelements);
  1773 		assert(v->u.air.pos < apc->nofelements);
  1760 	}
  1774 	}
  1761 
  1775 
  1762 	const AirportFTA *current = &apc->layout[v->u.air.pos];
  1776 	const AirportFTA *current = &apc->layout[v->u.air.pos];
  1763 	// we have arrived in an important state (eg terminal, hangar, etc.)
  1777 	/* we have arrived in an important state (eg terminal, hangar, etc.) */
  1764 	if (current->heading == v->u.air.state) {
  1778 	if (current->heading == v->u.air.state) {
  1765 		byte prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand
  1779 		byte prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand
  1766 		_aircraft_state_handlers[v->u.air.state](v, apc);
  1780 		_aircraft_state_handlers[v->u.air.state](v, apc);
  1767 		if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos;
  1781 		if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos;
  1768 		return true;
  1782 		return true;
  1769 	}
  1783 	}
  1770 
  1784 
  1771 	v->u.air.previous_pos = v->u.air.pos; // save previous location
  1785 	v->u.air.previous_pos = v->u.air.pos; // save previous location
  1772 
  1786 
  1773 	// there is only one choice to move to
  1787 	/* there is only one choice to move to */
  1774 	if (current->next == NULL) {
  1788 	if (current->next == NULL) {
  1775 		if (AirportSetBlocks(v, current, apc)) {
  1789 		if (AirportSetBlocks(v, current, apc)) {
  1776 			v->u.air.pos = current->next_position;
  1790 			v->u.air.pos = current->next_position;
  1777 		} // move to next position
  1791 		} // move to next position
  1778 		return false;
  1792 		return false;
  1779 	}
  1793 	}
  1780 
  1794 
  1781 	// there are more choices to choose from, choose the one that
  1795 	/* there are more choices to choose from, choose the one that
  1782 	// matches our heading
  1796 	 * matches our heading */
  1783 	do {
  1797 	do {
  1784 		if (v->u.air.state == current->heading || current->heading == TO_ALL) {
  1798 		if (v->u.air.state == current->heading || current->heading == TO_ALL) {
  1785 			if (AirportSetBlocks(v, current, apc)) {
  1799 			if (AirportSetBlocks(v, current, apc)) {
  1786 				v->u.air.pos = current->next_position;
  1800 				v->u.air.pos = current->next_position;
  1787 			} // move to next position
  1801 			} // move to next position
  1793 	DEBUG(misc, 0, "[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->u.air.pos, v->u.air.state, v->index);
  1807 	DEBUG(misc, 0, "[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->u.air.pos, v->u.air.state, v->index);
  1794 	assert(0);
  1808 	assert(0);
  1795 	return false;
  1809 	return false;
  1796 }
  1810 }
  1797 
  1811 
  1798 // returns true if the road ahead is busy, eg. you must wait before proceeding
  1812 /*  returns true if the road ahead is busy, eg. you must wait before proceeding */
  1799 static bool AirportHasBlock(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
  1813 static bool AirportHasBlock(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
  1800 {
  1814 {
  1801 	const AirportFTA *reference = &apc->layout[v->u.air.pos];
  1815 	const AirportFTA *reference = &apc->layout[v->u.air.pos];
  1802 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1816 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1803 
  1817 
  1804 	// same block, then of course we can move
  1818 	/* same block, then of course we can move */
  1805 	if (apc->layout[current_pos->position].block != next->block) {
  1819 	if (apc->layout[current_pos->position].block != next->block) {
  1806 		const Station *st = GetStation(v->u.air.targetairport);
  1820 		const Station *st = GetStation(v->u.air.targetairport);
  1807 		uint64 airport_flags = next->block;
  1821 		uint64 airport_flags = next->block;
  1808 
  1822 
  1809 		// check additional possible extra blocks
  1823 		/* check additional possible extra blocks */
  1810 		if (current_pos != reference && current_pos->block != NOTHING_block) {
  1824 		if (current_pos != reference && current_pos->block != NOTHING_block) {
  1811 			airport_flags |= current_pos->block;
  1825 			airport_flags |= current_pos->block;
  1812 		}
  1826 		}
  1813 
  1827 
  1814 		if (HASBITS(st->airport_flags, airport_flags)) {
  1828 		if (HASBITS(st->airport_flags, airport_flags)) {
  1818 		}
  1832 		}
  1819 	}
  1833 	}
  1820 	return false;
  1834 	return false;
  1821 }
  1835 }
  1822 
  1836 
  1823 // returns true on success. Eg, next block was free and we have occupied it
  1837 /**
       
  1838  * ...
       
  1839  * @param v airplane that requires the operation
       
  1840  * @param currentpos of the vehicle in the list of blocks
       
  1841  * @param apc airport on which block is requsted to be set
       
  1842  * @returns true on success. Eg, next block was free and we have occupied it
       
  1843  */
  1824 static bool AirportSetBlocks(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
  1844 static bool AirportSetBlocks(Vehicle *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
  1825 {
  1845 {
  1826 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1846 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1827 	const AirportFTA *reference = &apc->layout[v->u.air.pos];
  1847 	const AirportFTA *reference = &apc->layout[v->u.air.pos];
  1828 
  1848 
  1829 	// if the next position is in another block, check it and wait until it is free
  1849 	/* if the next position is in another block, check it and wait until it is free */
  1830 	if ((apc->layout[current_pos->position].block & next->block) != next->block) {
  1850 	if ((apc->layout[current_pos->position].block & next->block) != next->block) {
  1831 		uint64 airport_flags = next->block;
  1851 		uint64 airport_flags = next->block;
  1832 		//search for all all elements in the list with the same state, and blocks != N
  1852 		/* search for all all elements in the list with the same state, and blocks != N
  1833 		// this means more blocks should be checked/set
  1853 		 * this means more blocks should be checked/set */
  1834 		const AirportFTA *current = current_pos;
  1854 		const AirportFTA *current = current_pos;
  1835 		if (current == reference) current = current->next;
  1855 		if (current == reference) current = current->next;
  1836 		while (current != NULL) {
  1856 		while (current != NULL) {
  1837 			if (current->heading == current_pos->heading && current->block != 0) {
  1857 			if (current->heading == current_pos->heading && current->block != 0) {
  1838 				airport_flags |= current->block;
  1858 				airport_flags |= current->block;
  1839 				break;
  1859 				break;
  1840 			}
  1860 			}
  1841 			current = current->next;
  1861 			current = current->next;
  1842 		};
  1862 		};
  1843 
  1863 
  1844 		// if the block to be checked is in the next position, then exclude that from
  1864 		/* if the block to be checked is in the next position, then exclude that from
  1845 		// checking, because it has been set by the airplane before
  1865 		 * checking, because it has been set by the airplane before */
  1846 		if (current_pos->block == next->block) airport_flags ^= next->block;
  1866 		if (current_pos->block == next->block) airport_flags ^= next->block;
  1847 
  1867 
  1848 		Station* st = GetStation(v->u.air.targetairport);
  1868 		Station* st = GetStation(v->u.air.targetairport);
  1849 		if (HASBITS(st->airport_flags, airport_flags)) {
  1869 		if (HASBITS(st->airport_flags, airport_flags)) {
  1850 			v->cur_speed = 0;
  1870 			v->cur_speed = 0;
  1862 static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal)
  1882 static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal)
  1863 {
  1883 {
  1864 	Station *st = GetStation(v->u.air.targetairport);
  1884 	Station *st = GetStation(v->u.air.targetairport);
  1865 	for (; i < last_terminal; i++) {
  1885 	for (; i < last_terminal; i++) {
  1866 		if (!HASBIT(st->airport_flags, _airport_terminal_flag[i])) {
  1886 		if (!HASBIT(st->airport_flags, _airport_terminal_flag[i])) {
  1867 			// TERMINAL# HELIPAD#
  1887 			/* TERMINAL# HELIPAD# */
  1868 			v->u.air.state = _airport_terminal_state[i]; // start moving to that terminal/helipad
  1888 			v->u.air.state = _airport_terminal_state[i]; // start moving to that terminal/helipad
  1869 			SETBIT(st->airport_flags, _airport_terminal_flag[i]); // occupy terminal/helipad
  1889 			SETBIT(st->airport_flags, _airport_terminal_flag[i]); // occupy terminal/helipad
  1870 			return true;
  1890 			return true;
  1871 		}
  1891 		}
  1872 	}
  1892 	}
  1899 		const AirportFTA *temp = apc->layout[v->u.air.pos].next;
  1919 		const AirportFTA *temp = apc->layout[v->u.air.pos].next;
  1900 
  1920 
  1901 		while (temp != NULL) {
  1921 		while (temp != NULL) {
  1902 			if (temp->heading == 255) {
  1922 			if (temp->heading == 255) {
  1903 				if (!HASBITS(st->airport_flags, temp->block)) {
  1923 				if (!HASBITS(st->airport_flags, temp->block)) {
  1904 					//read which group do we want to go to?
  1924 					/* read which group do we want to go to?
  1905 					//(the first free group)
  1925 					 * (the first free group) */
  1906 					uint target_group = temp->next_position + 1;
  1926 					uint target_group = temp->next_position + 1;
  1907 
  1927 
  1908 					//at what terminal does the group start?
  1928 					/* at what terminal does the group start?
  1909 					//that means, sum up all terminals of
  1929 					 * that means, sum up all terminals of
  1910 					//groups with lower number
  1930 					 * groups with lower number */
  1911 					uint group_start = 0;
  1931 					uint group_start = 0;
  1912 					for (uint i = 1; i < target_group; i++) {
  1932 					for (uint i = 1; i < target_group; i++) {
  1913 						group_start += apc->terminals[i];
  1933 						group_start += apc->terminals[i];
  1914 					}
  1934 					}
  1915 
  1935 
  1923 			}
  1943 			}
  1924 			temp = temp->next;
  1944 			temp = temp->next;
  1925 		}
  1945 		}
  1926 	}
  1946 	}
  1927 
  1947 
  1928 	// if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max)
  1948 	/* if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max) */
  1929 	return FreeTerminal(v, 0, GetNumTerminals(apc));
  1949 	return FreeTerminal(v, 0, GetNumTerminals(apc));
  1930 }
  1950 }
  1931 
  1951 
  1932 static uint GetNumHelipads(const AirportFTAClass *apc)
  1952 static uint GetNumHelipads(const AirportFTAClass *apc)
  1933 {
  1953 {
  1939 }
  1959 }
  1940 
  1960 
  1941 
  1961 
  1942 static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc)
  1962 static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc)
  1943 {
  1963 {
  1944 	// if an airport doesn't have helipads, use terminals
  1964 	/* if an airport doesn't have helipads, use terminals */
  1945 	if (apc->helipads == NULL) return AirportFindFreeTerminal(v, apc);
  1965 	if (apc->helipads == NULL) return AirportFindFreeTerminal(v, apc);
  1946 
  1966 
  1947 	// if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal()
  1967 	/* if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal() */
  1948 	if (apc->helipads[0] > 1) {
  1968 	if (apc->helipads[0] > 1) {
  1949 		const Station* st = GetStation(v->u.air.targetairport);
  1969 		const Station* st = GetStation(v->u.air.targetairport);
  1950 		const AirportFTA* temp = apc->layout[v->u.air.pos].next;
  1970 		const AirportFTA* temp = apc->layout[v->u.air.pos].next;
  1951 
  1971 
  1952 		while (temp != NULL) {
  1972 		while (temp != NULL) {
  1953 			if (temp->heading == 255) {
  1973 			if (temp->heading == 255) {
  1954 				if (!HASBITS(st->airport_flags, temp->block)) {
  1974 				if (!HASBITS(st->airport_flags, temp->block)) {
  1955 
  1975 
  1956 					//read which group do we want to go to?
  1976 					/* read which group do we want to go to?
  1957 					//(the first free group)
  1977 					 * (the first free group) */
  1958 					uint target_group = temp->next_position + 1;
  1978 					uint target_group = temp->next_position + 1;
  1959 
  1979 
  1960 					//at what terminal does the group start?
  1980 					/* at what terminal does the group start?
  1961 					//that means, sum up all terminals of
  1981 					 * that means, sum up all terminals of
  1962 					//groups with lower number
  1982 					 * groups with lower number */
  1963 					uint group_start = 0;
  1983 					uint group_start = 0;
  1964 					for (uint i = 1; i < target_group; i++) {
  1984 					for (uint i = 1; i < target_group; i++) {
  1965 						group_start += apc->helipads[i];
  1985 						group_start += apc->helipads[i];
  1966 					}
  1986 					}
  1967 
  1987 
  1974 				return false;
  1994 				return false;
  1975 			}
  1995 			}
  1976 			temp = temp->next;
  1996 			temp = temp->next;
  1977 		}
  1997 		}
  1978 	} else {
  1998 	} else {
  1979 		// only 1 helicoptergroup, check all helipads
  1999 		/* only 1 helicoptergroup, check all helipads
  1980 		// The blocks for helipads start after the last terminal (MAX_TERMINALS)
  2000 		 * The blocks for helipads start after the last terminal (MAX_TERMINALS) */
  1981 		return FreeTerminal(v, MAX_TERMINALS, GetNumHelipads(apc) + MAX_TERMINALS);
  2001 		return FreeTerminal(v, MAX_TERMINALS, GetNumHelipads(apc) + MAX_TERMINALS);
  1982 	}
  2002 	}
  1983 	return false; // it shouldn't get here anytime, but just to be sure
  2003 	return false; // it shouldn't get here anytime, but just to be sure
  1984 }
  2004 }
  1985 
  2005 
  2026 			break;
  2046 			break;
  2027 	}
  2047 	}
  2028 }
  2048 }
  2029 
  2049 
  2030 
  2050 
  2031 // need to be called to load aircraft from old version
  2051 /** need to be called to load aircraft from old version */
  2032 void UpdateOldAircraft(void)
  2052 void UpdateOldAircraft(void)
  2033 {
  2053 {
  2034 	// set airport_flags to 0 for all airports just to be sure
  2054 	/* set airport_flags to 0 for all airports just to be sure */
  2035 	Station *st;
  2055 	Station *st;
  2036 	FOR_ALL_STATIONS(st) {
  2056 	FOR_ALL_STATIONS(st) {
  2037 		st->airport_flags = 0; // reset airport
  2057 		st->airport_flags = 0; // reset airport
  2038 	}
  2058 	}
  2039 
  2059 
  2040 	Vehicle *v_oldstyle;
  2060 	Vehicle *v_oldstyle;
  2041 	FOR_ALL_VEHICLES(v_oldstyle) {
  2061 	FOR_ALL_VEHICLES(v_oldstyle) {
  2042 	// airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
  2062 	/* airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
  2043 	// skip those
  2063 	 * skip those */
  2044 		if (v_oldstyle->type == VEH_Aircraft && IsNormalAircraft(v_oldstyle)) {
  2064 		if (v_oldstyle->type == VEH_Aircraft && IsNormalAircraft(v_oldstyle)) {
  2045 			// airplane in terminal stopped doesn't hurt anyone, so goto next
  2065 			/* airplane in terminal stopped doesn't hurt anyone, so goto next */
  2046 			if (v_oldstyle->vehstatus & VS_STOPPED && v_oldstyle->u.air.state == 0) {
  2066 			if (v_oldstyle->vehstatus & VS_STOPPED && v_oldstyle->u.air.state == 0) {
  2047 				v_oldstyle->u.air.state = HANGAR;
  2067 				v_oldstyle->u.air.state = HANGAR;
  2048 				continue;
  2068 				continue;
  2049 			}
  2069 			}
  2050 
  2070 
  2054 			AircraftNextAirportPos_and_Order(v_oldstyle); // move it to the entry point of the airport
  2074 			AircraftNextAirportPos_and_Order(v_oldstyle); // move it to the entry point of the airport
  2055 			GetNewVehiclePosResult gp;
  2075 			GetNewVehiclePosResult gp;
  2056 			GetNewVehiclePos(v_oldstyle, &gp); // get the position of the plane (to be used for setting)
  2076 			GetNewVehiclePos(v_oldstyle, &gp); // get the position of the plane (to be used for setting)
  2057 			v_oldstyle->tile = 0; // aircraft in air is tile=0
  2077 			v_oldstyle->tile = 0; // aircraft in air is tile=0
  2058 
  2078 
  2059 			// correct speed of helicopter-rotors
  2079 			/* correct speed of helicopter-rotors */
  2060 			if (v_oldstyle->subtype == AIR_HELICOPTER) v_oldstyle->next->next->cur_speed = 32;
  2080 			if (v_oldstyle->subtype == AIR_HELICOPTER) v_oldstyle->next->next->cur_speed = 32;
  2061 
  2081 
  2062 			// set new position x,y,z
  2082 			/* set new position x,y,z */
  2063 			SetAircraftPosition(v_oldstyle, gp.x, gp.y, GetAircraftFlyingAltitude(v_oldstyle));
  2083 			SetAircraftPosition(v_oldstyle, gp.x, gp.y, GetAircraftFlyingAltitude(v_oldstyle));
  2064 		}
  2084 		}
  2065 	}
  2085 	}
  2066 }
  2086 }
  2067 
  2087 
  2068 void UpdateAirplanesOnNewStation(const Station *st)
  2088 void UpdateAirplanesOnNewStation(const Station *st)
  2069 {
  2089 {
  2070 	// only 1 station is updated per function call, so it is enough to get entry_point once
  2090 	/* only 1 station is updated per function call, so it is enough to get entry_point once */
  2071 	const AirportFTAClass *ap = st->Airport();
  2091 	const AirportFTAClass *ap = st->Airport();
  2072 
  2092 
  2073 	Vehicle *v;
  2093 	Vehicle *v;
  2074 	FOR_ALL_VEHICLES(v) {
  2094 	FOR_ALL_VEHICLES(v) {
  2075 		if (v->type == VEH_Aircraft && IsNormalAircraft(v)) {
  2095 		if (v->type == VEH_Aircraft && IsNormalAircraft(v)) {
  2076 			if (v->u.air.targetairport == st->index) { // if heading to this airport
  2096 			if (v->u.air.targetairport == st->index) { // if heading to this airport
  2077 				/* update position of airplane. If plane is not flying, landing, or taking off
  2097 				/* update position of airplane. If plane is not flying, landing, or taking off
  2078 				 *you cannot delete airport, so it doesn't matter
  2098 				 *you cannot delete airport, so it doesn't matter */
  2079 				 */
       
  2080 				if (v->u.air.state >= FLYING) { // circle around
  2099 				if (v->u.air.state >= FLYING) { // circle around
  2081 					v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap);
  2100 					v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap);
  2082 					v->u.air.state = FLYING;
  2101 					v->u.air.state = FLYING;
  2083 					// landing plane needs to be reset to flying height (only if in pause mode upgrade,
  2102 					/* landing plane needs to be reset to flying height (only if in pause mode upgrade,
  2084 					// in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING
  2103 					 * in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING */
  2085 					GetNewVehiclePosResult gp;
  2104 					GetNewVehiclePosResult gp;
  2086 					GetNewVehiclePos(v, &gp);
  2105 					GetNewVehiclePos(v, &gp);
  2087 					// set new position x,y,z
  2106 					/* set new position x,y,z */
  2088 					SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
  2107 					SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
  2089 				} else {
  2108 				} else {
  2090 					assert(v->u.air.state == ENDTAKEOFF || v->u.air.state == HELITAKEOFF);
  2109 					assert(v->u.air.state == ENDTAKEOFF || v->u.air.state == HELITAKEOFF);
  2091 					byte takeofftype = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : ENDTAKEOFF;
  2110 					byte takeofftype = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : ENDTAKEOFF;
  2092 					// search in airportdata for that heading
  2111 					/* search in airportdata for that heading
  2093 					// easiest to do, since this doesn't happen a lot
  2112 					 * easiest to do, since this doesn't happen a lot */
  2094 					for (uint cnt = 0; cnt < ap->nofelements; cnt++) {
  2113 					for (uint cnt = 0; cnt < ap->nofelements; cnt++) {
  2095 						if (ap->layout[cnt].heading == takeofftype) {
  2114 						if (ap->layout[cnt].heading == takeofftype) {
  2096 							v->u.air.pos = ap->layout[cnt].position;
  2115 							v->u.air.pos = ap->layout[cnt].position;
  2097 							break;
  2116 							break;
  2098 						}
  2117 						}