mirror of https://github.com/OpenTTD/OpenTTD
(svn r9524) -Fix(FS#640,r8755): Implemented a "dummy" State Machine for stations who got their airport removed while there were still aircraft within the State Machine (and thus caused asserts)
parent
386e298acd
commit
a1ab0d29fe
|
@ -943,6 +943,42 @@ static byte GetAircraftFlyingAltitude(const Vehicle *v)
|
||||||
return base_altitude;
|
return base_altitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the entry point to an airport depending on direction which
|
||||||
|
* the airport is being approached from. Each airport can have up to
|
||||||
|
* four entry points for its approach system so that approaching
|
||||||
|
* aircraft do not fly through each other or are forced to do 180
|
||||||
|
* degree turns during the approach. The arrivals are grouped into
|
||||||
|
* four sectors dependent on the DiagDirection from which the airport
|
||||||
|
* is approached.
|
||||||
|
*
|
||||||
|
* @param v The vehicle that is approaching the airport
|
||||||
|
* @param apc The Airport Class being approached.
|
||||||
|
* @returns The index of the entry point
|
||||||
|
*/
|
||||||
|
static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc)
|
||||||
|
{
|
||||||
|
assert(v != NULL);
|
||||||
|
assert(apc != NULL);
|
||||||
|
|
||||||
|
const Station *st = GetStation(v->u.air.targetairport);
|
||||||
|
/* Make sure we don't go to 0,0 if the airport has been removed. */
|
||||||
|
TileIndex tile = (st->airport_tile != 0) ? st->airport_tile : st->xy;
|
||||||
|
|
||||||
|
int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
|
||||||
|
int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
|
||||||
|
|
||||||
|
DiagDirection dir;
|
||||||
|
if (abs(delta_y) < abs(delta_x)) {
|
||||||
|
/* We are northeast or southwest of the airport */
|
||||||
|
dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
|
||||||
|
} else {
|
||||||
|
/* We are northwest or southeast of the airport */
|
||||||
|
dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
|
||||||
|
}
|
||||||
|
return apc->entry_points[dir];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the movement of an aircraft. This function actually moves the vehicle
|
* Controls the movement of an aircraft. This function actually moves the vehicle
|
||||||
* on the map and takes care of minor things like sound playback.
|
* on the map and takes care of minor things like sound playback.
|
||||||
|
@ -954,16 +990,23 @@ static bool AircraftController(Vehicle *v)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
const Station *st = GetStation(v->u.air.targetairport);
|
const Station *st = GetStation(v->u.air.targetairport);
|
||||||
|
const AirportFTAClass *afc = st->Airport();
|
||||||
|
const AirportMovingData *amd;
|
||||||
|
|
||||||
/* prevent going to 0,0 if airport is deleted. */
|
/* prevent going to 0,0 if airport is deleted. */
|
||||||
TileIndex tile = st->airport_tile;
|
TileIndex tile = st->airport_tile;
|
||||||
if (tile == 0) tile = st->xy;
|
if (tile == 0) {
|
||||||
int x = TileX(tile) * TILE_SIZE;
|
tile = st->xy;
|
||||||
int y = TileY(tile) * TILE_SIZE;
|
|
||||||
|
/* Jump into our "holding pattern" state machine if possible */
|
||||||
|
if (v->u.air.pos >= afc->nofelements) v->u.air.pos = v->u.air.previous_pos = AircraftGetEntryPoint(v, afc);
|
||||||
|
}
|
||||||
|
|
||||||
/* get airport moving data */
|
/* get airport moving data */
|
||||||
const AirportFTAClass *afc = st->Airport();
|
amd = afc->MovingData(v->u.air.pos);
|
||||||
const AirportMovingData *amd = afc->MovingData(v->u.air.pos);
|
|
||||||
|
int x = TileX(tile) * TILE_SIZE;
|
||||||
|
int y = TileY(tile) * TILE_SIZE;
|
||||||
|
|
||||||
/* Helicopter raise */
|
/* Helicopter raise */
|
||||||
if (amd->flag & AMED_HELI_RAISE) {
|
if (amd->flag & AMED_HELI_RAISE) {
|
||||||
|
@ -1470,42 +1513,6 @@ static void AircraftLandAirplane(Vehicle *v)
|
||||||
MaybeCrashAirplane(v);
|
MaybeCrashAirplane(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the entry point to an airport depending on direction which
|
|
||||||
* the airport is being approached from. Each airport can have up to
|
|
||||||
* four entry points for its approach system so that approaching
|
|
||||||
* aircraft do not fly through each other or are forced to do 180
|
|
||||||
* degree turns during the approach. The arrivals are grouped into
|
|
||||||
* four sectors dependent on the DiagDirection from which the airport
|
|
||||||
* is approached.
|
|
||||||
*
|
|
||||||
* @param v The vehicle that is approaching the airport
|
|
||||||
* @param apc The Airport Class being approached.
|
|
||||||
* @returns The index of the entry point
|
|
||||||
*/
|
|
||||||
static byte AircraftGetEntryPoint(const Vehicle *v, const AirportFTAClass *apc)
|
|
||||||
{
|
|
||||||
assert(v != NULL);
|
|
||||||
assert(apc != NULL);
|
|
||||||
|
|
||||||
const Station *st = GetStation(v->u.air.targetairport);
|
|
||||||
/* Make sure we don't go to 0,0 if the airport has been removed. */
|
|
||||||
TileIndex tile = (st->airport_tile != 0) ? st->airport_tile : st->xy;
|
|
||||||
|
|
||||||
int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
|
|
||||||
int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
|
|
||||||
|
|
||||||
DiagDirection dir;
|
|
||||||
if (abs(delta_y) < abs(delta_x)) {
|
|
||||||
/* We are northeast or southwest of the airport */
|
|
||||||
dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
|
|
||||||
} else {
|
|
||||||
/* We are northwest or southeast of the airport */
|
|
||||||
dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
|
|
||||||
}
|
|
||||||
return apc->entry_points[dir];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** set the right pos when heading to other airports after takeoff */
|
/** set the right pos when heading to other airports after takeoff */
|
||||||
static void AircraftNextAirportPos_and_Order(Vehicle *v)
|
static void AircraftNextAirportPos_and_Order(Vehicle *v)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* - false: give a summarized report which only shows current and next position */
|
* - false: give a summarized report which only shows current and next position */
|
||||||
//#define DEBUG_AIRPORT false
|
//#define DEBUG_AIRPORT false
|
||||||
|
|
||||||
|
static AirportFTAClass *DummyAirport;
|
||||||
static AirportFTAClass *CountryAirport;
|
static AirportFTAClass *CountryAirport;
|
||||||
static AirportFTAClass *CityAirport;
|
static AirportFTAClass *CityAirport;
|
||||||
static AirportFTAClass *Oilrig;
|
static AirportFTAClass *Oilrig;
|
||||||
|
@ -34,6 +35,20 @@ static AirportFTAClass *HeliStation;
|
||||||
|
|
||||||
void InitializeAirports()
|
void InitializeAirports()
|
||||||
{
|
{
|
||||||
|
DummyAirport = new AirportFTAClass(
|
||||||
|
_airport_moving_data_dummy,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
_airport_entries_dummy,
|
||||||
|
AirportFTAClass::ALL,
|
||||||
|
_airport_fta_dummy,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
0, 0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
CountryAirport = new AirportFTAClass(
|
CountryAirport = new AirportFTAClass(
|
||||||
_airport_moving_data_country,
|
_airport_moving_data_country,
|
||||||
_airport_terminal_country,
|
_airport_terminal_country,
|
||||||
|
@ -463,6 +478,7 @@ const AirportFTAClass *GetAirport(const byte airport_type)
|
||||||
case AT_HELIDEPOT: return HeliDepot;
|
case AT_HELIDEPOT: return HeliDepot;
|
||||||
case AT_INTERCON: return IntercontinentalAirport;
|
case AT_INTERCON: return IntercontinentalAirport;
|
||||||
case AT_HELISTATION: return HeliStation;
|
case AT_HELISTATION: return HeliStation;
|
||||||
|
case AT_DUMMY: return DummyAirport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,17 @@ enum {MAX_HEADINGS = 22};
|
||||||
|
|
||||||
// Airport types
|
// Airport types
|
||||||
enum {
|
enum {
|
||||||
AT_SMALL = 0,
|
AT_SMALL = 0,
|
||||||
AT_LARGE = 1,
|
AT_LARGE = 1,
|
||||||
AT_HELIPORT = 2,
|
AT_HELIPORT = 2,
|
||||||
AT_METROPOLITAN = 3,
|
AT_METROPOLITAN = 3,
|
||||||
AT_INTERNATIONAL = 4,
|
AT_INTERNATIONAL = 4,
|
||||||
AT_COMMUTER = 5,
|
AT_COMMUTER = 5,
|
||||||
AT_HELIDEPOT = 6,
|
AT_HELIDEPOT = 6,
|
||||||
AT_INTERCON = 7,
|
AT_INTERCON = 7,
|
||||||
AT_HELISTATION = 8,
|
AT_HELISTATION = 8,
|
||||||
AT_OILRIG = 15
|
AT_OILRIG = 15,
|
||||||
|
AT_DUMMY = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,14 @@ struct AirportFTAbuildup {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
/////*********Movement Positions on Airports********************///////
|
/////*********Movement Positions on Airports********************///////
|
||||||
|
|
||||||
|
static const AirportMovingData _airport_moving_data_dummy[] = {
|
||||||
|
{ 0, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} },
|
||||||
|
{ 0, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} },
|
||||||
|
{ 96, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} },
|
||||||
|
{ 96, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, {DIR_N} },
|
||||||
|
};
|
||||||
|
|
||||||
// Country Airfield (small) 4x3
|
// Country Airfield (small) 4x3
|
||||||
static const AirportMovingData _airport_moving_data_country[22] = {
|
static const AirportMovingData _airport_moving_data_country[22] = {
|
||||||
{ 53, 3, AMED_EXACTPOS, {DIR_SE} }, // 00 In Hangar
|
{ 53, 3, AMED_EXACTPOS, {DIR_SE} }, // 00 In Hangar
|
||||||
|
@ -376,6 +384,15 @@ static const AirportMovingData _airport_moving_data_oilrig[9] = {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
/////**********Movement Machine on Airports*********************///////
|
/////**********Movement Machine on Airports*********************///////
|
||||||
|
static const byte _airport_entries_dummy[] = {0, 1, 2, 3};
|
||||||
|
static const AirportFTAbuildup _airport_fta_dummy[] = {
|
||||||
|
{ 0, 0, 0, 3},
|
||||||
|
{ 1, 0, 0, 0},
|
||||||
|
{ 2, 0, 0, 1},
|
||||||
|
{ 3, 0, 0, 2},
|
||||||
|
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
|
||||||
|
};
|
||||||
|
|
||||||
/* First element of terminals array tells us how many depots there are (to know size of array)
|
/* First element of terminals array tells us how many depots there are (to know size of array)
|
||||||
* this may be changed later when airports are moved to external file */
|
* this may be changed later when airports are moved to external file */
|
||||||
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
|
||||||
|
|
|
@ -118,7 +118,7 @@ struct Station {
|
||||||
|
|
||||||
const AirportFTAClass *Airport() const
|
const AirportFTAClass *Airport() const
|
||||||
{
|
{
|
||||||
assert(airport_tile != 0);
|
if (airport_tile == 0) return GetAirport(AT_DUMMY);
|
||||||
return GetAirport(airport_type);
|
return GetAirport(airport_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1600,6 +1600,13 @@ static int32 RemoveAirport(Station *st, uint32 flags)
|
||||||
|
|
||||||
int32 cost = w * h * _price.remove_airport;
|
int32 cost = w * h * _price.remove_airport;
|
||||||
|
|
||||||
|
Vehicle *v;
|
||||||
|
FOR_ALL_VEHICLES(v) {
|
||||||
|
if (!(v->type == VEH_AIRCRAFT && IsNormalAircraft(v))) continue;
|
||||||
|
|
||||||
|
if (v->u.air.targetairport == st->index && v->u.air.state != FLYING) return CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
|
BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
|
||||||
if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
|
if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue