Skip to content

Commit

Permalink
Fix OpenTTD#6493: CheckIfAircraftNeedsService - Try to service aircra…
Browse files Browse the repository at this point in the history
…ft 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.
  • Loading branch information
SamuXarick committed Apr 1, 2020
1 parent 40d2078 commit 3019f2b
Showing 1 changed file with 45 additions and 15 deletions.
60 changes: 45 additions & 15 deletions src/aircraft_cmd.cpp
Expand Up @@ -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;
Expand All @@ -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);
}
}
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<CompanyID> 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)
Expand Down Expand Up @@ -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<CompanyID> 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)
Expand Down

0 comments on commit 3019f2b

Please sign in to comment.