src/aircraft_cmd.cpp
branchcpp_gui
changeset 6254 abc6ad7c035c
parent 6253 23983700e3d7
child 6268 4b5241e5dd10
equal deleted inserted replaced
6253:23983700e3d7 6254:abc6ad7c035c
    72 	uint best = 0;
    72 	uint best = 0;
    73 	StationID index = INVALID_STATION;
    73 	StationID index = INVALID_STATION;
    74 	TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
    74 	TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
    75 
    75 
    76 	FOR_ALL_STATIONS(st) {
    76 	FOR_ALL_STATIONS(st) {
    77 		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT &&
    77 		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
    78 				GetAirport(st->airport_type)->nof_depots > 0) {
    78 
    79 			uint distance;
    79 		const AirportFTAClass *afc = st->Airport();
    80 
    80 		if (afc->nof_depots == 0 || (
    81 			// don't crash the plane if we know it can't land at the airport
    81 					/* don't crash the plane if we know it can't land at the airport */
    82 			if ((AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
    82 					afc->flags & AirportFTAClass::SHORT_STRIP &&
    83 					(st->airport_type == AT_SMALL || st->airport_type == AT_COMMUTER) &&
    83 					AircraftVehInfo(v->engine_type)->subtype & AIR_FAST &&
    84 					!_cheats.no_jetcrash.value)
    84 					!_cheats.no_jetcrash.value
    85 				continue;
    85 				)) {
    86 
    86 			continue;
    87 			// v->tile can't be used here, when aircraft is flying v->tile is set to 0
    87 		}
    88 			distance = DistanceSquare(vtile, st->airport_tile);
    88 
    89 			if (distance < best || index == INVALID_STATION) {
    89 		// v->tile can't be used here, when aircraft is flying v->tile is set to 0
    90 				best = distance;
    90 		uint distance = DistanceSquare(vtile, st->airport_tile);
    91 				index = st->index;
    91 		if (distance < best || index == INVALID_STATION) {
    92 			}
    92 			best = distance;
       
    93 			index = st->index;
    93 		}
    94 		}
    94 	}
    95 	}
    95 	return index;
    96 	return index;
    96 }
    97 }
    97 
    98 
   103 
   104 
   104 	FOR_VEHICLE_ORDERS(v, order) {
   105 	FOR_VEHICLE_ORDERS(v, order) {
   105 		const Station *st = GetStation(order->station);
   106 		const Station *st = GetStation(order->station);
   106 		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
   107 		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
   107 			// If an airport doesn't have a hangar, skip it
   108 			// If an airport doesn't have a hangar, skip it
   108 			if (GetAirport(st->airport_type)->nof_depots != 0)
   109 			if (st->Airport()->nof_depots != 0)
   109 				return true;
   110 				return true;
   110 		}
   111 		}
   111 	}
   112 	}
   112 
   113 
   113 	return false;
   114 	return false;
   247 
   248 
   248 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   249 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   249 
   250 
   250 	// Prevent building aircraft types at places which can't handle them
   251 	// Prevent building aircraft types at places which can't handle them
   251 	const Station* st = GetStationByTile(tile);
   252 	const Station* st = GetStationByTile(tile);
   252 	const AirportFTAClass* apc = GetAirport(st->airport_type);
   253 	const AirportFTAClass* apc = st->Airport();
   253 	if ((avi->subtype & AIR_CTOL ? HELICOPTERS_ONLY : AIRCRAFT_ONLY) == apc->acc_planes) {
   254 	if (!(apc->flags & (avi->subtype & AIR_CTOL ? AirportFTAClass::AIRPLANES : AirportFTAClass::HELICOPTERS))) {
   254 		return CMD_ERROR;
   255 		return CMD_ERROR;
   255 	}
   256 	}
   256 
   257 
   257 	/* Allocate 2 or 3 vehicle structs, depending on type
   258 	/* Allocate 2 or 3 vehicle structs, depending on type
   258 	 * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */
   259 	 * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */
   556 	} else {
   557 	} else {
   557 		bool next_airport_has_hangar = true;
   558 		bool next_airport_has_hangar = true;
   558 		StationID next_airport_index = v->u.air.targetairport;
   559 		StationID next_airport_index = v->u.air.targetairport;
   559 		const Station *st = GetStation(next_airport_index);
   560 		const Station *st = GetStation(next_airport_index);
   560 		/* If the station is not a valid airport or if it has no hangars */
   561 		/* If the station is not a valid airport or if it has no hangars */
   561 		if (!st->IsValid() || st->airport_tile == 0 || GetAirport(st->airport_type)->nof_depots == 0) {
   562 		if (!st->IsValid() || st->airport_tile == 0 || st->Airport()->nof_depots == 0) {
   562 			StationID station;
   563 			StationID station;
   563 
   564 
   564 			// the aircraft has to search for a hangar on its own
   565 			// the aircraft has to search for a hangar on its own
   565 			station = FindNearestHangar(v);
   566 			station = FindNearestHangar(v);
   566 
   567 
   693 		return;
   694 		return;
   694 	}
   695 	}
   695 
   696 
   696 	st = GetStation(v->current_order.dest);
   697 	st = GetStation(v->current_order.dest);
   697 	// only goto depot if the target airport has terminals (eg. it is airport)
   698 	// only goto depot if the target airport has terminals (eg. it is airport)
   698 	if (st->IsValid() && st->airport_tile != 0 && GetAirport(st->airport_type)->terminals != NULL) {
   699 	if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
   699 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
   700 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
   700 //		v->u.air.targetairport = st->index;
   701 //		v->u.air.targetairport = st->index;
   701 		v->current_order.type = OT_GOTO_DEPOT;
   702 		v->current_order.type = OT_GOTO_DEPOT;
   702 		v->current_order.flags = OF_NON_STOP;
   703 		v->current_order.flags = OF_NON_STOP;
   703 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   704 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   967 		x = TileX(tile) * TILE_SIZE;
   968 		x = TileX(tile) * TILE_SIZE;
   968 		y = TileY(tile) * TILE_SIZE;
   969 		y = TileY(tile) * TILE_SIZE;
   969 	}
   970 	}
   970 
   971 
   971 	// get airport moving data
   972 	// get airport moving data
   972 	const AirportMovingData *amd = GetAirport(st->airport_type)->MovingData(v->u.air.pos);
   973 	const AirportFTAClass *afc = st->Airport();
       
   974 	const AirportMovingData *amd = afc->MovingData(v->u.air.pos);
   973 
   975 
   974 	// Helicopter raise
   976 	// Helicopter raise
   975 	if (amd->flag & AMED_HELI_RAISE) {
   977 	if (amd->flag & AMED_HELI_RAISE) {
   976 		u = v->next->next;
   978 		u = v->next->next;
   977 
   979 
  1009 
  1011 
  1010 			// Vehicle is now at the airport.
  1012 			// Vehicle is now at the airport.
  1011 			v->tile = st->airport_tile;
  1013 			v->tile = st->airport_tile;
  1012 
  1014 
  1013 			// Find altitude of landing position.
  1015 			// Find altitude of landing position.
  1014 			z = GetSlopeZ(x, y) + 1;
  1016 			z = GetSlopeZ(x, y) + 1 + afc->delta_z;
  1015 			if (st->airport_type == AT_OILRIG) z += 54;
       
  1016 			if (st->airport_type == AT_HELIPORT) z += 60;
       
  1017 
  1017 
  1018 			if (z == v->z_pos) {
  1018 			if (z == v->z_pos) {
  1019 				u = v->next->next;
  1019 				u = v->next->next;
  1020 
  1020 
  1021 				// Increase speed of rotors. When speed is 80, we've landed.
  1021 				// Increase speed of rotors. When speed is 80, we've landed.
  1367 
  1367 
  1368 	st = GetStation(v->u.air.targetairport);
  1368 	st = GetStation(v->u.air.targetairport);
  1369 
  1369 
  1370 	//FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports
  1370 	//FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports
  1371 	prob = 0x10000 / 1500;
  1371 	prob = 0x10000 / 1500;
  1372 	if (((st->airport_type == AT_SMALL) || (st->airport_type == AT_COMMUTER)) && (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) {
  1372 	if (st->Airport()->flags & AirportFTAClass::SHORT_STRIP &&
       
  1373 			AircraftVehInfo(v->engine_type)->subtype & AIR_FAST &&
       
  1374 			!_cheats.no_jetcrash.value) {
  1373 		prob = 0x10000 / 20;
  1375 		prob = 0x10000 / 20;
  1374 	}
  1376 	}
  1375 
  1377 
  1376 	if (GB(Random(), 0, 16) > prob) return;
  1378 	if (GB(Random(), 0, 16) > prob) return;
  1377 
  1379 
  1439 		SndPlayVehicleFx(SND_17_SKID_PLANE, v);
  1441 		SndPlayVehicleFx(SND_17_SKID_PLANE, v);
  1440 	}
  1442 	}
  1441 	MaybeCrashAirplane(v);
  1443 	MaybeCrashAirplane(v);
  1442 }
  1444 }
  1443 
  1445 
       
  1446 /**
       
  1447  * Find the entry point to an airport depending on direction which
       
  1448  * the airport is being approached from. Each airport can have up to
       
  1449  * four entry points for its approach system so that approaching
       
  1450  * aircraft do not fly through each other or are forced to do 180
       
  1451  * degree turns during the approach. The arrivals are grouped into
       
  1452  * four sectors dependent on the DiagDirection from which the airport
       
  1453  * is approached.
       
  1454  *
       
  1455  * @param v   The vehicle that is approaching the airport
       
  1456  * @param apc The Airport Class being approached.
       
  1457  * @returns   The index of the entry point
       
  1458  */
       
  1459 static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc)
       
  1460 {
       
  1461 	assert(v != NULL);
       
  1462 	assert(apc != NULL);
       
  1463 
       
  1464 	const Station *st = GetStation(v->u.air.targetairport);
       
  1465 	/* Make sure we don't go to 0,0 if the airport has been removed. */
       
  1466 	TileIndex tile = (st->airport_tile != 0) ? st->airport_tile : st->xy;
       
  1467 
       
  1468 	int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
       
  1469 	int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
       
  1470 
       
  1471 	DiagDirection dir;
       
  1472 	if (abs(delta_y) < abs(delta_x)) {
       
  1473 		/* We are northeast or southwest of the airport */
       
  1474 		dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
       
  1475 	} else {
       
  1476 		/* We are northwest or southeast of the airport */
       
  1477 		dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
       
  1478 	}
       
  1479 	return apc->entry_points[dir];
       
  1480 }
       
  1481 
       
  1482 
  1444 // set the right pos when heading to other airports after takeoff
  1483 // set the right pos when heading to other airports after takeoff
  1445 static void AircraftNextAirportPos_and_Order(Vehicle *v)
  1484 static void AircraftNextAirportPos_and_Order(Vehicle *v)
  1446 {
  1485 {
  1447 	const Station* st;
       
  1448 	const AirportFTAClass *apc;
       
  1449 
       
  1450 	if (v->current_order.type == OT_GOTO_STATION ||
  1486 	if (v->current_order.type == OT_GOTO_STATION ||
  1451 			v->current_order.type == OT_GOTO_DEPOT)
  1487 			v->current_order.type == OT_GOTO_DEPOT)
  1452 		v->u.air.targetairport = v->current_order.dest;
  1488 		v->u.air.targetairport = v->current_order.dest;
  1453 
  1489 
  1454 	st = GetStation(v->u.air.targetairport);
  1490 	const AirportFTAClass *apc = GetStation(v->u.air.targetairport)->Airport();
  1455 	apc = GetAirport(st->airport_type);
  1491 	v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, apc);
  1456 	v->u.air.pos = v->u.air.previous_pos = apc->entry_point;
       
  1457 }
  1492 }
  1458 
  1493 
  1459 static void AircraftLeaveHangar(Vehicle *v)
  1494 static void AircraftLeaveHangar(Vehicle *v)
  1460 {
  1495 {
  1461 	v->cur_speed = 0;
  1496 	v->cur_speed = 0;
  1635 	byte landingtype;
  1670 	byte landingtype;
  1636 	AirportFTA *current;
  1671 	AirportFTA *current;
  1637 	uint16 tcur_speed, tsubspeed;
  1672 	uint16 tcur_speed, tsubspeed;
  1638 
  1673 
  1639 	st = GetStation(v->u.air.targetairport);
  1674 	st = GetStation(v->u.air.targetairport);
  1640 	// flying device is accepted at this station
       
  1641 	// small airport --> no helicopters (AIRCRAFT_ONLY)
       
  1642 	// all other airports --> all types of flying devices (ALL)
       
  1643 	// heliport/oilrig, etc --> no airplanes (HELICOPTERS_ONLY)
       
  1644 	// runway busy or not allowed to use this airstation, circle
  1675 	// runway busy or not allowed to use this airstation, circle
  1645 	if (v->subtype != apc->acc_planes &&
  1676 	if (apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES) &&
  1646 			st->airport_tile != 0 &&
  1677 			st->airport_tile != 0 &&
  1647 			(st->owner == OWNER_NONE || st->owner == v->owner)) {
  1678 			(st->owner == OWNER_NONE || st->owner == v->owner)) {
  1648 		// {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
  1679 		// {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
  1649 		// if it is an airplane, look for LANDING, for helicopter HELILANDING
  1680 		// if it is an airplane, look for LANDING, for helicopter HELILANDING
  1650 		// it is possible to choose from multiple landing runways, so loop until a free one is found
  1681 		// it is possible to choose from multiple landing runways, so loop until a free one is found
  1821 			return false;
  1852 			return false;
  1822 		}
  1853 		}
  1823 		current = current->next;
  1854 		current = current->next;
  1824 	} while (current != NULL);
  1855 	} while (current != NULL);
  1825 
  1856 
  1826 	DEBUG(misc, 0, "[Ap] cannot move further on Airport! (pos %d state %d)", v->u.air.pos, v->u.air.state);
  1857 	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);
  1827 	DEBUG(misc, 0, "[Ap] airport entry point: %d, Vehicle: %d", apc->entry_point, v->index);
       
  1828 	assert(0);
  1858 	assert(0);
  1829 	return false;
  1859 	return false;
  1830 }
  1860 }
  1831 
  1861 
  1832 // returns true if the road ahead is busy, eg. you must wait before proceeding
  1862 // returns true if the road ahead is busy, eg. you must wait before proceeding
  1836 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1866 	const AirportFTA *next = &apc->layout[current_pos->next_position];
  1837 
  1867 
  1838 	// same block, then of course we can move
  1868 	// same block, then of course we can move
  1839 	if (apc->layout[current_pos->position].block != next->block) {
  1869 	if (apc->layout[current_pos->position].block != next->block) {
  1840 		const Station *st = GetStation(v->u.air.targetairport);
  1870 		const Station *st = GetStation(v->u.air.targetairport);
  1841 		uint32 airport_flags = next->block;
  1871 		uint64 airport_flags = next->block;
  1842 
  1872 
  1843 		// check additional possible extra blocks
  1873 		// check additional possible extra blocks
  1844 		if (current_pos != reference && current_pos->block != NOTHING_block) {
  1874 		if (current_pos != reference && current_pos->block != NOTHING_block) {
  1845 			airport_flags |= current_pos->block;
  1875 			airport_flags |= current_pos->block;
  1846 		}
  1876 		}
  1860 	AirportFTA *next = &apc->layout[current_pos->next_position];
  1890 	AirportFTA *next = &apc->layout[current_pos->next_position];
  1861 	AirportFTA *reference = &apc->layout[v->u.air.pos];
  1891 	AirportFTA *reference = &apc->layout[v->u.air.pos];
  1862 
  1892 
  1863 	// if the next position is in another block, check it and wait until it is free
  1893 	// if the next position is in another block, check it and wait until it is free
  1864 	if ((apc->layout[current_pos->position].block & next->block) != next->block) {
  1894 	if ((apc->layout[current_pos->position].block & next->block) != next->block) {
  1865 		uint32 airport_flags = next->block;
  1895 		uint64 airport_flags = next->block;
  1866 		Station* st = GetStation(v->u.air.targetairport);
  1896 		Station* st = GetStation(v->u.air.targetairport);
  1867 		//search for all all elements in the list with the same state, and blocks != N
  1897 		//search for all all elements in the list with the same state, and blocks != N
  1868 		// this means more blocks should be checked/set
  1898 		// this means more blocks should be checked/set
  1869 			AirportFTA *current = current_pos;
  1899 			AirportFTA *current = current_pos;
  1870 		if (current == reference) current = current->next;
  1900 		if (current == reference) current = current->next;
  2048 	ProcessAircraftOrder(v);
  2078 	ProcessAircraftOrder(v);
  2049 	HandleAircraftLoading(v, loop);
  2079 	HandleAircraftLoading(v, loop);
  2050 
  2080 
  2051 	if (v->current_order.type >= OT_LOADING) return;
  2081 	if (v->current_order.type >= OT_LOADING) return;
  2052 
  2082 
  2053 	// pass the right airport structure to the functions
  2083 	AirportGoToNextPosition(v, GetStation(v->u.air.targetairport)->Airport());
  2054 	// DEREF_STATION gets target airport (Station *st), its type is passed to GetAirport
       
  2055 	// that returns the correct layout depending on type
       
  2056 	AirportGoToNextPosition(v, GetAirport(GetStation(v->u.air.targetairport)->airport_type));
       
  2057 }
  2084 }
  2058 
  2085 
  2059 void Aircraft_Tick(Vehicle *v)
  2086 void Aircraft_Tick(Vehicle *v)
  2060 {
  2087 {
  2061 	int i;
  2088 	int i;
  2117 	GetNewVehiclePosResult gp;
  2144 	GetNewVehiclePosResult gp;
  2118 	Vehicle *v;
  2145 	Vehicle *v;
  2119 	byte takeofftype;
  2146 	byte takeofftype;
  2120 	uint16 cnt;
  2147 	uint16 cnt;
  2121 	// only 1 station is updated per function call, so it is enough to get entry_point once
  2148 	// only 1 station is updated per function call, so it is enough to get entry_point once
  2122 	const AirportFTAClass *ap = GetAirport(st->airport_type);
  2149 	const AirportFTAClass *ap = st->Airport();
  2123 	FOR_ALL_VEHICLES(v) {
  2150 	FOR_ALL_VEHICLES(v) {
  2124 		if (v->type == VEH_Aircraft && IsNormalAircraft(v)) {
  2151 		if (v->type == VEH_Aircraft && IsNormalAircraft(v)) {
  2125 			if (v->u.air.targetairport == st->index) { // if heading to this airport
  2152 			if (v->u.air.targetairport == st->index) { // if heading to this airport
  2126 				/* update position of airplane. If plane is not flying, landing, or taking off
  2153 				/* update position of airplane. If plane is not flying, landing, or taking off
  2127 				 *you cannot delete airport, so it doesn't matter
  2154 				 *you cannot delete airport, so it doesn't matter
  2128 				 */
  2155 				 */
  2129 				if (v->u.air.state >= FLYING) { // circle around
  2156 				if (v->u.air.state >= FLYING) { // circle around
  2130 					v->u.air.pos = v->u.air.previous_pos = ap->entry_point;
  2157 					v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap);
  2131 					v->u.air.state = FLYING;
  2158 					v->u.air.state = FLYING;
  2132 					// landing plane needs to be reset to flying height (only if in pause mode upgrade,
  2159 					// landing plane needs to be reset to flying height (only if in pause mode upgrade,
  2133 					// in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING
  2160 					// in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING
  2134 					GetNewVehiclePos(v, &gp);
  2161 					GetNewVehiclePos(v, &gp);
  2135 					// set new position x,y,z
  2162 					// set new position x,y,z