diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -149,8 +149,8 @@ static StationID FindNearestHangar(const /* don't crash the plane if we know it can't land at the airport */ if ((afc->flags & AirportFTAClass::SHORT_STRIP) && (avi->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) continue; - /* the plane won't land at any helicopter station */ - if (!(afc->flags & AirportFTAClass::AIRPLANES) && (avi->subtype & AIR_CTOL)) continue; + /* the plane won't land at any helicopter station and vice versa*/ + if (!CanVehicleUseStation(v, st)) continue; /* Check if our last and next destinations can be reached from the depot airport. */ if (max_range != 0) { @@ -326,6 +326,9 @@ CommandCost CmdBuildAircraft(DoCommandFl v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; + /* higher speed means higher breakdown chance */ + /* to somewhat compensate for the fact that fast aircraft spend less time in the air */ + v->breakdown_chance = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255); v->max_age = e->GetLifeLengthInDays(); v->pos = GetVehiclePosOnBuild(tile); @@ -437,6 +440,7 @@ Money Aircraft::GetRunningCost() const { const Engine *e = this->GetEngine(); uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->u.air.running_cost); + cost_factor *= _settings_game.economy.running_cost_multiplier_air; return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF()); } @@ -607,7 +611,7 @@ void UpdateAircraftCache(Aircraft *v, bo /* Update aircraft range. */ if (update_range) { - v->acache.cached_max_range = GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range); + v->acache.cached_max_range = (GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range) * _settings_game.vehicle.plane_range_multiplier); /* Squared it now so we don't have to do it later all the time. */ v->acache.cached_max_range_sqr = v->acache.cached_max_range * v->acache.cached_max_range; } @@ -649,9 +653,17 @@ static int UpdateAircraftSpeed(Aircraft speed_limit *= _settings_game.vehicle.plane_speed; /* adjust speed for broken vehicles */ - if (v->vehstatus & VS_AIRCRAFT_BROKEN) { - if (SPEED_LIMIT_BROKEN < speed_limit) hard_limit = false; - speed_limit = std::min(speed_limit, SPEED_LIMIT_BROKEN); + if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_SPEED) { + if (v->breakdown_severity < 10) + { + // stupid workaround for fixing old saves with severity 0, also FGSP + v->breakdown_severity = 10; + } + uint percentage_speed_limit = v->breakdown_severity; + uint cached_max_speed = v->vcache.cached_max_speed; + uint broken_down_max_speed = ((cached_max_speed * percentage_speed_limit) + 99) / 100; + if (broken_down_max_speed < speed_limit) hard_limit = false; + speed_limit = std::min(speed_limit, broken_down_max_speed); } if (v->vcache.cached_max_speed < speed_limit) { @@ -1156,6 +1168,39 @@ static bool AircraftController(Aircraft } /** + * Send a broken plane that needs to visit a depot to the correct location. + * @param v The airplane in question + */ +void FindBreakdownDestination(Aircraft *v) +{ + assert(v->type == VEH_AIRCRAFT && v->breakdown_ctr == 1); + + DestinationID destination = INVALID_STATION; + if (v->breakdown_type == BREAKDOWN_AIRCRAFT_DEPOT) { + /* Go to a hangar, if possible at our current destination */ + v->FindClosestDepot(NULL, &destination, NULL); + } else if (v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) { + /* Go to the nearest airport with a hangar */ + destination = FindNearestHangar(v); + } else { + NOT_REACHED(); + } + + if(destination != INVALID_STATION) { + if(destination != v->current_order.GetDestination()) { + v->current_order.MakeGoToDepot(destination, ODTFB_BREAKDOWN); + AircraftNextAirportPos_and_Order(v); + } else { + v->current_order.MakeGoToDepot(destination, ODTFB_BREAKDOWN); + } + } else { + /* If no hangar was found, crash */ + v->targetairport = INVALID_STATION; + CrashAirplane(v); + } +} + +/** * Handle crashed aircraft \a v. * @param v Crashed aircraft. */ @@ -1235,8 +1280,9 @@ static void HandleAircraftSmoke(Aircraft if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return; - /* Stop smoking when landed */ - if (v->cur_speed < 10) { + /* breakdown-related speed limits are lifted when we are on the ground */ + if(v->state != FLYING && v->state != LANDING && v->breakdown_type == BREAKDOWN_AIRCRAFT_SPEED) { + /* Stop smoking when landed */ v->vehstatus &= ~VS_AIRCRAFT_BROKEN; v->breakdown_ctr = 0; return; @@ -1365,8 +1411,12 @@ static void MaybeCrashAirplane(Aircraft (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) { prob = 3276; + } else if (_settings_game.vehicle.plane_crashes == 0) { + return; + } else if (_settings_game.vehicle.improved_breakdowns && v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) { + /* Airplanes that are attempting an emergency landing have a 2% chance to crash */ + prob = 0x10000 / 50; } else { - if (_settings_game.vehicle.plane_crashes == 0) return; prob = (0x4000 << _settings_game.vehicle.plane_crashes) / 1500; }