From 4672bdb266586283bcecbaee66b8a63ce12a2a47 Mon Sep 17 00:00:00 2001 From: Ivan Pravdin Date: Sat, 31 May 2025 13:20:16 -0400 Subject: [PATCH] Fix #14277: Aircrafts can land when Zeppeliner in the runway --- src/aircraft_cmd.cpp | 14 ++++++++++++++ src/airport.h | 1 + src/disaster_vehicle.cpp | 10 +++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index aac97c84c9..3414801d05 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1125,6 +1125,15 @@ static bool AircraftController(Aircraft *v) } if (amd.flags.Test(AirportMovingDataFlag::Land)) { + if (st->airport.blocks.Test(AirportBlock::Zeppeliner)) { + /* Zeppeliner blocked the runway, abort landing */ + v->state = FLYING; + UpdateAircraftCache(v); + SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v)); + v->pos = v->previous_pos; + continue; + } + if (st->airport.tile == INVALID_TILE) { /* Airport has been removed, abort the landing procedure */ v->state = FLYING; @@ -1782,6 +1791,11 @@ static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc) if (apc->layout[v->previous_pos].blocks != apc->layout[v->pos].blocks) { Station *st = Station::Get(v->targetairport); + if (st->airport.blocks.Test(AirportBlock::Zeppeliner) && + apc->layout[v->previous_pos].blocks == AirportBlock::RunwayIn) { + return; + } + st->airport.blocks.Reset(apc->layout[v->previous_pos].blocks); } } diff --git a/src/airport.h b/src/airport.h index dd795bb943..cdfa14cba4 100644 --- a/src/airport.h +++ b/src/airport.h @@ -127,6 +127,7 @@ enum class AirportBlock : uint8_t { /* end of new blocks */ Nothing = 30, + Zeppeliner = 62, ///< Block for the zeppeliner disaster vehicle. AirportClosed = 63, ///< Dummy block for indicating a closed airport. }; using AirportBlocks = EnumBitSet; diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index 0b279b6059..051bc05892 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -215,7 +215,7 @@ void DisasterVehicle::UpdatePosition(int x, int y, int z) /** * Zeppeliner handling, v->state states: - * 0: Zeppeliner initialization has found a small airport, go there and crash + * 0: Zeppeliner initialization has found an airport, go there and crash * 1: Create crash and animate falling down for extra dramatic effect * 2: Create more smoke and leave debris on ground * 2: Clear the runway after some time and remove crashed zeppeliner @@ -263,7 +263,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v) if (IsValidTile(v->tile) && IsAirportTile(v->tile)) { Station *st = Station::GetByTile(v->tile); - st->airport.blocks.Reset(AirportBlock::RunwayIn); + st->airport.blocks.Reset({AirportBlock::Zeppeliner, AirportBlock::RunwayIn}); AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCleared(st->index)); } @@ -300,7 +300,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v) } if (IsValidTile(v->tile) && IsAirportTile(v->tile)) { - Station::GetByTile(v->tile)->airport.blocks.Set(AirportBlock::RunwayIn); + Station::GetByTile(v->tile)->airport.blocks.Reset({AirportBlock::Zeppeliner, AirportBlock::RunwayIn}); } return true; @@ -722,14 +722,14 @@ typedef void DisasterInitProc(); /** - * Zeppeliner which crashes on a small airport if one found, + * Zeppeliner which crashes on an airport if one found, * otherwise crashes on a random tile */ static void Disaster_Zeppeliner_Init() { if (!Vehicle::CanAllocateItem(2)) return; - /* Pick a random place, unless we find a small airport */ + /* Pick a random place, unless we find an airport */ int x = TileX(RandomTile()) * TILE_SIZE + TILE_SIZE / 2; for (const Station *st : Station::Iterate()) {