31 #include "newgrf_sound.h" |
31 #include "newgrf_sound.h" |
32 #include "date.h" |
32 #include "date.h" |
33 #include "spritecache.h" |
33 #include "spritecache.h" |
34 #include "cargotype.h" |
34 #include "cargotype.h" |
35 |
35 |
|
36 void Aircraft::UpdateDeltaXY(Direction direction) |
|
37 { |
|
38 uint32 x; |
|
39 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
|
40 switch (this->subtype) { |
|
41 default: NOT_REACHED(); |
|
42 case AIR_AIRCRAFT: |
|
43 case AIR_HELICOPTER: |
|
44 switch (this->u.air.state) { |
|
45 case ENDTAKEOFF: |
|
46 case LANDING: |
|
47 case HELILANDING: |
|
48 case FLYING: x = MKIT(24, 24, -1, -1); break; |
|
49 default: x = MKIT( 2, 2, -1, -1); break; |
|
50 } |
|
51 this->z_height = 5; |
|
52 break; |
|
53 case AIR_SHADOW: this->z_height = 1; x = MKIT(2, 2, 0, 0); break; |
|
54 case AIR_ROTOR: this->z_height = 1; x = MKIT(2, 2, -1, -1); break; |
|
55 } |
|
56 #undef MKIT |
|
57 |
|
58 this->x_offs = GB(x, 0, 8); |
|
59 this->y_offs = GB(x, 8, 8); |
|
60 this->sprite_width = GB(x, 16, 8); |
|
61 this->sprite_height = GB(x, 24, 8); |
|
62 } |
|
63 |
|
64 |
36 /** this maps the terminal to its corresponding state and block flag |
65 /** this maps the terminal to its corresponding state and block flag |
37 * currently set for 10 terms, 4 helipads */ |
66 * currently set for 10 terms, 4 helipads */ |
38 static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22}; |
67 static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22}; |
39 static const byte _airport_terminal_flag[] = {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25}; |
68 static const byte _airport_terminal_flag[] = {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25}; |
40 |
69 |
239 int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
268 int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
240 { |
269 { |
241 if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_player)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE); |
270 if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_player)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE); |
242 |
271 |
243 const AircraftVehicleInfo *avi = AircraftVehInfo(p1); |
272 const AircraftVehicleInfo *avi = AircraftVehInfo(p1); |
244 int32 value = EstimateAircraftCost(avi); |
273 int32 value = EstimateAircraftCost(p1, avi); |
245 |
274 |
246 /* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */ |
275 /* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */ |
247 if (flags & DC_QUERY_COST) return value; |
276 if (flags & DC_QUERY_COST) return value; |
248 |
277 |
249 if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR; |
278 if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR; |
267 if (flags & DC_EXEC) { |
296 if (flags & DC_EXEC) { |
268 Vehicle *v = vl[0]; // aircraft |
297 Vehicle *v = vl[0]; // aircraft |
269 Vehicle *u = vl[1]; // shadow |
298 Vehicle *u = vl[1]; // shadow |
270 |
299 |
271 v->unitnumber = unit_num; |
300 v->unitnumber = unit_num; |
272 v->type = u->type = VEH_AIRCRAFT; |
301 v = new (v) Aircraft(); |
|
302 u = new (u) Aircraft(); |
273 v->direction = DIR_SE; |
303 v->direction = DIR_SE; |
274 |
304 |
275 v->owner = u->owner = _current_player; |
305 v->owner = u->owner = _current_player; |
276 |
306 |
277 v->tile = tile; |
307 v->tile = tile; |
284 v->y_pos = u->y_pos = y; |
314 v->y_pos = u->y_pos = y; |
285 |
315 |
286 u->z_pos = GetSlopeZ(x, y); |
316 u->z_pos = GetSlopeZ(x, y); |
287 v->z_pos = u->z_pos + 1; |
317 v->z_pos = u->z_pos + 1; |
288 |
318 |
289 v->x_offs = v->y_offs = -1; |
|
290 // u->delta_x = u->delta_y = 0; |
319 // u->delta_x = u->delta_y = 0; |
291 |
|
292 v->sprite_width = v->sprite_height = 2; |
|
293 v->z_height = 5; |
|
294 |
|
295 u->sprite_width = u->sprite_height = 2; |
|
296 u->z_height = 1; |
|
297 |
320 |
298 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
321 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
299 u->vehstatus = VS_HIDDEN | VS_UNCLICKABLE | VS_SHADOW; |
322 u->vehstatus = VS_HIDDEN | VS_UNCLICKABLE | VS_SHADOW; |
300 |
323 |
301 v->spritenum = avi->image_index; |
324 v->spritenum = avi->image_index; |
320 v->max_speed = avi->max_speed; |
343 v->max_speed = avi->max_speed; |
321 v->acceleration = avi->acceleration; |
344 v->acceleration = avi->acceleration; |
322 v->engine_type = p1; |
345 v->engine_type = p1; |
323 |
346 |
324 v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER); |
347 v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER); |
|
348 v->UpdateDeltaXY(INVALID_DIR); |
325 v->value = value; |
349 v->value = value; |
326 |
350 |
327 u->subtype = AIR_SHADOW; |
351 u->subtype = AIR_SHADOW; |
|
352 u->UpdateDeltaXY(INVALID_DIR); |
328 |
353 |
329 /* Danger, Will Robinson! |
354 /* Danger, Will Robinson! |
330 * If the aircraft is refittable, but cannot be refitted to |
355 * If the aircraft is refittable, but cannot be refitted to |
331 * passengers, we select the cargo type from the refit mask. |
356 * passengers, we select the cargo type from the refit mask. |
332 * This is a fairly nasty hack to get around the fact that TTD |
357 * This is a fairly nasty hack to get around the fact that TTD |
402 if (v->subtype == AIR_HELICOPTER) { |
427 if (v->subtype == AIR_HELICOPTER) { |
403 Vehicle *w = vl[2]; |
428 Vehicle *w = vl[2]; |
404 |
429 |
405 u->next = w; |
430 u->next = w; |
406 |
431 |
407 w->type = VEH_AIRCRAFT; |
432 w = new (w) Aircraft(); |
408 w->direction = DIR_N; |
433 w->direction = DIR_N; |
409 w->owner = _current_player; |
434 w->owner = _current_player; |
410 w->x_pos = v->x_pos; |
435 w->x_pos = v->x_pos; |
411 w->y_pos = v->y_pos; |
436 w->y_pos = v->y_pos; |
412 w->z_pos = v->z_pos + 5; |
437 w->z_pos = v->z_pos + 5; |
413 w->x_offs = w->y_offs = -1; |
|
414 w->sprite_width = w->sprite_height = 2; |
|
415 w->z_height = 1; |
|
416 w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE; |
438 w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE; |
417 w->spritenum = 0xFF; |
439 w->spritenum = 0xFF; |
418 w->subtype = AIR_ROTOR; |
440 w->subtype = AIR_ROTOR; |
419 w->cur_image = SPR_ROTOR_STOPPED; |
441 w->cur_image = SPR_ROTOR_STOPPED; |
420 w->random_bits = VehicleRandomBits(); |
442 w->random_bits = VehicleRandomBits(); |
421 /* Use rotor's air.state to store the rotor animation frame */ |
443 /* Use rotor's air.state to store the rotor animation frame */ |
422 w->u.air.state = HRS_ROTOR_STOPPED; |
444 w->u.air.state = HRS_ROTOR_STOPPED; |
|
445 w->UpdateDeltaXY(INVALID_DIR); |
423 VehiclePositionChanged(w); |
446 VehiclePositionChanged(w); |
424 } |
447 } |
425 |
448 |
426 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
449 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
427 RebuildVehicleLists(); |
450 RebuildVehicleLists(); |
595 * @param flags for command type |
618 * @param flags for command type |
596 * @param p1 vehicle ID of the aircraft to refit |
619 * @param p1 vehicle ID of the aircraft to refit |
597 * @param p2 various bitstuffed elements |
620 * @param p2 various bitstuffed elements |
598 * - p2 = (bit 0-7) - the new cargo type to refit to |
621 * - p2 = (bit 0-7) - the new cargo type to refit to |
599 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
622 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
|
623 * - p2 = (bit 16) - refit only this vehicle (ignored) |
600 * @return cost of refit or error |
624 * @return cost of refit or error |
601 */ |
625 */ |
602 int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
626 int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
603 { |
627 { |
604 byte new_subtype = GB(p2, 8, 8); |
628 byte new_subtype = GB(p2, 8, 8); |
693 const Station *st = GetStation(v->current_order.dest); |
717 const Station *st = GetStation(v->current_order.dest); |
694 /* only goto depot if the target airport has terminals (eg. it is airport) */ |
718 /* only goto depot if the target airport has terminals (eg. it is airport) */ |
695 if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) { |
719 if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) { |
696 // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); |
720 // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); |
697 // v->u.air.targetairport = st->index; |
721 // v->u.air.targetairport = st->index; |
|
722 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
698 v->current_order.type = OT_GOTO_DEPOT; |
723 v->current_order.type = OT_GOTO_DEPOT; |
699 v->current_order.flags = OF_NON_STOP; |
724 v->current_order.flags = OF_NON_STOP; |
700 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
725 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
701 } else if (v->current_order.type == OT_GOTO_DEPOT) { |
726 } else if (v->current_order.type == OT_GOTO_DEPOT) { |
702 v->current_order.type = OT_DUMMY; |
727 v->current_order.type = OT_DUMMY; |
1066 if (st->airport_tile == 0) { |
1091 if (st->airport_tile == 0) { |
1067 /* FIXME - AircraftController -> if station no longer exists, do not land |
1092 /* FIXME - AircraftController -> if station no longer exists, do not land |
1068 * helicopter will circle until sign disappears, then go to next order |
1093 * helicopter will circle until sign disappears, then go to next order |
1069 * what to do when it is the only order left, right now it just stays in 1 place */ |
1094 * what to do when it is the only order left, right now it just stays in 1 place */ |
1070 v->u.air.state = FLYING; |
1095 v->u.air.state = FLYING; |
|
1096 UpdateAircraftCache(v); |
1071 AircraftNextAirportPos_and_Order(v); |
1097 AircraftNextAirportPos_and_Order(v); |
1072 return false; |
1098 return false; |
1073 } |
1099 } |
1074 |
1100 |
1075 /* Vehicle is now at the airport. */ |
1101 /* Vehicle is now at the airport. */ |
1180 |
1206 |
1181 if (amd->flag & AMED_LAND) { |
1207 if (amd->flag & AMED_LAND) { |
1182 if (st->airport_tile == 0) { |
1208 if (st->airport_tile == 0) { |
1183 /* Airport has been removed, abort the landing procedure */ |
1209 /* Airport has been removed, abort the landing procedure */ |
1184 v->u.air.state = FLYING; |
1210 v->u.air.state = FLYING; |
|
1211 UpdateAircraftCache(v); |
1185 AircraftNextAirportPos_and_Order(v); |
1212 AircraftNextAirportPos_and_Order(v); |
1186 /* get aircraft back on running altitude */ |
1213 /* get aircraft back on running altitude */ |
1187 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); |
1214 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); |
1188 continue; |
1215 continue; |
1189 } |
1216 } |
1382 InvalidateVehicleOrder(v); |
1409 InvalidateVehicleOrder(v); |
1383 |
1410 |
1384 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
1411 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
1385 } |
1412 } |
1386 |
1413 |
1387 /** Mark all views dirty for an aircraft. |
1414 void Aircraft::MarkDirty() |
1388 * @param v vehicle to be redrawn. |
1415 { |
1389 */ |
1416 this->cur_image = GetAircraftImage(this, this->direction); |
1390 static void MarkAircraftDirty(Vehicle *v) |
1417 if (this->subtype == AIR_HELICOPTER) this->next->next->cur_image = GetRotorImage(this); |
1391 { |
1418 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
1392 v->cur_image = GetAircraftImage(v, v->direction); |
|
1393 if (v->subtype == AIR_HELICOPTER) v->next->next->cur_image = GetRotorImage(v); |
|
1394 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
|
1395 } |
|
1396 |
|
1397 static void HandleAircraftLoading(Vehicle *v, int mode) |
|
1398 { |
|
1399 switch (v->current_order.type) { |
|
1400 case OT_LOADING: { |
|
1401 if (mode != 0) return; |
|
1402 if (--v->load_unload_time_rem != 0) return; |
|
1403 |
|
1404 if (CanFillVehicle(v) && ( |
|
1405 v->current_order.flags & OF_FULL_LOAD || |
|
1406 (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) |
|
1407 )) { |
|
1408 SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); |
|
1409 if (LoadUnloadVehicle(v, false)) { |
|
1410 InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); |
|
1411 MarkAircraftDirty(v); |
|
1412 } |
|
1413 return; |
|
1414 } |
|
1415 |
|
1416 Order b = v->current_order; |
|
1417 v->LeaveStation(); |
|
1418 v->current_order.Free(); |
|
1419 MarkAircraftDirty(v); |
|
1420 if (!(b.flags & OF_NON_STOP)) return; |
|
1421 break; |
|
1422 } |
|
1423 |
|
1424 case OT_DUMMY: break; |
|
1425 |
|
1426 default: return; |
|
1427 } |
|
1428 |
|
1429 v->cur_order_index++; |
|
1430 InvalidateVehicleOrder(v); |
|
1431 } |
1419 } |
1432 |
1420 |
1433 static void CrashAirplane(Vehicle *v) |
1421 static void CrashAirplane(Vehicle *v) |
1434 { |
1422 { |
1435 v->vehstatus |= VS_CRASHED; |
1423 v->vehstatus |= VS_CRASHED; |
1507 flags, |
1495 flags, |
1508 v->index, |
1496 v->index, |
1509 0); |
1497 0); |
1510 } |
1498 } |
1511 |
1499 |
1512 Order old_order = v->current_order; |
|
1513 v->BeginLoading(); |
1500 v->BeginLoading(); |
1514 v->current_order.flags = 0; |
|
1515 |
|
1516 if (old_order.type == OT_GOTO_STATION && |
|
1517 v->current_order.dest == v->last_station_visited) { |
|
1518 v->current_order.flags = |
|
1519 (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER)) | OF_NON_STOP; |
|
1520 } |
|
1521 |
|
1522 SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC); |
|
1523 LoadUnloadVehicle(v, true); |
|
1524 MarkAircraftDirty(v); |
|
1525 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
|
1526 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
|
1527 } |
|
1528 |
|
1529 static void AircraftLand(Vehicle *v) |
|
1530 { |
|
1531 v->sprite_width = v->sprite_height = 2; |
|
1532 } |
1501 } |
1533 |
1502 |
1534 static void AircraftLandAirplane(Vehicle *v) |
1503 static void AircraftLandAirplane(Vehicle *v) |
1535 { |
1504 { |
1536 AircraftLand(v); |
1505 v->UpdateDeltaXY(INVALID_DIR); |
|
1506 |
1537 if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) { |
1507 if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) { |
1538 SndPlayVehicleFx(SND_17_SKID_PLANE, v); |
1508 SndPlayVehicleFx(SND_17_SKID_PLANE, v); |
1539 } |
1509 } |
1540 MaybeCrashAirplane(v); |
1510 MaybeCrashAirplane(v); |
1541 } |
1511 } |
1690 v->u.air.state = STARTTAKEOFF; |
1660 v->u.air.state = STARTTAKEOFF; |
1691 } |
1661 } |
1692 |
1662 |
1693 static void AircraftEventHandler_StartTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1663 static void AircraftEventHandler_StartTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1694 { |
1664 { |
1695 v->sprite_width = v->sprite_height = 24; // ??? no idea what this is |
|
1696 v->u.air.state = ENDTAKEOFF; |
1665 v->u.air.state = ENDTAKEOFF; |
|
1666 v->UpdateDeltaXY(INVALID_DIR); |
1697 } |
1667 } |
1698 |
1668 |
1699 static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1669 static void AircraftEventHandler_EndTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1700 { |
1670 { |
1701 v->u.air.state = FLYING; |
1671 v->u.air.state = FLYING; |
1704 } |
1674 } |
1705 |
1675 |
1706 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1676 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1707 { |
1677 { |
1708 const Player* p = GetPlayer(v->owner); |
1678 const Player* p = GetPlayer(v->owner); |
1709 v->sprite_width = v->sprite_height = 24; // ??? no idea what this is |
|
1710 v->u.air.state = FLYING; |
1679 v->u.air.state = FLYING; |
|
1680 v->UpdateDeltaXY(INVALID_DIR); |
|
1681 |
1711 /* get the next position to go to, differs per airport */ |
1682 /* get the next position to go to, differs per airport */ |
1712 AircraftNextAirportPos_and_Order(v); |
1683 AircraftNextAirportPos_and_Order(v); |
1713 |
1684 |
1714 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed |
1685 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed |
1715 * unless it is due for renewal but the engine is no longer available */ |
1686 * unless it is due for renewal but the engine is no longer available */ |
1716 if (v->owner == _local_player && ( |
1687 if (v->owner == _local_player && ( |
1717 EngineHasReplacementForPlayer(p, v->engine_type) || |
1688 EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) || |
1718 ((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) && |
1689 ((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) && |
1719 HASBIT(GetEngine(v->engine_type)->player_avail, _local_player)) |
1690 HASBIT(GetEngine(v->engine_type)->player_avail, _local_player)) |
1720 )) { |
1691 )) { |
1721 _current_player = _local_player; |
1692 _current_player = _local_player; |
1722 DoCommandP(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
1693 DoCommandP(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
1763 v->u.air.pos = apc->layout[v->u.air.pos].next_position; |
1734 v->u.air.pos = apc->layout[v->u.air.pos].next_position; |
1764 } |
1735 } |
1765 |
1736 |
1766 static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *apc) |
1737 static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *apc) |
1767 { |
1738 { |
|
1739 v->u.air.state = ENDLANDING; |
1768 AircraftLandAirplane(v); // maybe crash airplane |
1740 AircraftLandAirplane(v); // maybe crash airplane |
1769 v->u.air.state = ENDLANDING; |
1741 |
1770 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ |
1742 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ |
1771 if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) { |
1743 if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) { |
1772 /* only the vehicle owner needs to calculate the rest (locally) */ |
1744 /* only the vehicle owner needs to calculate the rest (locally) */ |
1773 const Player* p = GetPlayer(v->owner); |
1745 const Player* p = GetPlayer(v->owner); |
1774 if (EngineHasReplacementForPlayer(p, v->engine_type) || |
1746 if (EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) || |
1775 (p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) { |
1747 (p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) { |
1776 /* send the aircraft to the hangar at next airport */ |
1748 /* send the aircraft to the hangar at next airport */ |
1777 _current_player = _local_player; |
1749 _current_player = _local_player; |
1778 DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
1750 DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
1779 _current_player = OWNER_NONE; |
1751 _current_player = OWNER_NONE; |
1781 } |
1753 } |
1782 } |
1754 } |
1783 |
1755 |
1784 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc) |
1756 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc) |
1785 { |
1757 { |
1786 AircraftLand(v); // helicopters don't crash |
|
1787 v->u.air.state = HELIENDLANDING; |
1758 v->u.air.state = HELIENDLANDING; |
|
1759 v->UpdateDeltaXY(INVALID_DIR); |
1788 } |
1760 } |
1789 |
1761 |
1790 static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *apc) |
1762 static void AircraftEventHandler_EndLanding(Vehicle *v, const AirportFTAClass *apc) |
1791 { |
1763 { |
1792 /* next block busy, don't do a thing, just wait */ |
1764 /* next block busy, don't do a thing, just wait */ |
1883 if (current->heading == v->u.air.state) { |
1855 if (current->heading == v->u.air.state) { |
1884 byte prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand |
1856 byte prev_pos = v->u.air.pos; // location could be changed in state, so save it before-hand |
1885 byte prev_state = v->u.air.state; |
1857 byte prev_state = v->u.air.state; |
1886 _aircraft_state_handlers[v->u.air.state](v, apc); |
1858 _aircraft_state_handlers[v->u.air.state](v, apc); |
1887 if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos; |
1859 if (v->u.air.state != FLYING) v->u.air.previous_pos = prev_pos; |
1888 if (v->u.air.state != prev_state) UpdateAircraftCache(v); |
1860 if (v->u.air.state != prev_state || v->u.air.pos != prev_pos) UpdateAircraftCache(v); |
1889 return true; |
1861 return true; |
1890 } |
1862 } |
1891 |
1863 |
1892 v->u.air.previous_pos = v->u.air.pos; // save previous location |
1864 v->u.air.previous_pos = v->u.air.pos; // save previous location |
1893 |
1865 |
1894 /* there is only one choice to move to */ |
1866 /* there is only one choice to move to */ |
1895 if (current->next == NULL) { |
1867 if (current->next == NULL) { |
1896 if (AirportSetBlocks(v, current, apc)) { |
1868 if (AirportSetBlocks(v, current, apc)) { |
1897 v->u.air.pos = current->next_position; |
1869 v->u.air.pos = current->next_position; |
|
1870 UpdateAircraftCache(v); |
1898 } // move to next position |
1871 } // move to next position |
1899 return false; |
1872 return false; |
1900 } |
1873 } |
1901 |
1874 |
1902 /* there are more choices to choose from, choose the one that |
1875 /* there are more choices to choose from, choose the one that |
1903 * matches our heading */ |
1876 * matches our heading */ |
1904 do { |
1877 do { |
1905 if (v->u.air.state == current->heading || current->heading == TO_ALL) { |
1878 if (v->u.air.state == current->heading || current->heading == TO_ALL) { |
1906 if (AirportSetBlocks(v, current, apc)) { |
1879 if (AirportSetBlocks(v, current, apc)) { |
1907 v->u.air.pos = current->next_position; |
1880 v->u.air.pos = current->next_position; |
|
1881 UpdateAircraftCache(v); |
1908 } // move to next position |
1882 } // move to next position |
1909 return false; |
1883 return false; |
1910 } |
1884 } |
1911 current = current->next; |
1885 current = current->next; |
1912 } while (current != NULL); |
1886 } while (current != NULL); |
2207 /* update position of airplane. If plane is not flying, landing, or taking off |
2181 /* update position of airplane. If plane is not flying, landing, or taking off |
2208 * you cannot delete airport, so it doesn't matter */ |
2182 * you cannot delete airport, so it doesn't matter */ |
2209 if (v->u.air.state >= FLYING) { // circle around |
2183 if (v->u.air.state >= FLYING) { // circle around |
2210 v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap); |
2184 v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, ap); |
2211 v->u.air.state = FLYING; |
2185 v->u.air.state = FLYING; |
|
2186 UpdateAircraftCache(v); |
2212 /* landing plane needs to be reset to flying height (only if in pause mode upgrade, |
2187 /* landing plane needs to be reset to flying height (only if in pause mode upgrade, |
2213 * in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING */ |
2188 * in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING */ |
2214 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
2189 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
2215 /* set new position x,y,z */ |
2190 /* set new position x,y,z */ |
2216 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); |
2191 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); |