src/aircraft_cmd.cpp
changeset 10154 5ae6e5fe6c71
parent 10125 8f12703df400
child 10177 41ce7529a331
equal deleted inserted replaced
10153:4d982a782aa8 10154:5ae6e5fe6c71
   496 	return ret;
   496 	return ret;
   497 }
   497 }
   498 
   498 
   499 bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
   499 bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
   500 {
   500 {
   501 	const Station *st = GetStation(this->u.air.targetairport);
   501 	const Station *st = GetTargetAirportIfValid(this);
   502 	/* If the station is not a valid airport or if it has no hangars */
   502 	/* If the station is not a valid airport or if it has no hangars */
   503 	if (!st->IsValid() || st->airport_tile == 0 || st->Airport()->nof_depots == 0) {
   503 	if (st == NULL || st->Airport()->nof_depots == 0) {
   504 		/* the aircraft has to search for a hangar on its own */
   504 		/* the aircraft has to search for a hangar on its own */
   505 		StationID station = FindNearestHangar(this);
   505 		StationID station = FindNearestHangar(this);
   506 
   506 
   507 		if (station == INVALID_STATION) return false;
   507 		if (station == INVALID_STATION) return false;
   508 
   508 
   935 static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc)
   935 static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc)
   936 {
   936 {
   937 	assert(v != NULL);
   937 	assert(v != NULL);
   938 	assert(apc != NULL);
   938 	assert(apc != NULL);
   939 
   939 
   940 	const Station *st = GetStation(v->u.air.targetairport);
   940 	/* In the case the station doesn't exit anymore, set target tile 0.
   941 	/* Make sure we don't go to 0,0 if the airport has been removed. */
   941 	 * It doesn't hurt much, aircraft will go to next order, nearest hangar
   942 	TileIndex tile = (st->airport_tile != 0) ? st->airport_tile : st->xy;
   942 	 * or it will simply crash in next tick */
       
   943 	TileIndex tile = 0;
       
   944 
       
   945 	if (IsValidStationID(v->u.air.targetairport)) {
       
   946 		const Station *st = GetStation(v->u.air.targetairport);
       
   947 		/* Make sure we don't go to 0,0 if the airport has been removed. */
       
   948 		tile = (st->airport_tile != 0) ? st->airport_tile : st->xy;
       
   949 	}
   943 
   950 
   944 	int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
   951 	int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
   945 	int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
   952 	int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
   946 
   953 
   947 	DiagDirection dir;
   954 	DiagDirection dir;
   963  * @return  Whether the position requested by the State Machine has been reached
   970  * @return  Whether the position requested by the State Machine has been reached
   964  */
   971  */
   965 static bool AircraftController(Vehicle *v)
   972 static bool AircraftController(Vehicle *v)
   966 {
   973 {
   967 	int count;
   974 	int count;
   968 	const Station *st = GetStation(v->u.air.targetairport);
   975 
   969 	const AirportFTAClass *afc = st->Airport();
   976 	StationID target = v->u.air.targetairport;
   970 	const AirportMovingData *amd;
   977 
       
   978 	/* NULL if station is invalid */
       
   979 	const Station *st = IsValidStationID(target) ? GetStation(target) : NULL;
       
   980 	/* 0 if there is no station */
       
   981 	TileIndex tile = 0;
       
   982 	if (st != NULL) {
       
   983 		tile = st->airport_tile;
       
   984 		if (tile == 0) tile = st->xy;
       
   985 	}
       
   986 	/* DUMMY if there is no station or no airport */
       
   987 	const AirportFTAClass *afc = tile == 0 ? GetAirport(AT_DUMMY) : st->Airport();
   971 
   988 
   972 	/* prevent going to 0,0 if airport is deleted. */
   989 	/* prevent going to 0,0 if airport is deleted. */
   973 	TileIndex tile = st->airport_tile;
   990 	if (st == NULL || st->airport_tile == 0) {
   974 	if (tile == 0) {
       
   975 		tile = st->xy;
       
   976 
       
   977 		/* Jump into our "holding pattern" state machine if possible */
   991 		/* Jump into our "holding pattern" state machine if possible */
   978 		if (v->u.air.pos >= afc->nofelements) {
   992 		if (v->u.air.pos >= afc->nofelements) {
   979 			v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, afc);
   993 			v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, afc);
   980 		} else if (v->u.air.targetairport != v->current_order.GetDestination()) {
   994 		} else if (v->u.air.targetairport != v->current_order.GetDestination()) {
   981 			/* If not possible, just get out of here fast */
   995 			/* If not possible, just get out of here fast */
   987 			return false;
  1001 			return false;
   988 		}
  1002 		}
   989 	}
  1003 	}
   990 
  1004 
   991 	/*  get airport moving data */
  1005 	/*  get airport moving data */
   992 	amd = afc->MovingData(v->u.air.pos);
  1006 	const AirportMovingData *amd = afc->MovingData(v->u.air.pos);
   993 
  1007 
   994 	int x = TileX(tile) * TILE_SIZE;
  1008 	int x = TileX(tile) * TILE_SIZE;
   995 	int y = TileY(tile) * TILE_SIZE;
  1009 	int y = TileY(tile) * TILE_SIZE;
   996 
  1010 
   997 	/* Helicopter raise */
  1011 	/* Helicopter raise */
  1019 		return false;
  1033 		return false;
  1020 	}
  1034 	}
  1021 
  1035 
  1022 	/* Helicopter landing. */
  1036 	/* Helicopter landing. */
  1023 	if (amd->flag & AMED_HELI_LOWER) {
  1037 	if (amd->flag & AMED_HELI_LOWER) {
  1024 		if (st->airport_tile == 0) {
  1038 		if (st == NULL) {
  1025 			/* FIXME - AircraftController -> if station no longer exists, do not land
  1039 			/* FIXME - AircraftController -> if station no longer exists, do not land
  1026 			 * helicopter will circle until sign disappears, then go to next order
  1040 			 * helicopter will circle until sign disappears, then go to next order
  1027 			 * what to do when it is the only order left, right now it just stays in 1 place */
  1041 			 * what to do when it is the only order left, right now it just stays in 1 place */
  1028 			v->u.air.state = FLYING;
  1042 			v->u.air.state = FLYING;
  1029 			UpdateAircraftCache(v);
  1043 			UpdateAircraftCache(v);
  1030 			AircraftNextAirportPos_and_Order(v);
  1044 			AircraftNextAirportPos_and_Order(v);
  1031 			return false;
  1045 			return false;
  1032 		}
  1046 		}
  1033 
  1047 
  1034 		/* Vehicle is now at the airport. */
  1048 		/* Vehicle is now at the airport. */
  1035 		v->tile = st->airport_tile;
  1049 		v->tile = tile;
  1036 
  1050 
  1037 		/* Find altitude of landing position. */
  1051 		/* Find altitude of landing position. */
  1038 		int z = GetSlopeZ(x, y) + 1 + afc->delta_z;
  1052 		int z = GetSlopeZ(x, y) + 1 + afc->delta_z;
  1039 
  1053 
  1040 		if (z == v->z_pos) {
  1054 		if (z == v->z_pos) {
  1184 
  1198 
  1185 static void HandleCrashedAircraft(Vehicle *v)
  1199 static void HandleCrashedAircraft(Vehicle *v)
  1186 {
  1200 {
  1187 	v->u.air.crashed_counter++;
  1201 	v->u.air.crashed_counter++;
  1188 
  1202 
  1189 	Station *st = GetStation(v->u.air.targetairport);
  1203 	Station *st = GetTargetAirportIfValid(v);
  1190 
  1204 
  1191 	/* make aircraft crash down to the ground */
  1205 	/* make aircraft crash down to the ground */
  1192 	if (v->u.air.crashed_counter < 500 && st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) {
  1206 	if (v->u.air.crashed_counter < 500 && st == NULL && ((v->u.air.crashed_counter % 3) == 0) ) {
  1193 		uint z = GetSlopeZ(v->x_pos, v->y_pos);
  1207 		uint z = GetSlopeZ(v->x_pos, v->y_pos);
  1194 		v->z_pos -= 1;
  1208 		v->z_pos -= 1;
  1195 		if (v->z_pos == z) {
  1209 		if (v->z_pos == z) {
  1196 			v->u.air.crashed_counter = 500;
  1210 			v->u.air.crashed_counter = 500;
  1197 			v->z_pos++;
  1211 			v->z_pos++;
  1218 		/*  remove rubble of crashed airplane */
  1232 		/*  remove rubble of crashed airplane */
  1219 
  1233 
  1220 		/* clear runway-in on all airports, set by crashing plane
  1234 		/* clear runway-in on all airports, set by crashing plane
  1221 		 * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
  1235 		 * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
  1222 		 * but they all share the same number */
  1236 		 * but they all share the same number */
  1223 		CLRBITS(st->airport_flags, RUNWAY_IN_block);
  1237 		if (st != NULL) {
  1224 		CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport
  1238 			CLRBITS(st->airport_flags, RUNWAY_IN_block);
  1225 		CLRBITS(st->airport_flags, RUNWAY_IN2_block);    // intercontinental
  1239 			CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport
       
  1240 			CLRBITS(st->airport_flags, RUNWAY_IN2_block);    // intercontinental
       
  1241 		}
  1226 
  1242 
  1227 		MarkSingleVehicleDirty(v);
  1243 		MarkSingleVehicleDirty(v);
  1228 
  1244 
  1229 		DoDeleteAircraft(v);
  1245 		DoDeleteAircraft(v);
  1230 	}
  1246 	}
  1293 	 *    changing the aircraft's orders while in-flight or in for
  1309 	 *    changing the aircraft's orders while in-flight or in for
  1294 	 *    example a depot. However, when we have a current order to
  1310 	 *    example a depot. However, when we have a current order to
  1295 	 *    go to a depot, we have to keep that order so the aircraft
  1311 	 *    go to a depot, we have to keep that order so the aircraft
  1296 	 *    actually stops.
  1312 	 *    actually stops.
  1297 	 */
  1313 	 */
  1298 	const Station *st = GetStation(v->u.air.targetairport);
  1314 	const Station *st = GetTargetAirportIfValid(v);
  1299 	if (!st->IsValid() || st->airport_tile == 0) {
  1315 	if (st == NULL) {
  1300 		CommandCost ret;
  1316 		CommandCost ret;
  1301 		PlayerID old_player = _current_player;
  1317 		PlayerID old_player = _current_player;
  1302 
  1318 
  1303 		_current_player = v->owner;
  1319 		_current_player = v->owner;
  1304 		ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1320 		ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
  1342 	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo.Count();
  1358 	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo.Count();
  1343 	SetDParam(0, amt);
  1359 	SetDParam(0, amt);
  1344 
  1360 
  1345 	v->cargo.Truncate(0);
  1361 	v->cargo.Truncate(0);
  1346 	v->Next()->cargo.Truncate(0);
  1362 	v->Next()->cargo.Truncate(0);
  1347 	const Station *st = GetStation(v->u.air.targetairport);
  1363 	const Station *st = GetTargetAirportIfValid(v);
  1348 	StringID newsitem;
  1364 	StringID newsitem;
  1349 	if (st->airport_tile == 0) {
  1365 	if (st == NULL) {
  1350 		newsitem = STR_PLANE_CRASH_OUT_OF_FUEL;
  1366 		newsitem = STR_PLANE_CRASH_OUT_OF_FUEL;
  1351 	} else {
  1367 	} else {
  1352 		SetDParam(1, st->index);
  1368 		SetDParam(1, st->index);
  1353 		newsitem = STR_A034_PLANE_CRASH_DIE_IN_FIREBALL;
  1369 		newsitem = STR_A034_PLANE_CRASH_DIE_IN_FIREBALL;
  1354 	}
  1370 	}
  1355 
  1371 
  1356 	SetDParam(1, st->index);
       
  1357 	AddNewsItem(newsitem,
  1372 	AddNewsItem(newsitem,
  1358 		NS_ACCIDENT_VEHICLE,
  1373 		NS_ACCIDENT_VEHICLE,
  1359 		v->index,
  1374 		v->index,
  1360 		0);
  1375 		0);
  1361 
  1376 
  1421 
  1436 
  1422 
  1437 
  1423 /** set the right pos when heading to other airports after takeoff */
  1438 /** set the right pos when heading to other airports after takeoff */
  1424 void AircraftNextAirportPos_and_Order(Vehicle *v)
  1439 void AircraftNextAirportPos_and_Order(Vehicle *v)
  1425 {
  1440 {
  1426 	if (v->current_order.IsType(OT_GOTO_STATION) ||
  1441 	if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) {
  1427 			v->current_order.IsType(OT_GOTO_DEPOT))
       
  1428 		v->u.air.targetairport = v->current_order.GetDestination();
  1442 		v->u.air.targetairport = v->current_order.GetDestination();
  1429 
  1443 	}
  1430 	const AirportFTAClass *apc = GetStation(v->u.air.targetairport)->Airport();
  1444 
       
  1445 	const Station *st = GetTargetAirportIfValid(v);
       
  1446 	const AirportFTAClass *apc = st == NULL ? GetAirport(AT_DUMMY) : st->Airport();
  1431 	v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, apc);
  1447 	v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, apc);
  1432 }
  1448 }
  1433 
  1449 
  1434 static void AircraftLeaveHangar(Vehicle *v)
  1450 static void AircraftLeaveHangar(Vehicle *v)
  1435 {
  1451 {
  2074 			break;
  2090 			break;
  2075 	}
  2091 	}
  2076 }
  2092 }
  2077 
  2093 
  2078 
  2094 
       
  2095 /** Returns aircraft's target station if v->u.air.target_airport
       
  2096  * is a valid station with airport.
       
  2097  * @param v vehicle to get target airport for
       
  2098  * @return pointer to target station, NULL if invalid
       
  2099  */
       
  2100 Station *GetTargetAirportIfValid(const Vehicle *v)
       
  2101 {
       
  2102 	assert(v->type == VEH_AIRCRAFT);
       
  2103 
       
  2104 	StationID sid = v->u.air.targetairport;
       
  2105 
       
  2106 	if (!IsValidStationID(sid)) return NULL;
       
  2107 
       
  2108 	Station *st = GetStation(sid);
       
  2109 
       
  2110 	return st->airport_tile == 0 ? NULL : st;
       
  2111 }
       
  2112 
  2079 /** need to be called to load aircraft from old version */
  2113 /** need to be called to load aircraft from old version */
  2080 void UpdateOldAircraft()
  2114 void UpdateOldAircraft()
  2081 {
  2115 {
  2082 	/* set airport_flags to 0 for all airports just to be sure */
  2116 	/* set airport_flags to 0 for all airports just to be sure */
  2083 	Station *st;
  2117 	Station *st;