From 3019f2b48b8f5826b5488c3b44fe187117613820 Mon Sep 17 00:00:00 2001 From: Samu Date: Tue, 2 Oct 2018 21:13:33 +0100 Subject: [PATCH] Fix #6493: CheckIfAircraftNeedsService - Try to service aircraft at a hangar outside the order list If a helicopter needs to be sent to a hangar during automatic service, and there are no airports with hangars in the orders (travelling between heliports), a nearby hangar outside the orders will be searched. If the distance to a found hangar is shorter than the distance to the helistation/airport the helicopter is headed to, the helicopter is sent to that hangar. --- src/aircraft_cmd.cpp | 60 +++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index fbf0d7f0eaa2..76ad4ce12453 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -410,7 +410,10 @@ bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, static void CheckIfAircraftNeedsService(Aircraft *v) { - if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return; + bool needs_automatic_servicing = v->NeedsAutomaticServicing(); + bool has_pending_replace = v->HasPendingReplace(); + if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || (!needs_automatic_servicing && + (!has_pending_replace || v->subtype != AIR_HELICOPTER || !_settings_game.order.serviceathelipad))) return; if (v->IsChainInDepot()) { VehicleServiceInDepot(v); return; @@ -431,6 +434,39 @@ static void CheckIfAircraftNeedsService(Aircraft *v) } else if (v->current_order.IsType(OT_GOTO_DEPOT)) { v->current_order.MakeDummy(); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); + } else { + bool hangar_in_o = false; + const Order *o; + + /* Is there at least an airport coupled with a hangar in the orders? */ + FOR_VEHICLE_ORDERS(v, o) { + if (o->IsType(OT_GOTO_STATION)) { + const Station *ost = Station::Get(o->GetDestination()); + if (ost->airport.HasHangar() || + /* Helicopters can be serviced at helipads as long as there is no pending replace and serviceathelipad is enabled */ + (v->subtype == AIR_HELICOPTER && !has_pending_replace && _settings_game.order.serviceathelipad && ost->airport.GetFTA()->num_helipads)) { + hangar_in_o = true; + break; + } + } + } + + if (!hangar_in_o) { + /* there's no airport coupled with a hangar in the orders, so look for a nearby hangar */ + const StationID nearest_hangar = FindNearestHangar(v); + + /* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */ + TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos); + + if (nearest_hangar != INVALID_STATION && ((has_pending_replace && v->subtype == AIR_HELICOPTER && _settings_game.order.serviceathelipad && !needs_automatic_servicing) || + /* is nearest hangar closer than destination? */ + DistanceSquare(vtile, Station::Get(nearest_hangar)->airport.tile) <= DistanceSquare(vtile, st->airport.tile))) { + /* defer destination, service aircraft at that hangar now */ + v->current_order.MakeGoToDepot(nearest_hangar, ODTFB_SERVICE); + v->SetDestTile(v->GetOrderStationLocation(nearest_hangar)); + SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); + } + } } } @@ -1544,6 +1580,14 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass * /* airport-road is free. We either have to go to another airport, or to the hangar * ---> start moving */ + if (Station::Get(v->targetairport)->airport.HasHangar()) { + if (v->NeedsAutomaticServicing() || (v->subtype == AIR_HELICOPTER && v->HasPendingReplace() && _settings_game.order.serviceathelipad && + (!v->HasDepotOrder() || !(v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDepotOrderType() != ODTFB_SERVICE)))) { + v->current_order.MakeGoToDepot(v->targetairport, ODTFB_SERVICE); + SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); + } + } + bool go_to_hangar = false; switch (v->current_order.GetType()) { case OT_GOTO_STATION: // ready to fly to another airport @@ -1602,13 +1646,6 @@ static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass /* get the next position to go to, differs per airport */ AircraftNextAirportPos_and_Order(v); - - /* Send the helicopter to a hangar if needed for replacement */ - if (v->NeedsAutomaticServicing()) { - Backup cur_company(_current_company, v->owner, FILE_LINE); - DoCommand(v->tile, v->index | DEPOT_SERVICE | DEPOT_LOCATE_HANGAR, 0, DC_EXEC, CMD_SEND_VEHICLE_TO_DEPOT); - cur_company.Restore(); - } } static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc) @@ -1653,13 +1690,6 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc { v->state = ENDLANDING; AircraftLandAirplane(v); // maybe crash airplane - - /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ - if (v->NeedsAutomaticServicing()) { - Backup cur_company(_current_company, v->owner, FILE_LINE); - DoCommand(v->tile, v->index | DEPOT_SERVICE, 0, DC_EXEC, CMD_SEND_VEHICLE_TO_DEPOT); - cur_company.Restore(); - } } static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *apc)