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 */ |
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; |