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/checksum_func.hpp"
#include "event_logs.h"
#include "3rdparty/cpp-btree/btree_map.h"
#include "table/strings.h"
@ -57,6 +58,7 @@
uint16_t _disaster_delay;
static uint32_t _disaster_vehicle_count = 0;
static btree::btree_map<VehicleID, VehicleID> _disaster_ufo_target_map;
static void DisasterClearSquare(TileIndex tile)
{
@ -369,6 +371,11 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
for (const RoadVehicle *u : RoadVehicle::Iterate()) {
/* Find (n+1)-th road vehicle. */
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. */
v->dest_tile = u->index;
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.
* @param vehicle deleted vehicle
*/
void ReleaseDisastersTargetingVehicle(VehicleID vehicle)
void ReleaseDisasterVehicleTargetingVehicle(VehicleID vehicle)
{
if (!_disaster_vehicle_count) return;
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;
}
}
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 */
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 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()

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);
ViewportMapClearTunnelCache();
ResetDisasterVehicleTargeting();
ClearCommandLog();
ClearCommandQueue();
ClearSpecialEventsLog();

View File

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

View File

@ -507,6 +507,8 @@ void AfterLoadVehicles(bool part_of_load)
}
}
ResetDisasterVehicleTargeting();
for (Vehicle *v : Vehicle::Iterate()) {
si_v = v;
switch (v->type) {
@ -539,6 +541,22 @@ 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);
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;
}

View File

@ -1030,6 +1030,7 @@ void InitializeVehicles()
{
_vehicles_to_autoreplace.clear();
ResetVehicleHash();
ResetDisasterVehicleTargeting();
}
uint CountVehiclesInChain(const Vehicle *v)
@ -1202,6 +1203,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);
}
ReleaseDisasterVehicleTargetingVehicle(this->index);
}
if (HasBit(this->vehicle_flags, VF_HAVE_SLOT)) {
@ -1238,8 +1241,6 @@ void Vehicle::PreDestructor()
StopGlobalFollowVehicle(this);
ReleaseDisastersTargetingVehicle(this->index);
/* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
* it may happen that vehicle chain is deleted when visible */
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);
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;
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles);