From 3a70d1e2f78ca7146aaf7287291d1166ccbc3d29 Mon Sep 17 00:00:00 2001
From: frosch <frosch@openttd.org>
Date: Sat, 26 Apr 2025 15:23:14 +0200
Subject: [PATCH] Codechange: Pass the max-distance as parameter to
 VehiclesNearTileXY.

---
 src/roadveh_cmd.cpp |  4 ++--
 src/train_cmd.cpp   |  2 +-
 src/vehicle.cpp     | 29 ++++++++++++++++++-----------
 src/vehicle_func.h  |  8 ++++----
 4 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index fe8ccf1adf..4f6761e144 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -553,7 +553,7 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v)
 
 		if (!IsLevelCrossingTile(tile)) continue;
 
-		if (HasVehicleNearTileXY(v->x_pos, v->y_pos, [&u](const Vehicle *t) {
+		if (HasVehicleNearTileXY(v->x_pos, v->y_pos, 6, [&u](const Vehicle *t) {
 				return t->type == VEH_TRAIN && abs(t->z_pos - u->z_pos) <= 6 &&
 					abs(t->x_pos - u->x_pos) <= 4 && abs(t->y_pos - u->y_pos) <= 4;
 			})) {
@@ -649,7 +649,7 @@ static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction d
 			FindClosestBlockingRoadVeh(u, &rvf);
 		}
 	} else {
-		for (Vehicle *u : VehiclesNearTileXY(x, y)) {
+		for (Vehicle *u : VehiclesNearTileXY(x, y, 6)) {
 			FindClosestBlockingRoadVeh(u, &rvf);
 		}
 	}
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 765e084ba8..039a2a174d 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -3228,7 +3228,7 @@ static bool CheckTrainCollision(Train *v)
 			num_victims += CheckTrainCollision(u, v);
 		}
 	} else {
-		for (Vehicle *u : VehiclesNearTileXY(v->x_pos, v->y_pos)) {
+		for (Vehicle *u : VehiclesNearTileXY(v->x_pos, v->y_pos, 6)) {
 			num_victims += CheckTrainCollision(u, v);
 		}
 	}
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 50baa5f9d8..0d4fef53c7 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -429,20 +429,27 @@ static std::array<Vehicle *, TOTAL_TILE_HASH_SIZE> _vehicle_tile_hash{};
  * Iterator constructor.
  * Find first vehicle near (x, y).
  */
-VehiclesNearTileXY::Iterator::Iterator(int32_t x, int32_t y)
+VehiclesNearTileXY::Iterator::Iterator(int32_t x, int32_t y, uint max_dist)
 {
-	const int COLL_DIST = 6;
 	/* There are no negative tile coordinates */
-	pos_rect.left = std::max<int>(0, x - COLL_DIST);
-	pos_rect.right = std::max<int>(0, x + COLL_DIST);
-	pos_rect.top = std::max<int>(0, y - COLL_DIST);
-	pos_rect.bottom = std::max<int>(0, y + COLL_DIST);
+	pos_rect.left = std::max<int>(0, x - max_dist);
+	pos_rect.right = std::max<int>(0, x + max_dist);
+	pos_rect.top = std::max<int>(0, y - max_dist);
+	pos_rect.bottom = std::max<int>(0, y + max_dist);
 
-	/* Hash area to scan */
-	this->hxmin = this->hx = GetTileHash1D(pos_rect.left / TILE_SIZE);
-	this->hxmax = GetTileHash1D(pos_rect.right / TILE_SIZE);
-	this->hymin = this->hy = GetTileHash1D(pos_rect.top / TILE_SIZE);
-	this->hymax = GetTileHash1D(pos_rect.bottom / TILE_SIZE);
+	if (2 * max_dist < TILE_HASH_MASK * TILE_SIZE) {
+		/* Hash area to scan */
+		this->hxmin = this->hx = GetTileHash1D(pos_rect.left / TILE_SIZE);
+		this->hxmax = GetTileHash1D(pos_rect.right / TILE_SIZE);
+		this->hymin = this->hy = GetTileHash1D(pos_rect.top / TILE_SIZE);
+		this->hymax = GetTileHash1D(pos_rect.bottom / TILE_SIZE);
+	} else {
+		/* Scan all */
+		this->hxmin = this->hx = 0;
+		this->hxmax = TILE_HASH_MASK;
+		this->hymin = this->hy = 0;
+		this->hymax = TILE_HASH_MASK;
+	}
 
 	this->current_veh = _vehicle_tile_hash[ComposeTileHash(this->hx, this->hy)];
 	this->SkipEmptyBuckets();
diff --git a/src/vehicle_func.h b/src/vehicle_func.h
index 9c882ac08f..f1aadce4d8 100644
--- a/src/vehicle_func.h
+++ b/src/vehicle_func.h
@@ -129,7 +129,7 @@ public:
 		using pointer = void;
 		using reference = void;
 
-		explicit Iterator(int32_t x, int32_t y);
+		explicit Iterator(int32_t x, int32_t y, uint max_dist);
 
 		bool operator==(const Iterator &rhs) const { return this->current_veh == rhs.current_veh; }
 		bool operator==(const std::default_sentinel_t &) const { return this->current_veh == nullptr; }
@@ -160,7 +160,7 @@ public:
 		void SkipFalseMatches();
 	};
 
-	explicit VehiclesNearTileXY(int32_t x, int32_t y) : start(x, y) {}
+	explicit VehiclesNearTileXY(int32_t x, int32_t y, uint max_dist) : start(x, y, max_dist) {}
 	Iterator begin() const { return this->start; }
 	std::default_sentinel_t end() const { return std::default_sentinel_t(); }
 private:
@@ -173,9 +173,9 @@ private:
  * @warning This only works for vehicles with proper Vehicle::Tile, so only ground vehicles outside wormholes.
  */
 template <class UnaryPred>
-bool HasVehicleNearTileXY(int32_t x, int32_t y, UnaryPred &&predicate)
+bool HasVehicleNearTileXY(int32_t x, int32_t y, uint max_dist, UnaryPred &&predicate)
 {
-	for (const auto *v : VehiclesNearTileXY(x, y)) {
+	for (const auto *v : VehiclesNearTileXY(x, y, max_dist)) {
 		if (predicate(v)) return true;
 	}
 	return false;