From a1ab0d29fe5d5f0e5b90cc0908837f6b301d32f7 Mon Sep 17 00:00:00 2001 From: celestar Date: Thu, 29 Mar 2007 13:52:34 +0000 Subject: (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) --- src/aircraft_cmd.cpp | 89 +++++++++++++++++++++++++++----------------------- src/airport.cpp | 16 +++++++++ src/airport.h | 21 ++++++------ src/airport_movement.h | 17 ++++++++++ src/station.h | 2 +- src/station_cmd.cpp | 7 ++++ 6 files changed, 100 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 6bd9a4a1c..caa6bfa85 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -943,6 +943,42 @@ static byte GetAircraftFlyingAltitude(const Vehicle *v) 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 * on the map and takes care of minor things like sound playback. @@ -954,16 +990,23 @@ static bool AircraftController(Vehicle *v) { int count; 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. */ TileIndex tile = st->airport_tile; - if (tile == 0) tile = st->xy; - int x = TileX(tile) * TILE_SIZE; - int y = TileY(tile) * TILE_SIZE; + if (tile == 0) { + tile = st->xy; + + /* 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 */ - const AirportFTAClass *afc = st->Airport(); - const AirportMovingData *amd = afc->MovingData(v->u.air.pos); + amd = afc->MovingData(v->u.air.pos); + + int x = TileX(tile) * TILE_SIZE; + int y = TileY(tile) * TILE_SIZE; /* Helicopter raise */ if (amd->flag & AMED_HELI_RAISE) { @@ -1470,42 +1513,6 @@ static void AircraftLandAirplane(Vehicle *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 */ static void AircraftNextAirportPos_and_Order(Vehicle *v) diff --git a/src/airport.cpp b/src/airport.cpp index a2c59d89b..539687997 100644 --- a/src/airport.cpp +++ b/src/airport.cpp @@ -20,6 +20,7 @@ * - false: give a summarized report which only shows current and next position */ //#define DEBUG_AIRPORT false +static AirportFTAClass *DummyAirport; static AirportFTAClass *CountryAirport; static AirportFTAClass *CityAirport; static AirportFTAClass *Oilrig; @@ -34,6 +35,20 @@ static AirportFTAClass *HeliStation; 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( _airport_moving_data_country, _airport_terminal_country, @@ -463,6 +478,7 @@ const AirportFTAClass *GetAirport(const byte airport_type) case AT_HELIDEPOT: return HeliDepot; case AT_INTERCON: return IntercontinentalAirport; case AT_HELISTATION: return HeliStation; + case AT_DUMMY: return DummyAirport; } } diff --git a/src/airport.h b/src/airport.h index 27af62e62..1113f03a0 100644 --- a/src/airport.h +++ b/src/airport.h @@ -14,16 +14,17 @@ enum {MAX_HEADINGS = 22}; // Airport types enum { - AT_SMALL = 0, - AT_LARGE = 1, - AT_HELIPORT = 2, - AT_METROPOLITAN = 3, - AT_INTERNATIONAL = 4, - AT_COMMUTER = 5, - AT_HELIDEPOT = 6, - AT_INTERCON = 7, - AT_HELISTATION = 8, - AT_OILRIG = 15 + AT_SMALL = 0, + AT_LARGE = 1, + AT_HELIPORT = 2, + AT_METROPOLITAN = 3, + AT_INTERNATIONAL = 4, + AT_COMMUTER = 5, + AT_HELIDEPOT = 6, + AT_INTERCON = 7, + AT_HELISTATION = 8, + AT_OILRIG = 15, + AT_DUMMY = 255 }; diff --git a/src/airport_movement.h b/src/airport_movement.h index 53d6174d5..02e5fef26 100644 --- a/src/airport_movement.h +++ b/src/airport_movement.h @@ -17,6 +17,14 @@ struct AirportFTAbuildup { /////////////////////////////////////////////////////////////////////// /////*********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 static const AirportMovingData _airport_moving_data_country[22] = { { 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*********************/////// +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) * this may be changed later when airports are moved to external file */ static const TileIndexDiffC _airport_depots_country[] = {{3, 0}}; diff --git a/src/station.h b/src/station.h index 3a4ef31cf..6bd6820d1 100644 --- a/src/station.h +++ b/src/station.h @@ -118,7 +118,7 @@ struct Station { const AirportFTAClass *Airport() const { - assert(airport_tile != 0); + if (airport_tile == 0) return GetAirport(AT_DUMMY); return GetAirport(airport_type); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 6341fd7df..00f77d44f 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1600,6 +1600,13 @@ static int32 RemoveAirport(Station *st, uint32 flags) 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) { if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR; -- cgit v1.2.3-54-g00ecf