7 #include "openttd.h" |
7 #include "openttd.h" |
8 #include "aircraft.h" |
8 #include "aircraft.h" |
9 #include "debug.h" |
9 #include "debug.h" |
10 #include "landscape.h" |
10 #include "landscape.h" |
11 #include "station_map.h" |
11 #include "station_map.h" |
12 #include "table/strings.h" |
|
13 #include "timetable.h" |
12 #include "timetable.h" |
14 #include "depot.h" |
13 #include "depot.h" |
15 #include "engine.h" |
14 #include "engine.h" |
16 #include "station.h" |
15 #include "station.h" |
17 #include "news.h" |
16 #include "news.h" |
18 #include "player.h" |
|
19 #include "aircraft.h" |
17 #include "aircraft.h" |
20 #include "airport.h" |
18 #include "airport.h" |
21 #include "vehicle_gui.h" |
19 #include "vehicle_gui.h" |
22 #include "table/sprites.h" |
|
23 #include "newgrf_engine.h" |
20 #include "newgrf_engine.h" |
24 #include "newgrf_callbacks.h" |
21 #include "newgrf_callbacks.h" |
25 #include "newgrf_text.h" |
22 #include "newgrf_text.h" |
26 #include "newgrf_sound.h" |
23 #include "newgrf_sound.h" |
27 #include "spritecache.h" |
24 #include "spritecache.h" |
36 #include "variables.h" |
33 #include "variables.h" |
37 #include "autoreplace_func.h" |
34 #include "autoreplace_func.h" |
38 #include "autoreplace_gui.h" |
35 #include "autoreplace_gui.h" |
39 #include "gfx_func.h" |
36 #include "gfx_func.h" |
40 #include "ai/ai.h" |
37 #include "ai/ai.h" |
|
38 #include "player_func.h" |
|
39 #include "settings_type.h" |
|
40 |
|
41 #include "table/strings.h" |
|
42 #include "table/sprites.h" |
41 |
43 |
42 void Aircraft::UpdateDeltaXY(Direction direction) |
44 void Aircraft::UpdateDeltaXY(Direction direction) |
43 { |
45 { |
44 uint32 x; |
46 uint32 x; |
45 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
47 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
334 v->cargo_type = CT_PASSENGERS; |
336 v->cargo_type = CT_PASSENGERS; |
335 u->cargo_type = CT_MAIL; |
337 u->cargo_type = CT_MAIL; |
336 |
338 |
337 v->cargo_subtype = 0; |
339 v->cargo_subtype = 0; |
338 |
340 |
339 v->string_id = STR_SV_AIRCRAFT_NAME; |
341 v->name = NULL; |
340 // v->next_order_param = v->next_order = 0; |
342 // v->next_order_param = v->next_order = 0; |
341 |
343 |
342 // v->load_unload_time_rem = 0; |
344 // v->load_unload_time_rem = 0; |
343 // v->progress = 0; |
345 // v->progress = 0; |
344 v->last_station_visited = INVALID_STATION; |
346 v->last_station_visited = INVALID_STATION; |
534 DeleteVehicleNews(p1, STR_A014_AIRCRAFT_IS_WAITING_IN); |
536 DeleteVehicleNews(p1, STR_A014_AIRCRAFT_IS_WAITING_IN); |
535 } |
537 } |
536 |
538 |
537 v->vehstatus ^= VS_STOPPED; |
539 v->vehstatus ^= VS_STOPPED; |
538 v->cur_speed = 0; |
540 v->cur_speed = 0; |
539 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
541 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
540 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
542 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
541 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
543 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
542 } |
544 } |
543 |
545 |
544 return CommandCost(); |
546 return CommandCost(); |
566 Vehicle *v = GetVehicle(p1); |
568 Vehicle *v = GetVehicle(p1); |
567 |
569 |
568 if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner) || v->IsInDepot()) return CMD_ERROR; |
570 if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner) || v->IsInDepot()) return CMD_ERROR; |
569 |
571 |
570 if (v->current_order.type == OT_GOTO_DEPOT && !(p2 & DEPOT_LOCATE_HANGAR)) { |
572 if (v->current_order.type == OT_GOTO_DEPOT && !(p2 & DEPOT_LOCATE_HANGAR)) { |
571 if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT)) { |
573 if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OF_HALT_IN_DEPOT)) { |
572 /* We called with a different DEPOT_SERVICE setting. |
574 /* We called with a different DEPOT_SERVICE setting. |
573 * Now we change the setting to apply the new one and let the vehicle head for the same hangar. |
575 * Now we change the setting to apply the new one and let the vehicle head for the same hangar. |
574 * Note: the if is (true for requesting service == true for ordered to stop in hangar) */ |
576 * Note: the if is (true for requesting service == true for ordered to stop in hangar) */ |
575 if (flags & DC_EXEC) { |
577 if (flags & DC_EXEC) { |
576 ClrBit(v->current_order.flags, OFB_PART_OF_ORDERS); |
578 ClrBit(v->current_order.flags, OF_PART_OF_ORDERS); |
577 ToggleBit(v->current_order.flags, OFB_HALT_IN_DEPOT); |
579 ToggleBit(v->current_order.flags, OF_HALT_IN_DEPOT); |
578 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
580 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
579 } |
581 } |
580 return CommandCost(); |
582 return CommandCost(); |
581 } |
583 } |
582 |
584 |
583 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of hangar orders |
585 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of hangar orders |
584 if (flags & DC_EXEC) { |
586 if (flags & DC_EXEC) { |
585 if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++; |
587 if (v->current_order.flags & OFB_UNLOAD) v->cur_order_index++; |
586 v->current_order.type = OT_DUMMY; |
588 v->current_order.type = OT_DUMMY; |
587 v->current_order.flags = 0; |
589 v->current_order.flags = 0; |
588 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
590 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
589 } |
591 } |
590 } else { |
592 } else { |
591 bool next_airport_has_hangar = true; |
593 bool next_airport_has_hangar = true; |
592 StationID next_airport_index = v->u.air.targetairport; |
594 StationID next_airport_index = v->u.air.targetairport; |
593 const Station *st = GetStation(next_airport_index); |
595 const Station *st = GetStation(next_airport_index); |
603 |
605 |
604 if (flags & DC_EXEC) { |
606 if (flags & DC_EXEC) { |
605 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
607 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
606 |
608 |
607 v->current_order.type = OT_GOTO_DEPOT; |
609 v->current_order.type = OT_GOTO_DEPOT; |
608 v->current_order.flags = OF_NON_STOP; |
610 v->current_order.flags = OFB_NON_STOP; |
609 if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OFB_HALT_IN_DEPOT); |
611 if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OF_HALT_IN_DEPOT); |
610 v->current_order.refit_cargo = CT_INVALID; |
612 v->current_order.refit_cargo = CT_INVALID; |
611 v->current_order.dest = next_airport_index; |
613 v->current_order.dest = next_airport_index; |
612 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
614 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
613 if (v->u.air.state == FLYING && !next_airport_has_hangar) { |
615 if (v->u.air.state == FLYING && !next_airport_has_hangar) { |
614 /* The aircraft is now heading for a different hangar than the next in the orders */ |
616 /* The aircraft is now heading for a different hangar than the next in the orders */ |
615 AircraftNextAirportPos_and_Order(v); |
617 AircraftNextAirportPos_and_Order(v); |
616 } |
618 } |
617 } |
619 } |
711 /* only goto depot if the target airport has terminals (eg. it is airport) */ |
713 /* only goto depot if the target airport has terminals (eg. it is airport) */ |
712 if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) { |
714 if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) { |
713 // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); |
715 // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); |
714 // v->u.air.targetairport = st->index; |
716 // v->u.air.targetairport = st->index; |
715 v->current_order.type = OT_GOTO_DEPOT; |
717 v->current_order.type = OT_GOTO_DEPOT; |
716 v->current_order.flags = OF_NON_STOP; |
718 v->current_order.flags = OFB_NON_STOP; |
717 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
719 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
718 } else if (v->current_order.type == OT_GOTO_DEPOT) { |
720 } else if (v->current_order.type == OT_GOTO_DEPOT) { |
719 v->current_order.type = OT_DUMMY; |
721 v->current_order.type = OT_DUMMY; |
720 v->current_order.flags = 0; |
722 v->current_order.flags = 0; |
721 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
723 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
722 } |
724 } |
723 } |
725 } |
724 |
726 |
725 void OnNewDay_Aircraft(Vehicle *v) |
727 void Aircraft::OnNewDay() |
726 { |
728 { |
727 if (!IsNormalAircraft(v)) return; |
729 if (!IsNormalAircraft(this)) return; |
728 |
730 |
729 if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v); |
731 if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); |
730 |
732 |
731 CheckOrders(v); |
733 CheckOrders(this); |
732 |
734 |
733 CheckVehicleBreakdown(v); |
735 CheckVehicleBreakdown(this); |
734 AgeVehicle(v); |
736 AgeVehicle(this); |
735 CheckIfAircraftNeedsService(v); |
737 CheckIfAircraftNeedsService(this); |
736 |
738 |
737 if (v->vehstatus & VS_STOPPED) return; |
739 if (this->vehstatus & VS_STOPPED) return; |
738 |
740 |
739 CommandCost cost = CommandCost(EXPENSES_AIRCRAFT_RUN, GetVehicleProperty(v, 0x0E, AircraftVehInfo(v->engine_type)->running_cost) * _price.aircraft_running / 364); |
741 CommandCost cost = CommandCost(EXPENSES_AIRCRAFT_RUN, GetVehicleProperty(this, 0x0E, AircraftVehInfo(this->engine_type)->running_cost) * _price.aircraft_running / 364); |
740 |
742 |
741 v->profit_this_year -= cost.GetCost() >> 8; |
743 this->profit_this_year -= cost.GetCost() >> 8; |
742 |
744 |
743 SubtractMoneyFromPlayerFract(v->owner, cost); |
745 SubtractMoneyFromPlayerFract(this->owner, cost); |
744 |
746 |
745 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
747 InvalidateWindow(WC_VEHICLE_DETAILS, this->index); |
746 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
748 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
747 } |
749 } |
748 |
750 |
749 void AircraftYearlyLoop() |
751 void AircraftYearlyLoop() |
750 { |
752 { |
938 |
940 |
939 /* updates statusbar only if speed have changed to save CPU time */ |
941 /* updates statusbar only if speed have changed to save CPU time */ |
940 if (spd != v->cur_speed) { |
942 if (spd != v->cur_speed) { |
941 v->cur_speed = spd; |
943 v->cur_speed = spd; |
942 if (_patches.vehicle_speed) |
944 if (_patches.vehicle_speed) |
943 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
945 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
944 } |
946 } |
945 |
947 |
946 if (!(v->direction & 1)) spd = spd * 3 / 4; |
948 if (!(v->direction & 1)) spd = spd * 3 / 4; |
947 |
949 |
948 spd += v->progress; |
950 spd += v->progress; |
1285 * but they all share the same number */ |
1287 * but they all share the same number */ |
1286 CLRBITS(st->airport_flags, RUNWAY_IN_block); |
1288 CLRBITS(st->airport_flags, RUNWAY_IN_block); |
1287 CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport |
1289 CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport |
1288 CLRBITS(st->airport_flags, RUNWAY_IN2_block); // intercontinental |
1290 CLRBITS(st->airport_flags, RUNWAY_IN2_block); // intercontinental |
1289 |
1291 |
1290 BeginVehicleMove(v); |
1292 MarkSingleVehicleDirty(v); |
1291 EndVehicleMove(v); |
|
1292 |
1293 |
1293 DoDeleteAircraft(v); |
1294 DoDeleteAircraft(v); |
1294 } |
1295 } |
1295 } |
1296 } |
1296 |
1297 |
1344 |
1345 |
1345 static void ProcessAircraftOrder(Vehicle *v) |
1346 static void ProcessAircraftOrder(Vehicle *v) |
1346 { |
1347 { |
1347 switch (v->current_order.type) { |
1348 switch (v->current_order.type) { |
1348 case OT_GOTO_DEPOT: |
1349 case OT_GOTO_DEPOT: |
1349 if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return; |
1350 if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return; |
1350 if (v->current_order.flags & OF_SERVICE_IF_NEEDED && |
1351 if (v->current_order.flags & OFB_SERVICE_IF_NEEDED && |
1351 !VehicleNeedsService(v)) { |
1352 !VehicleNeedsService(v)) { |
1352 UpdateVehicleTimetable(v, true); |
1353 UpdateVehicleTimetable(v, true); |
1353 v->cur_order_index++; |
1354 v->cur_order_index++; |
1354 } |
1355 } |
1355 break; |
1356 break; |
1414 |
1415 |
1415 void Aircraft::MarkDirty() |
1416 void Aircraft::MarkDirty() |
1416 { |
1417 { |
1417 this->cur_image = this->GetImage(this->direction); |
1418 this->cur_image = this->GetImage(this->direction); |
1418 if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this); |
1419 if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this); |
1419 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
1420 MarkSingleVehicleDirty(this); |
1420 } |
1421 } |
1421 |
1422 |
1422 static void CrashAirplane(Vehicle *v) |
1423 static void CrashAirplane(Vehicle *v) |
1423 { |
1424 { |
1424 v->vehstatus |= VS_CRASHED; |
1425 v->vehstatus |= VS_CRASHED; |
1548 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); |
1549 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos); |
1549 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1550 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1550 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
1551 InvalidateWindowClasses(WC_AIRCRAFT_LIST); |
1551 } |
1552 } |
1552 |
1553 |
|
1554 /** Checks if an aircraft should head towards a hangar because it needs replacement |
|
1555 * @param *v the vehicle to test |
|
1556 * @return true if the aircraft should head towards a hangar |
|
1557 */ |
|
1558 static inline bool CheckSendAircraftToHangarForReplacement(const Vehicle *v) |
|
1559 { |
|
1560 EngineID new_engine; |
|
1561 Player *p = GetPlayer(v->owner); |
|
1562 |
|
1563 if (VehicleHasDepotOrders(v)) return false; // The aircraft will end up in the hangar eventually on it's own |
|
1564 |
|
1565 new_engine = EngineReplacementForPlayer(p, v->engine_type, v->group_id); |
|
1566 |
|
1567 if (new_engine == INVALID_ENGINE) { |
|
1568 /* There is no autoreplace assigned to this EngineID so we will set it to renew to the same type if needed */ |
|
1569 new_engine = v->engine_type; |
|
1570 |
|
1571 if(!p->engine_renew || (v->age - v->max_age) < p->engine_renew_months * 30) { |
|
1572 /* No need to replace the aircraft */ |
|
1573 return false; |
|
1574 } |
|
1575 } |
|
1576 |
|
1577 if (!HasBit(GetEngine(new_engine)->player_avail, v->owner)) { |
|
1578 /* Engine is not buildable anymore */ |
|
1579 return false; |
|
1580 } |
|
1581 |
|
1582 if (p->player_money < (p->engine_renew_money + (2 * DoCommand(0, new_engine, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT).GetCost()))) { |
|
1583 /* We lack enough money to request the replacement right away. |
|
1584 * We want 2*(the price of the new vehicle) and not looking at the value of the vehicle we are going to sell. |
|
1585 * The reason is that we don't want to send a whole lot of vehicles to the hangars when we only have enough money to replace a single one. |
|
1586 * Remember this happens in the background so the user can't stop this. */ |
|
1587 return false; |
|
1588 } |
|
1589 |
|
1590 /* We found no reason NOT to send the aircraft to a hangar so we will send it there at once */ |
|
1591 return true; |
|
1592 } |
1553 |
1593 |
1554 //////////////////////////////////////////////////////////////////////////////// |
1594 //////////////////////////////////////////////////////////////////////////////// |
1555 /////////////////// AIRCRAFT MOVEMENT SCHEME //////////////////////////////// |
1595 /////////////////// AIRCRAFT MOVEMENT SCHEME //////////////////////////////// |
1556 //////////////////////////////////////////////////////////////////////////////// |
1596 //////////////////////////////////////////////////////////////////////////////// |
1557 static void AircraftEventHandler_EnterTerminal(Vehicle *v, const AirportFTAClass *apc) |
1597 static void AircraftEventHandler_EnterTerminal(Vehicle *v, const AirportFTAClass *apc) |
1676 AircraftNextAirportPos_and_Order(v); |
1716 AircraftNextAirportPos_and_Order(v); |
1677 } |
1717 } |
1678 |
1718 |
1679 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1719 static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *apc) |
1680 { |
1720 { |
1681 const Player* p = GetPlayer(v->owner); |
|
1682 v->u.air.state = FLYING; |
1721 v->u.air.state = FLYING; |
1683 v->UpdateDeltaXY(INVALID_DIR); |
1722 v->UpdateDeltaXY(INVALID_DIR); |
1684 |
1723 |
1685 /* get the next position to go to, differs per airport */ |
1724 /* get the next position to go to, differs per airport */ |
1686 AircraftNextAirportPos_and_Order(v); |
1725 AircraftNextAirportPos_and_Order(v); |
1687 |
1726 |
1688 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed |
1727 /* Send the helicopter to a hangar if needed for replacement */ |
1689 * unless it is due for renewal but the engine is no longer available */ |
1728 if (CheckSendAircraftToHangarForReplacement(v)) { |
1690 if (v->owner == _local_player && ( |
1729 _current_player = v->owner; |
1691 EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) || |
1730 DoCommand(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR); |
1692 ((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) && |
|
1693 HasBit(GetEngine(v->engine_type)->player_avail, _local_player)) |
|
1694 )) { |
|
1695 _current_player = _local_player; |
|
1696 DoCommandP(v->tile, v->index, DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
|
1697 _current_player = OWNER_NONE; |
1731 _current_player = OWNER_NONE; |
1698 } |
1732 } |
1699 } |
1733 } |
1700 |
1734 |
1701 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc) |
1735 static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc) |
1741 { |
1775 { |
1742 v->u.air.state = ENDLANDING; |
1776 v->u.air.state = ENDLANDING; |
1743 AircraftLandAirplane(v); // maybe crash airplane |
1777 AircraftLandAirplane(v); // maybe crash airplane |
1744 |
1778 |
1745 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ |
1779 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ |
1746 if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) { |
1780 if (CheckSendAircraftToHangarForReplacement(v)) { |
1747 /* only the vehicle owner needs to calculate the rest (locally) */ |
1781 _current_player = v->owner; |
1748 const Player* p = GetPlayer(v->owner); |
1782 DoCommand(v->tile, v->index, DEPOT_SERVICE, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR); |
1749 if (EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) || |
1783 _current_player = OWNER_NONE; |
1750 (p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) { |
|
1751 /* send the aircraft to the hangar at next airport */ |
|
1752 _current_player = _local_player; |
|
1753 DoCommandP(v->tile, v->index, DEPOT_SERVICE, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR); |
|
1754 _current_player = OWNER_NONE; |
|
1755 } |
|
1756 } |
1784 } |
1757 } |
1785 } |
1758 |
1786 |
1759 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc) |
1787 static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *apc) |
1760 { |
1788 { |