Maintain map of targeted road vehicles to small UFO disaster vehicle

This commit is contained in:
Jonathan G Rennison 2024-02-12 00:48:13 +00:00
parent 1e2834a422
commit 903adceab5
6 changed files with 66 additions and 15 deletions

View File

@ -48,6 +48,7 @@
#include "core/backup_type.hpp" #include "core/backup_type.hpp"
#include "core/checksum_func.hpp" #include "core/checksum_func.hpp"
#include "event_logs.h" #include "event_logs.h"
#include "3rdparty/cpp-btree/btree_map.h"
#include "table/strings.h" #include "table/strings.h"
@ -57,6 +58,7 @@
uint16_t _disaster_delay; uint16_t _disaster_delay;
static uint32_t _disaster_vehicle_count = 0; static uint32_t _disaster_vehicle_count = 0;
static btree::btree_map<VehicleID, VehicleID> _disaster_ufo_target_map;
static void DisasterClearSquare(TileIndex tile) static void DisasterClearSquare(TileIndex tile)
{ {
@ -369,6 +371,11 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
for (const RoadVehicle *u : RoadVehicle::Iterate()) { for (const RoadVehicle *u : RoadVehicle::Iterate()) {
/* Find (n+1)-th road vehicle. */ /* Find (n+1)-th road vehicle. */
if (u->IsFrontEngine() && (n-- == 0)) { if (u->IsFrontEngine() && (n-- == 0)) {
if (u->crashed_ctr != 0 || !SetDisasterVehicleTargetingVehicle(u->index, v->index)) {
/* Targetted vehicle is crashed or already a target, destroy the UFO. */
delete v;
return false;
}
/* Target it. */ /* Target it. */
v->dest_tile = u->index; v->dest_tile = u->index;
v->age = 0; v->age = 0;
@ -1010,22 +1017,43 @@ void ReleaseDisastersTargetingIndustry(IndustryID i)
* Notify disasters that we are about to delete a vehicle. So make them head elsewhere. * Notify disasters that we are about to delete a vehicle. So make them head elsewhere.
* @param vehicle deleted vehicle * @param vehicle deleted vehicle
*/ */
void ReleaseDisastersTargetingVehicle(VehicleID vehicle) void ReleaseDisasterVehicleTargetingVehicle(VehicleID vehicle)
{ {
if (!_disaster_vehicle_count) return; if (!_disaster_vehicle_count) return;
for (DisasterVehicle *v : DisasterVehicle::Iterate()) { auto iter = _disaster_ufo_target_map.find(vehicle);
if (iter == _disaster_ufo_target_map.end()) return;
DisasterVehicle *v = DisasterVehicle::GetIfValid(iter->second);
_disaster_ufo_target_map.erase(iter);
if (v == nullptr) return;
/* primary disaster vehicles that have chosen target */ /* primary disaster vehicles that have chosen target */
if (v->subtype == ST_SMALL_UFO) { assert(v->subtype == ST_SMALL_UFO);
if (v->state != 0 && v->dest_tile == vehicle) { assert(v->state != 0);
/* Revert to target-searching */ /* Revert to target-searching */
v->state = 0; v->state = 0;
v->dest_tile = RandomTile(); v->dest_tile = RandomTile();
GetAircraftFlightLevelBounds(v, &v->z_pos, nullptr); GetAircraftFlightLevelBounds(v, &v->z_pos, nullptr);
v->age = 0; v->age = 0;
} }
void ResetDisasterVehicleTargeting()
{
_disaster_ufo_target_map.clear();
} }
bool SetDisasterVehicleTargetingVehicle(VehicleID vehicle, VehicleID disaster_vehicle)
{
auto insert_result = _disaster_ufo_target_map.insert(std::make_pair(vehicle, disaster_vehicle));
if (!insert_result.second) {
/* Vehicle already has an associated disaster vehicle, return failure if that isn't this disaster vehicle */
if (insert_result.first->second != disaster_vehicle) return false;
} }
return true;
} }
void DisasterVehicle::UpdateDeltaXY() void DisasterVehicle::UpdateDeltaXY()

View File

@ -120,6 +120,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
AllocateMap(size_x, size_y); AllocateMap(size_x, size_y);
ViewportMapClearTunnelCache(); ViewportMapClearTunnelCache();
ResetDisasterVehicleTargeting();
ClearCommandLog(); ClearCommandLog();
ClearCommandQueue(); ClearCommandQueue();
ClearSpecialEventsLog(); ClearSpecialEventsLog();

View File

@ -520,6 +520,7 @@ static void ShutdownGame()
InvalidateVehicleTickCaches(); InvalidateVehicleTickCaches();
ClearVehicleTickCaches(); ClearVehicleTickCaches();
InvalidateTemplateReplacementImages(); InvalidateTemplateReplacementImages();
ResetDisasterVehicleTargeting();
ClearCommandLog(); ClearCommandLog();
ClearCommandQueue(); ClearCommandQueue();
ClearSpecialEventsLog(); ClearSpecialEventsLog();

View File

@ -507,6 +507,8 @@ void AfterLoadVehicles(bool part_of_load)
} }
} }
ResetDisasterVehicleTargeting();
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::Iterate()) {
si_v = v; si_v = v;
switch (v->type) { switch (v->type) {
@ -539,6 +541,22 @@ void AfterLoadVehicles(bool part_of_load)
UpdateAircraftCache(Aircraft::From(v), true); UpdateAircraftCache(Aircraft::From(v), true);
} }
break; 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);
if (u != nullptr && u->IsFrontEngine()) {
/* Delete UFO targeting a vehicle which is already a target. */
if (!SetDisasterVehicleTargetingVehicle(u->index, dv->index)) {
delete v;
continue;
}
}
}
break;
}
default: break; default: break;
} }

View File

@ -1030,6 +1030,7 @@ void InitializeVehicles()
{ {
_vehicles_to_autoreplace.clear(); _vehicles_to_autoreplace.clear();
ResetVehicleHash(); ResetVehicleHash();
ResetDisasterVehicleTargeting();
} }
uint CountVehiclesInChain(const Vehicle *v) uint CountVehiclesInChain(const Vehicle *v)
@ -1202,6 +1203,8 @@ void Vehicle::PreDestructor()
/* Leave the drive through roadstop, when you have not already left it. */ /* Leave the drive through roadstop, when you have not already left it. */
RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v); RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
} }
ReleaseDisasterVehicleTargetingVehicle(this->index);
} }
if (HasBit(this->vehicle_flags, VF_HAVE_SLOT)) { if (HasBit(this->vehicle_flags, VF_HAVE_SLOT)) {
@ -1238,8 +1241,6 @@ void Vehicle::PreDestructor()
StopGlobalFollowVehicle(this); StopGlobalFollowVehicle(this);
ReleaseDisastersTargetingVehicle(this->index);
/* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles, /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
* it may happen that vehicle chain is deleted when visible */ * it may happen that vehicle chain is deleted when visible */
if (this->IsDrawn()) this->MarkAllViewportsDirty(); if (this->IsDrawn()) this->MarkAllViewportsDirty();

View File

@ -258,7 +258,9 @@ bool CanVehicleUseStation(EngineID engine_type, const struct Station *st);
bool CanVehicleUseStation(const Vehicle *v, const struct Station *st); bool CanVehicleUseStation(const Vehicle *v, const struct Station *st);
StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st); StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st);
void ReleaseDisastersTargetingVehicle(VehicleID vehicle); void ResetDisasterVehicleTargeting();
void ReleaseDisasterVehicleTargetingVehicle(VehicleID vehicle);
bool SetDisasterVehicleTargetingVehicle(VehicleID vehicle, VehicleID disaster_vehicle);
typedef std::vector<VehicleID> VehicleSet; typedef std::vector<VehicleID> VehicleSet;
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles); void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles);