|
@@ -146,14 +146,14 @@ static StationID FindNearestHangar(const
|
|
|
|
|
|
const AirportFTAClass *afc = st->airport.GetFTA();
|
|
|
|
|
|
/* 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) {
|
|
|
uint last_dist = (last_dest != nullptr && last_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, last_dest->airport.tile) : 0;
|
|
|
uint next_dist = (next_dest != nullptr && next_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, next_dest->airport.tile) : 0;
|
|
|
if (last_dist > max_range || next_dist > max_range) continue;
|
|
@@ -323,12 +323,15 @@ CommandCost CmdBuildAircraft(DoCommandFl
|
|
|
|
|
|
u->subtype = AIR_SHADOW;
|
|
|
u->UpdateDeltaXY();
|
|
|
|
|
|
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);
|
|
|
|
|
|
v->state = HANGAR;
|
|
|
v->previous_pos = v->pos;
|
|
@@ -434,12 +437,13 @@ static void CheckIfAircraftNeedsService(
|
|
|
}
|
|
|
|
|
|
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());
|
|
|
}
|
|
|
|
|
|
void Aircraft::OnNewDay()
|
|
|
{
|
|
|
if (!this->IsNormalAircraft()) return;
|
|
@@ -604,13 +608,13 @@ void UpdateAircraftCache(Aircraft *v, bo
|
|
|
v->vcache.cached_cargo_age_period = GetVehicleProperty(v, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(v->engine_type)->cargo_age_period);
|
|
|
Aircraft *u = v->Next(); // Shadow for mail
|
|
|
u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
|
|
|
|
|
|
/* 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;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
@@ -646,15 +650,23 @@ static int UpdateAircraftSpeed(Aircraft
|
|
|
|
|
|
/* Adjust speed limits by plane speed factor to prevent taxiing
|
|
|
* and take-off speeds being too low. */
|
|
|
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<uint>(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<uint>(speed_limit, broken_down_max_speed);
|
|
|
}
|
|
|
|
|
|
if (v->vcache.cached_max_speed < speed_limit) {
|
|
|
if (v->cur_speed < speed_limit) hard_limit = false;
|
|
|
speed_limit = v->vcache.cached_max_speed;
|
|
|
}
|
|
@@ -1153,12 +1165,45 @@ static bool AircraftController(Aircraft
|
|
|
SetAircraftPosition(v, gp.x, gp.y, z);
|
|
|
} while (--count != 0);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 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.
|
|
|
*/
|
|
|
static bool HandleCrashedAircraft(Aircraft *v)
|
|
|
{
|
|
|
v->crashed_counter += 3;
|
|
@@ -1232,14 +1277,15 @@ static void HandleAircraftSmoke(Aircraft
|
|
|
{ -5, 5 },
|
|
|
{ 0, 6 }
|
|
|
};
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
/* Spawn effect et most once per Tick, i.e. !mode */
|
|
@@ -1362,14 +1408,18 @@ static void MaybeCrashAirplane(Aircraft
|
|
|
|
|
|
uint32 prob;
|
|
|
if ((st->airport.GetFTA()->flags & AirportFTAClass::SHORT_STRIP) &&
|
|
|
(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;
|
|
|
}
|
|
|
|
|
|
if (GB(Random(), 0, 22) > prob) return;
|
|
|
|
|
|
/* Crash the airplane. Remove all goods stored at the station. */
|