From b1c9a0f6287aa0ea93c7f3dc99944c6471e2dcfb Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 11 Feb 2024 11:12:21 +0000 Subject: [PATCH] Codechange: Don't scan vehicle pool to find targeting disaster vehicle when deleting any vehicle. When deleting a vehicle, the vehicle pool is scanned to find a targetting disaster vehicle. With lots of vehicles this can take some time, especially when deleting multiple consecutive vehicles. Disasters vehicles can actually only target road vehicles. Store the DisasterVehicle index in the road vehicle, so that no pool scan is necessary. --- src/disaster_vehicle.cpp | 30 ++++++++++++++++-------------- src/roadveh.h | 2 ++ src/saveload/vehicle_sl.cpp | 10 ++++++++++ src/vehicle.cpp | 4 ++-- src/vehicle_func.h | 2 +- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index 98f03f9679..a2a97a279f 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -345,12 +345,13 @@ static bool DisasterTick_Ufo(DisasterVehicle *v) } n = RandomRange(n); // Choose one of them. - for (const RoadVehicle *u : RoadVehicle::Iterate()) { + for (RoadVehicle *u : RoadVehicle::Iterate()) { /* Find (n+1)-th road vehicle. */ if (u->IsFrontEngine() && (n-- == 0)) { /* Target it. */ v->dest_tile = u->index; v->age = 0; + u->disaster_vehicle = v->index; break; } } @@ -379,6 +380,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v) v->age++; if (u->crashed_ctr == 0) { u->Crash(); + u->disaster_vehicle = INVALID_VEHICLE; AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NT_ACCIDENT, u->tile); @@ -970,20 +972,20 @@ void ReleaseDisastersTargetingIndustry(IndustryID i) * Notify disasters that we are about to delete a vehicle. So make them head elsewhere. * @param vehicle deleted vehicle */ -void ReleaseDisastersTargetingVehicle(VehicleID vehicle) +void ReleaseDisasterVehicle(VehicleID vehicle) { - for (DisasterVehicle *v : DisasterVehicle::Iterate()) { - /* primary disaster vehicles that have chosen target */ - if (v->subtype == ST_SMALL_UFO) { - if (v->state != 0 && v->dest_tile == vehicle) { - /* Revert to target-searching */ - v->state = 0; - v->dest_tile = RandomTile(); - GetAircraftFlightLevelBounds(v, &v->z_pos, nullptr); - v->age = 0; - } - } - } + DisasterVehicle *v = DisasterVehicle::GetIfValid(vehicle); + if (v == nullptr) return; + + /* primary disaster vehicles that have chosen target */ + assert(v->subtype == ST_SMALL_UFO); + assert(v->state != 0); + + /* Revert to target-searching */ + v->state = 0; + v->dest_tile = RandomTile(); + GetAircraftFlightLevelBounds(v, &v->z_pos, nullptr); + v->age = 0; } void DisasterVehicle::UpdateDeltaXY() diff --git a/src/roadveh.h b/src/roadveh.h index 3205da5083..19ba64d1d6 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -116,6 +116,8 @@ struct RoadVehicle final : public GroundVehicle { RoadType roadtype; //!< Roadtype of this vehicle. RoadTypes compatible_roadtypes; //!< Roadtypes this consist is powered on. + VehicleID disaster_vehicle = INVALID_VEHICLE; ///< NOSAVE: Disaster vehicle targetting this vehicle. + /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ RoadVehicle() : GroundVehicleBase() {} /** We want to 'destruct' the right class. */ diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 1dbdb53c7d..04ad699284 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -496,6 +496,16 @@ void AfterLoadVehicles(bool part_of_load) UpdateAircraftCache(Aircraft::From(v), true); } break; + + case VEH_DISASTER: { + auto *dv = DisasterVehicle::From(v); + if (dv->subtype == ST_SMALL_UFO && dv->state != 0) { + RoadVehicle *u = RoadVehicle::GetIfValid(v->dest_tile.base()); + if (u != nullptr && u->IsFrontEngine()) u->disaster_vehicle = dv->index; + } + break; + } + default: break; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index d4a50101c9..b1fa59a2d2 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -862,6 +862,8 @@ void Vehicle::PreDestructor() /* Leave the drive through roadstop, when you have not already left it. */ RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v); } + + if (v->disaster_vehicle != INVALID_VEHICLE) ReleaseDisasterVehicle(v->disaster_vehicle); } if (this->Previous() == nullptr) { @@ -884,8 +886,6 @@ void Vehicle::PreDestructor() DeleteDepotHighlightOfVehicle(this); StopGlobalFollowVehicle(this); - - ReleaseDisastersTargetingVehicle(this->index); } Vehicle::~Vehicle() diff --git a/src/vehicle_func.h b/src/vehicle_func.h index f2d67227d5..e426391b7d 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -168,7 +168,7 @@ bool CanVehicleUseStation(EngineID engine_type, const struct Station *st); bool CanVehicleUseStation(const Vehicle *v, const struct Station *st); StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st); -void ReleaseDisastersTargetingVehicle(VehicleID vehicle); +void ReleaseDisasterVehicle(VehicleID vehicle); typedef std::vector VehicleSet; void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles);