Changeset - r28742:e80d6a5b649a
[Not reviewed]
master
0 5 0
Peter Nelson - 3 months ago 2024-02-11 23:04:29
peter1138@openttd.org
Codechange: Don't scan vehicle pool to find targeting disaster vehicle when deleting any vehicle. (#12064)

* 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.

* Change: Small UFOs no longer target a vehicle which is already a target.
5 files changed with 44 insertions and 17 deletions:
0 comments (0 inline, 0 general)
src/disaster_vehicle.cpp
Show inline comments
 
@@ -342,18 +342,24 @@ static bool DisasterTick_Ufo(DisasterVeh
 
			/* If there are no targetable road vehicles, destroy the UFO. */
 
			delete v;
 
			return false;
 
		}
 

	
 
		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)) {
 
				if (u->crashed_ctr != 0 || u->disaster_vehicle != INVALID_VEHICLE) {
 
					/* Targetted vehicle is crashed or already a target, destroy the UFO. */
 
					delete v;
 
					return false;
 
				}
 
				/* Target it. */
 
				v->dest_tile = u->index;
 
				v->age = 0;
 
				u->disaster_vehicle = v->index;
 
				break;
 
			}
 
		}
 

	
 
		return true;
 
	} else {
 
@@ -376,12 +382,13 @@ static bool DisasterTick_Ufo(DisasterVeh
 
		v->UpdatePosition(gp.x, gp.y, z);
 

	
 
		if (z <= u->z_pos && (u->vehstatus & VS_HIDDEN) == 0) {
 
			v->age++;
 
			if (u->crashed_ctr == 0) {
 
				u->Crash();
 
				u->disaster_vehicle = INVALID_VEHICLE;
 

	
 
				AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NT_ACCIDENT, u->tile);
 

	
 
				AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
 
				Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
 
			}
 
@@ -967,26 +974,26 @@ void ReleaseDisastersTargetingIndustry(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()
 
{
 
	this->x_offs        = -1;
 
	this->y_offs        = -1;
src/roadveh.h
Show inline comments
 
@@ -113,12 +113,14 @@ struct RoadVehicle final : public Ground
 
	uint16_t crashed_ctr;     ///< Animation counter when the vehicle has crashed. @see RoadVehIsCrashed
 
	byte reverse_ctr;
 

	
 
	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. */
 
	virtual ~RoadVehicle() { this->PreDestructor(); }
 

	
 
	friend struct GroundVehicle<RoadVehicle, VEH_ROAD>; // GroundVehicle needs to use the acceleration functions defined at RoadVehicle.
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -493,12 +493,30 @@ void AfterLoadVehicles(bool part_of_load
 
						GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_cache.sprite_seq);
 
					}
 

	
 
					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()) {
 
						/* Delete UFO targetting a vehicle which is already a target. */
 
						if (u->disaster_vehicle != INVALID_VEHICLE) {
 
							delete v;
 
							continue;
 
						} else {
 
							u->disaster_vehicle = dv->index;
 
						}
 
					}
 
				}
 
				break;
 
			}
 

	
 
			default: break;
 
		}
 

	
 
		v->UpdateDeltaXY();
 
		v->coord.left = INVALID_COORD;
 
		v->sprite_cache.old_coord.left = INVALID_COORD;
src/vehicle.cpp
Show inline comments
 
@@ -859,12 +859,14 @@ void Vehicle::PreDestructor()
 
	if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
 
		RoadVehicle *v = RoadVehicle::From(this);
 
		if (!(v->vehstatus & VS_CRASHED) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
 
			/* 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) {
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
 
	}
 

	
 
@@ -881,14 +883,12 @@ void Vehicle::PreDestructor()
 

	
 
	this->cargo.Truncate();
 
	DeleteVehicleOrders(this);
 
	DeleteDepotHighlightOfVehicle(this);
 

	
 
	StopGlobalFollowVehicle(this);
 

	
 
	ReleaseDisastersTargetingVehicle(this->index);
 
}
 

	
 
Vehicle::~Vehicle()
 
{
 
	if (CleaningPool()) {
 
		this->cargo.OnCleanPool();
src/vehicle_func.h
Show inline comments
 
@@ -165,13 +165,13 @@ CommandCost EnsureNoVehicleOnGround(Tile
 
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits);
 

	
 
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<VehicleID> VehicleSet;
 
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles);
 

	
 
void CheckCargoCapacity(Vehicle *v);
 

	
0 comments (0 inline, 0 general)