mirror of https://github.com/OpenTTD/OpenTTD
(svn r26866) -Change: make aircraft ascend/descend when they are too close to the ground or too far away (based on patch by ic111)
parent
c88a4aaa5c
commit
c0771b1657
|
@ -15,6 +15,17 @@
|
||||||
#include "station_map.h"
|
#include "station_map.h"
|
||||||
#include "vehicle_base.h"
|
#include "vehicle_base.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base values for flight levels above ground level for 'normal' flight and holding patterns.
|
||||||
|
* Due to speed and direction, the actual flight level may be higher.
|
||||||
|
*/
|
||||||
|
enum AircraftFlyingAltitude {
|
||||||
|
AIRCRAFT_MIN_FLYING_ALTITUDE = 120, ///< Minimum flying altitude above tile.
|
||||||
|
AIRCRAFT_MAX_FLYING_ALTITUDE = 360, ///< Maximum flying altitude above tile.
|
||||||
|
PLANE_HOLD_MAX_FLYING_ALTITUDE = 150, ///< holding flying altitude above tile of planes.
|
||||||
|
HELICOPTER_HOLD_MAX_FLYING_ALTITUDE = 184 ///< holding flying altitude above tile of helicopters.
|
||||||
|
};
|
||||||
|
|
||||||
struct Aircraft;
|
struct Aircraft;
|
||||||
|
|
||||||
/** An aircraft can be one of those types. */
|
/** An aircraft can be one of those types. */
|
||||||
|
@ -25,9 +36,15 @@ enum AircraftSubType {
|
||||||
AIR_ROTOR = 6, ///< rotor of an helicopter
|
AIR_ROTOR = 6, ///< rotor of an helicopter
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Aircraft flags. */
|
/** Flags for air vehicles; shared with disaster vehicles. */
|
||||||
enum VehicleAirFlags {
|
enum AirVehicleFlags {
|
||||||
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
|
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
|
||||||
|
|
||||||
|
/* The next two flags are to prevent stair climbing of the aircraft. The idea is that the aircraft
|
||||||
|
* will ascend or descend multiple flight levels at a time instead of following the contours of the
|
||||||
|
* landscape at a fixed altitude. This only has effect when there are more than 15 height levels. */
|
||||||
|
VAF_IN_MAX_HEIGHT_CORRECTION = 1, ///< The vehicle is currently lowering its altitude because it hit the upper bound.
|
||||||
|
VAF_IN_MIN_HEIGHT_CORRECTION = 2, ///< The vehicle is currently raising its altitude because it hit the lower bound.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int ROTOR_Z_OFFSET = 5; ///< Z Offset between helicopter- and rotorsprite.
|
static const int ROTOR_Z_OFFSET = 5; ///< Z Offset between helicopter- and rotorsprite.
|
||||||
|
@ -40,7 +57,10 @@ void UpdateAircraftCache(Aircraft *v, bool update_range = false);
|
||||||
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir);
|
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir);
|
||||||
void AircraftNextAirportPos_and_Order(Aircraft *v);
|
void AircraftNextAirportPos_and_Order(Aircraft *v);
|
||||||
void SetAircraftPosition(Aircraft *v, int x, int y, int z);
|
void SetAircraftPosition(Aircraft *v, int x, int y, int z);
|
||||||
int GetAircraftFlyingAltitude(const Aircraft *v);
|
|
||||||
|
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min, int *max);
|
||||||
|
template <class T>
|
||||||
|
int GetAircraftFlightLevel(T *v, bool takeoff = false);
|
||||||
|
|
||||||
/** Variables that are cached to improve performance and such. */
|
/** Variables that are cached to improve performance and such. */
|
||||||
struct AircraftCache {
|
struct AircraftCache {
|
||||||
|
@ -60,7 +80,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
||||||
DirectionByte last_direction;
|
DirectionByte last_direction;
|
||||||
byte number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
|
byte number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
|
||||||
byte turn_counter; ///< Ticks between each turn to prevent > 45 degree turns.
|
byte turn_counter; ///< Ticks between each turn to prevent > 45 degree turns.
|
||||||
byte flags; ///< Aircraft flags. @see VehicleAirFlags
|
byte flags; ///< Aircraft flags. @see AirVehicleFlags
|
||||||
|
|
||||||
AircraftCache acache;
|
AircraftCache acache;
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,6 @@
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
static const int PLANE_HOLDING_ALTITUDE = 150; ///< Altitude of planes in holding pattern (= lowest flight altitude).
|
|
||||||
static const int HELI_FLIGHT_ALTITUDE = 184; ///< Normal flight altitude of helicopters.
|
|
||||||
|
|
||||||
|
|
||||||
void Aircraft::UpdateDeltaXY(Direction direction)
|
void Aircraft::UpdateDeltaXY(Direction direction)
|
||||||
{
|
{
|
||||||
this->x_offs = -1;
|
this->x_offs = -1;
|
||||||
|
@ -663,20 +659,35 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the cruise altitude of an aircraft.
|
* Get the tile height below the aircraft.
|
||||||
* The cruise altitude is determined by the velocity of the vehicle
|
* This function is needed because aircraft can leave the mapborders.
|
||||||
* and the direction it is moving
|
*
|
||||||
* @param v The vehicle. Should be an aircraft
|
* @param v The vehicle to get the height for.
|
||||||
* @returns Altitude in pixel units
|
* @return The height in pixels from 'z_pos' 0.
|
||||||
*/
|
*/
|
||||||
int GetAircraftFlyingAltitude(const Aircraft *v)
|
int GetTileHeightBelowAircraft(const Vehicle *v)
|
||||||
{
|
{
|
||||||
if (v->subtype == AIR_HELICOPTER) return HELI_FLIGHT_ALTITUDE;
|
int safe_x = Clamp(v->x_pos, 0, MapMaxX() * TILE_SIZE);
|
||||||
|
int safe_y = Clamp(v->y_pos, 0, MapMaxY() * TILE_SIZE);
|
||||||
|
return TileHeight(TileVirtXY(safe_x, safe_y)) * TILE_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure Aircraft fly no lower so that they don't conduct
|
/**
|
||||||
* CFITs (controlled flight into terrain)
|
* Get the 'flight level' bounds, in pixels from 'z_pos' 0 for a particular
|
||||||
*/
|
* vehicle for normal flight situation.
|
||||||
int base_altitude = PLANE_HOLDING_ALTITUDE;
|
* When the maximum is reached the vehicle should consider descending.
|
||||||
|
* When the minimum is reached the vehicle should consider ascending.
|
||||||
|
*
|
||||||
|
* @param v The vehicle to get the flight levels for.
|
||||||
|
* @param [out] min_level The minimum bounds for flight level.
|
||||||
|
* @param [out] max_level The maximum bounds for flight level.
|
||||||
|
*/
|
||||||
|
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
|
||||||
|
{
|
||||||
|
int base_altitude = GetTileHeightBelowAircraft(v);
|
||||||
|
if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->subtype == AIR_HELICOPTER) {
|
||||||
|
base_altitude += HELICOPTER_HOLD_MAX_FLYING_ALTITUDE - PLANE_HOLD_MAX_FLYING_ALTITUDE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure eastbound and westbound planes do not "crash" into each
|
/* Make sure eastbound and westbound planes do not "crash" into each
|
||||||
* other by providing them with vertical separation
|
* other by providing them with vertical separation
|
||||||
|
@ -693,9 +704,63 @@ int GetAircraftFlyingAltitude(const Aircraft *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make faster planes fly higher so that they can overtake slower ones */
|
/* Make faster planes fly higher so that they can overtake slower ones */
|
||||||
base_altitude += min(20 * (v->vcache.cached_max_speed / 200), 90);
|
base_altitude += min(20 * (v->vcache.cached_max_speed / 200) - 90, 0);
|
||||||
|
|
||||||
return base_altitude;
|
if (min_level != NULL) *min_level = base_altitude + AIRCRAFT_MIN_FLYING_ALTITUDE;
|
||||||
|
if (max_level != NULL) *max_level = base_altitude + AIRCRAFT_MAX_FLYING_ALTITUDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum 'flight level' for the holding pattern of the aircraft,
|
||||||
|
* in pixels 'z_pos' 0, depending on terrain below..
|
||||||
|
*
|
||||||
|
* @param v The aircraft that may or may not need to decrease its altitude.
|
||||||
|
* @return Maximal aircraft holding altitude, while in normal flight, in pixels.
|
||||||
|
*/
|
||||||
|
int GetAircraftHoldMaxAltitude(const Aircraft *v)
|
||||||
|
{
|
||||||
|
int tile_height = GetTileHeightBelowAircraft(v);
|
||||||
|
|
||||||
|
return tile_height + ((v->subtype == AIR_HELICOPTER) ? HELICOPTER_HOLD_MAX_FLYING_ALTITUDE : PLANE_HOLD_MAX_FLYING_ALTITUDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
int GetAircraftFlightLevel(T *v, bool takeoff = false)
|
||||||
|
{
|
||||||
|
/* Aircraft is in flight. We want to enforce it being somewhere
|
||||||
|
* between the minimum and the maximum allowed altitude. */
|
||||||
|
int aircraft_min_altitude;
|
||||||
|
int aircraft_max_altitude;
|
||||||
|
GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude);
|
||||||
|
int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
|
||||||
|
|
||||||
|
/* If those assumptions would be violated, aircrafts would behave fairly strange. */
|
||||||
|
assert(aircraft_min_altitude < aircraft_middle_altitude);
|
||||||
|
assert(aircraft_middle_altitude < aircraft_max_altitude);
|
||||||
|
|
||||||
|
int z = v->z_pos;
|
||||||
|
if (z < aircraft_min_altitude ||
|
||||||
|
(HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
|
||||||
|
/* Ascend. And don't fly into that mountain right ahead.
|
||||||
|
* And avoid our aircraft become a stairclimber, so if we start
|
||||||
|
* correcting altitude, then we stop correction not too early. */
|
||||||
|
SetBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION);
|
||||||
|
z += takeoff ? 2 : 1;
|
||||||
|
} else if (!takeoff && (z > aircraft_max_altitude ||
|
||||||
|
(HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
|
||||||
|
/* Descend lower. You are an aircraft, not an space ship.
|
||||||
|
* And again, don't stop correcting altitude too early. */
|
||||||
|
SetBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION);
|
||||||
|
z--;
|
||||||
|
} else if (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z >= aircraft_middle_altitude) {
|
||||||
|
/* Now, we have corrected altitude enough. */
|
||||||
|
ClrBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION);
|
||||||
|
} else if (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z <= aircraft_middle_altitude) {
|
||||||
|
/* Now, we have corrected altitude enough. */
|
||||||
|
ClrBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -710,7 +775,7 @@ int GetAircraftFlyingAltitude(const Aircraft *v)
|
||||||
* @param v The vehicle that is approaching the airport
|
* @param v The vehicle that is approaching the airport
|
||||||
* @param apc The Airport Class being approached.
|
* @param apc The Airport Class being approached.
|
||||||
* @param rotation The rotation of the airport.
|
* @param rotation The rotation of the airport.
|
||||||
* @returns The index of the entry point
|
* @return The index of the entry point
|
||||||
*/
|
*/
|
||||||
static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
|
static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
|
||||||
{
|
{
|
||||||
|
@ -787,7 +852,7 @@ static bool AircraftController(Aircraft *v)
|
||||||
UpdateAircraftCache(v);
|
UpdateAircraftCache(v);
|
||||||
AircraftNextAirportPos_and_Order(v);
|
AircraftNextAirportPos_and_Order(v);
|
||||||
/* get aircraft back on running altitude */
|
/* get aircraft back on running altitude */
|
||||||
SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlyingAltitude(v));
|
SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,7 +880,9 @@ static bool AircraftController(Aircraft *v)
|
||||||
count = UpdateAircraftSpeed(v);
|
count = UpdateAircraftSpeed(v);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
v->tile = 0;
|
v->tile = 0;
|
||||||
int z_dest = GetAircraftFlyingAltitude(v);
|
|
||||||
|
int z_dest;
|
||||||
|
GetAircraftFlightLevelBounds(v, &z_dest, NULL);
|
||||||
|
|
||||||
/* Reached altitude? */
|
/* Reached altitude? */
|
||||||
if (v->z_pos >= z_dest) {
|
if (v->z_pos >= z_dest) {
|
||||||
|
@ -972,12 +1039,14 @@ static bool AircraftController(Aircraft *v)
|
||||||
int z = v->z_pos;
|
int z = v->z_pos;
|
||||||
|
|
||||||
if (amd.flag & AMED_TAKEOFF) {
|
if (amd.flag & AMED_TAKEOFF) {
|
||||||
z = min(z + 2, GetAircraftFlyingAltitude(v));
|
z = GetAircraftFlightLevel(v, true);
|
||||||
|
} else if (amd.flag & AMED_HOLD) {
|
||||||
|
/* Let the plane drop from normal flight altitude to holding pattern altitude */
|
||||||
|
if (z > GetAircraftHoldMaxAltitude(v)) z--;
|
||||||
|
} else if ((amd.flag & AMED_SLOWTURN) && (amd.flag & AMED_NOSPDCLAMP)) {
|
||||||
|
z = GetAircraftFlightLevel(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the plane drop from normal flight altitude to holding pattern altitude */
|
|
||||||
if ((amd.flag & AMED_HOLD) && (z > PLANE_HOLDING_ALTITUDE)) z--;
|
|
||||||
|
|
||||||
if (amd.flag & AMED_LAND) {
|
if (amd.flag & AMED_LAND) {
|
||||||
if (st->airport.tile == INVALID_TILE) {
|
if (st->airport.tile == INVALID_TILE) {
|
||||||
/* Airport has been removed, abort the landing procedure */
|
/* Airport has been removed, abort the landing procedure */
|
||||||
|
@ -985,7 +1054,7 @@ static bool AircraftController(Aircraft *v)
|
||||||
UpdateAircraftCache(v);
|
UpdateAircraftCache(v);
|
||||||
AircraftNextAirportPos_and_Order(v);
|
AircraftNextAirportPos_and_Order(v);
|
||||||
/* get aircraft back on running altitude */
|
/* get aircraft back on running altitude */
|
||||||
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
|
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -567,7 +567,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object,
|
||||||
|
|
||||||
{
|
{
|
||||||
const Vehicle *w = v->Next();
|
const Vehicle *w = v->Next();
|
||||||
uint16 altitude = v->z_pos - w->z_pos; // Aircraft height - shadow height
|
uint16 altitude = ClampToU16(v->z_pos - w->z_pos); // Aircraft height - shadow height
|
||||||
byte airporttype = ATP_TTDP_LARGE;
|
byte airporttype = ATP_TTDP_LARGE;
|
||||||
|
|
||||||
const Station *st = GetTargetAirportIfValid(Aircraft::From(v));
|
const Station *st = GetTargetAirportIfValid(Aircraft::From(v));
|
||||||
|
|
|
@ -2374,7 +2374,10 @@ bool AfterLoadGame()
|
||||||
UpdateAircraftCache(v);
|
UpdateAircraftCache(v);
|
||||||
AircraftNextAirportPos_and_Order(v);
|
AircraftNextAirportPos_and_Order(v);
|
||||||
/* get aircraft back on running altitude */
|
/* get aircraft back on running altitude */
|
||||||
if ((v->vehstatus & VS_CRASHED) == 0) SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlyingAltitude(v));
|
if ((v->vehstatus & VS_CRASHED) == 0) {
|
||||||
|
GetAircraftFlightLevelBounds(v, &v->z_pos, NULL);
|
||||||
|
SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,8 @@ void UpdateOldAircraft()
|
||||||
if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
|
if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
|
||||||
|
|
||||||
/* set new position x,y,z */
|
/* set new position x,y,z */
|
||||||
SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlyingAltitude(a));
|
GetAircraftFlightLevelBounds(a, &a->z_pos, NULL);
|
||||||
|
SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlightLevel(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue