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_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(0, x - COLL_DIST); - pos_rect.right = std::max(0, x + COLL_DIST); - pos_rect.top = std::max(0, y - COLL_DIST); - pos_rect.bottom = std::max(0, y + COLL_DIST); + pos_rect.left = std::max(0, x - max_dist); + pos_rect.right = std::max(0, x + max_dist); + pos_rect.top = std::max(0, y - max_dist); + pos_rect.bottom = std::max(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 -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;