mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-04 06:00:15 +00:00
Adjust various water region types
This commit is contained in:
parent
45205a4284
commit
c2e1dfcfc1
@ -19,6 +19,8 @@
|
||||
#include "follow_track.hpp"
|
||||
#include "ship.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
using TWaterRegionTraversabilityBits = uint16_t;
|
||||
constexpr TWaterRegionPatchLabel FIRST_REGION_LABEL = 1;
|
||||
constexpr TWaterRegionPatchLabel INVALID_WATER_REGION_PATCH = 0;
|
||||
@ -28,13 +30,13 @@ static_assert(sizeof(TWaterRegionTraversabilityBits) * 8 == WATER_REGION_EDGE_LE
|
||||
static inline TrackBits GetWaterTracks(TileIndex tile) { return TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)); }
|
||||
static inline bool IsAqueductTile(TileIndex tile) { return IsBridgeTile(tile) && GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER; }
|
||||
|
||||
static inline int GetWaterRegionX(TileIndex tile) { return TileX(tile) / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline int GetWaterRegionY(TileIndex tile) { return TileY(tile) / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline uint32_t GetWaterRegionX(TileIndex tile) { return TileX(tile) / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline uint32_t GetWaterRegionY(TileIndex tile) { return TileY(tile) / WATER_REGION_EDGE_LENGTH; }
|
||||
|
||||
static inline int GetWaterRegionMapSizeX() { return MapSizeX() / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline int GetWaterRegionMapSizeY() { return MapSizeY() / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline uint32_t GetWaterRegionMapSizeX() { return MapSizeX() / WATER_REGION_EDGE_LENGTH; }
|
||||
static inline uint32_t GetWaterRegionMapSizeY() { return MapSizeY() / WATER_REGION_EDGE_LENGTH; }
|
||||
|
||||
static inline TWaterRegionIndex GetWaterRegionIndex(int region_x, int region_y) { return GetWaterRegionMapSizeX() * region_y + region_x; }
|
||||
static inline TWaterRegionIndex GetWaterRegionIndex(uint32_t region_x, uint32_t region_y) { return GetWaterRegionMapSizeX() * region_y + region_x; }
|
||||
static inline TWaterRegionIndex GetWaterRegionIndex(TileIndex tile) { return GetWaterRegionIndex(GetWaterRegionX(tile), GetWaterRegionY(tile)); }
|
||||
|
||||
/**
|
||||
@ -66,7 +68,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
WaterRegion(int region_x, int region_y)
|
||||
WaterRegion(uint32_t region_x, uint32_t region_y)
|
||||
: tile_area(TileXY(region_x * WATER_REGION_EDGE_LENGTH, region_y * WATER_REGION_EDGE_LENGTH), WATER_REGION_EDGE_LENGTH, WATER_REGION_EDGE_LENGTH)
|
||||
{}
|
||||
|
||||
@ -168,9 +170,9 @@ public:
|
||||
/* Calculate the traversability (whether the tile can be entered / exited) for all edges. Note that
|
||||
* we always follow the same X and Y scanning direction, this is important for comparisons later on! */
|
||||
this->edge_traversability_bits.fill(0);
|
||||
const int top_x = TileX(tile_area.tile);
|
||||
const int top_y = TileY(tile_area.tile);
|
||||
for (int i = 0; i < WATER_REGION_EDGE_LENGTH; ++i) {
|
||||
const uint32_t top_x = TileX(tile_area.tile);
|
||||
const uint32_t top_y = TileY(tile_area.tile);
|
||||
for (uint32_t i = 0; i < WATER_REGION_EDGE_LENGTH; ++i) {
|
||||
if (GetWaterTracks(TileXY(top_x + i, top_y)) & TRACK_BIT_3WAY_NW) SetBit(this->edge_traversability_bits[DIAGDIR_NW], i); // NW edge
|
||||
if (GetWaterTracks(TileXY(top_x + i, top_y + WATER_REGION_EDGE_LENGTH - 1)) & TRACK_BIT_3WAY_SE) SetBit(this->edge_traversability_bits[DIAGDIR_SE], i); // SE edge
|
||||
if (GetWaterTracks(TileXY(top_x, top_y + i)) & TRACK_BIT_3WAY_NE) SetBit(this->edge_traversability_bits[DIAGDIR_NE], i); // NE edge
|
||||
@ -189,16 +191,16 @@ public:
|
||||
|
||||
std::vector<WaterRegion> _water_regions;
|
||||
|
||||
TileIndex GetTileIndexFromLocalCoordinate(int region_x, int region_y, int local_x, int local_y)
|
||||
TileIndex GetTileIndexFromLocalCoordinate(uint32_t region_x, uint32_t region_y, uint32_t local_x, uint32_t local_y)
|
||||
{
|
||||
assert(local_x >= 0 && local_y < WATER_REGION_EDGE_LENGTH);
|
||||
assert(local_y >= 0 && local_y < WATER_REGION_EDGE_LENGTH);
|
||||
assert(local_x < WATER_REGION_EDGE_LENGTH);
|
||||
assert(local_y < WATER_REGION_EDGE_LENGTH);
|
||||
return TileXY(WATER_REGION_EDGE_LENGTH * region_x + local_x, WATER_REGION_EDGE_LENGTH * region_y + local_y);
|
||||
}
|
||||
|
||||
TileIndex GetEdgeTileCoordinate(int region_x, int region_y, DiagDirection side, int x_or_y)
|
||||
TileIndex GetEdgeTileCoordinate(uint32_t region_x, uint32_t region_y, DiagDirection side, uint32_t x_or_y)
|
||||
{
|
||||
assert(x_or_y >= 0 && x_or_y < WATER_REGION_EDGE_LENGTH);
|
||||
assert(x_or_y < WATER_REGION_EDGE_LENGTH);
|
||||
switch (side) {
|
||||
case DIAGDIR_NE: return GetTileIndexFromLocalCoordinate(region_x, region_y, 0, x_or_y);
|
||||
case DIAGDIR_SW: return GetTileIndexFromLocalCoordinate(region_x, region_y, WATER_REGION_EDGE_LENGTH - 1, x_or_y);
|
||||
@ -208,7 +210,7 @@ TileIndex GetEdgeTileCoordinate(int region_x, int region_y, DiagDirection side,
|
||||
}
|
||||
}
|
||||
|
||||
WaterRegion &GetUpdatedWaterRegion(uint16_t region_x, uint16_t region_y)
|
||||
WaterRegion &GetUpdatedWaterRegion(uint32_t region_x, uint32_t region_y)
|
||||
{
|
||||
WaterRegion &result = _water_regions[GetWaterRegionIndex(region_x, region_y)];
|
||||
result.UpdateIfNotInitialized();
|
||||
@ -266,8 +268,8 @@ WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
|
||||
*/
|
||||
void InvalidateWaterRegion(TileIndex tile)
|
||||
{
|
||||
const int index = GetWaterRegionIndex(tile);
|
||||
if (index > static_cast<int>(_water_regions.size())) return;
|
||||
const uint32_t index = GetWaterRegionIndex(tile);
|
||||
if (index > static_cast<uint32_t>(_water_regions.size())) return;
|
||||
_water_regions[index].Invalidate();
|
||||
}
|
||||
|
||||
@ -283,10 +285,11 @@ static inline void VisitAdjacentWaterRegionPatchNeighbors(const WaterRegionPatch
|
||||
const WaterRegion ¤t_region = GetUpdatedWaterRegion(water_region_patch.x, water_region_patch.y);
|
||||
|
||||
const TileIndexDiffC offset = TileIndexDiffCByDiagDir(side);
|
||||
const int nx = water_region_patch.x + offset.x;
|
||||
const int ny = water_region_patch.y + offset.y;
|
||||
/* Unsigned underflow is allowed here, not UB */
|
||||
const uint32_t nx = water_region_patch.x + (uint32_t)offset.x;
|
||||
const uint32_t ny = water_region_patch.y + (uint32_t)offset.y;
|
||||
|
||||
if (nx < 0 || ny < 0 || nx >= GetWaterRegionMapSizeX() || ny >= GetWaterRegionMapSizeY()) return;
|
||||
if (nx >= GetWaterRegionMapSizeX() || ny >= GetWaterRegionMapSizeY()) return;
|
||||
|
||||
const WaterRegion &neighboring_region = GetUpdatedWaterRegion(nx, ny);
|
||||
const DiagDirection opposite_side = ReverseDiagDir(side);
|
||||
@ -304,7 +307,7 @@ static inline void VisitAdjacentWaterRegionPatchNeighbors(const WaterRegionPatch
|
||||
/* Multiple water patches can be reached from the current patch. Check each edge tile individually. */
|
||||
static std::vector<TWaterRegionPatchLabel> unique_labels; // static and vector-instead-of-map for performance reasons
|
||||
unique_labels.clear();
|
||||
for (int x_or_y = 0; x_or_y < WATER_REGION_EDGE_LENGTH; ++x_or_y) {
|
||||
for (uint32_t x_or_y = 0; x_or_y < WATER_REGION_EDGE_LENGTH; ++x_or_y) {
|
||||
if (!HasBit(traversability_bits, x_or_y)) continue;
|
||||
|
||||
const TileIndex current_edge_tile = GetEdgeTileCoordinate(water_region_patch.x, water_region_patch.y, side, x_or_y);
|
||||
@ -355,8 +358,8 @@ void LoadWaterRegions(const std::vector<WaterRegionSaveLoadInfo> &save_load_info
|
||||
_water_regions.reserve(save_load_info.size());
|
||||
TWaterRegionIndex index = 0;
|
||||
for (const auto &loaded_region_info : save_load_info) {
|
||||
const int region_x = index % GetWaterRegionMapSizeX();
|
||||
const int region_y = index / GetWaterRegionMapSizeX();
|
||||
const uint32_t region_x = index % GetWaterRegionMapSizeX();
|
||||
const uint32_t region_y = index / GetWaterRegionMapSizeX();
|
||||
WaterRegion ®ion = _water_regions.emplace_back(region_x, region_y);
|
||||
if (loaded_region_info.initialized) region.ForceUpdate();
|
||||
index++;
|
||||
@ -371,8 +374,8 @@ void InitializeWaterRegions()
|
||||
_water_regions.clear();
|
||||
_water_regions.reserve(static_cast<size_t>(GetWaterRegionMapSizeX()) * GetWaterRegionMapSizeY());
|
||||
|
||||
for (int region_y = 0; region_y < GetWaterRegionMapSizeY(); region_y++) {
|
||||
for (int region_x = 0; region_x < GetWaterRegionMapSizeX(); region_x++) {
|
||||
for (uint32_t region_y = 0; region_y < GetWaterRegionMapSizeY(); region_y++) {
|
||||
for (uint32_t region_x = 0; region_x < GetWaterRegionMapSizeX(); region_x++) {
|
||||
_water_regions.emplace_back(region_x, region_y).ForceUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -13,19 +13,22 @@
|
||||
#include "tile_type.h"
|
||||
#include "map_func.h"
|
||||
|
||||
using TWaterRegionPatchLabel = uint8_t;
|
||||
using TWaterRegionIndex = uint;
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
constexpr int WATER_REGION_EDGE_LENGTH = 16;
|
||||
constexpr int WATER_REGION_NUMBER_OF_TILES = WATER_REGION_EDGE_LENGTH * WATER_REGION_EDGE_LENGTH;
|
||||
using TWaterRegionPatchLabel = uint8_t;
|
||||
using TWaterRegionIndex = uint32_t;
|
||||
|
||||
constexpr uint32_t WATER_REGION_EDGE_LENGTH = 16;
|
||||
constexpr uint32_t WATER_REGION_NUMBER_OF_TILES = WATER_REGION_EDGE_LENGTH * WATER_REGION_EDGE_LENGTH;
|
||||
|
||||
/**
|
||||
* Describes a single interconnected patch of water within a particular water region.
|
||||
*/
|
||||
struct WaterRegionPatchDesc
|
||||
{
|
||||
int x; ///< The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis
|
||||
int y; ///< The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis
|
||||
uint32_t x; ///< The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis
|
||||
uint32_t y; ///< The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis
|
||||
TWaterRegionPatchLabel label; ///< Unique label identifying the patch within the region
|
||||
|
||||
bool operator==(const WaterRegionPatchDesc &other) const { return x == other.x && y == other.y && label == other.label; }
|
||||
@ -38,10 +41,10 @@ struct WaterRegionPatchDesc
|
||||
*/
|
||||
struct WaterRegionDesc
|
||||
{
|
||||
int x; ///< The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis
|
||||
int y; ///< The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis
|
||||
uint32_t x; ///< The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis
|
||||
uint32_t y; ///< The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis
|
||||
|
||||
WaterRegionDesc(const int x, const int y) : x(x), y(y) {}
|
||||
WaterRegionDesc(const uint32_t x, const uint32_t y) : x(x), y(y) {}
|
||||
WaterRegionDesc(const WaterRegionPatchDesc &water_region_patch) : x(water_region_patch.x), y(water_region_patch.y) {}
|
||||
|
||||
bool operator==(const WaterRegionDesc &other) const { return x == other.x && y == other.y; }
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../ship.h"
|
||||
#include "../../core/math_func.hpp"
|
||||
|
||||
#include "yapf.hpp"
|
||||
#include "yapf_ship_regions.h"
|
||||
@ -18,7 +19,7 @@
|
||||
|
||||
constexpr int DIRECT_NEIGHBOR_COST = 100;
|
||||
constexpr int NODES_PER_REGION = 4;
|
||||
constexpr int MAX_NUMBER_OF_NODES = 65536;
|
||||
constexpr uint32_t MAX_NUMBER_OF_NODES = 65536;
|
||||
|
||||
/** Yapf Node Key that represents a single patch of interconnected water within a water region. */
|
||||
struct CYapfRegionPatchNodeKey {
|
||||
@ -37,7 +38,7 @@ struct CYapfRegionPatchNodeKey {
|
||||
|
||||
inline uint ManhattanDistance(const CYapfRegionPatchNodeKey &a, const CYapfRegionPatchNodeKey &b)
|
||||
{
|
||||
return (std::abs(a.m_water_region_patch.x - b.m_water_region_patch.x) + std::abs(a.m_water_region_patch.y - b.m_water_region_patch.y)) * DIRECT_NEIGHBOR_COST;
|
||||
return (Delta(a.m_water_region_patch.x, b.m_water_region_patch.x) + Delta(a.m_water_region_patch.y, b.m_water_region_patch.y)) * DIRECT_NEIGHBOR_COST;
|
||||
}
|
||||
|
||||
/** Yapf Node for water regions. */
|
||||
@ -195,7 +196,7 @@ public:
|
||||
|
||||
/* We reserve 4 nodes (patches) per water region. The vast majority of water regions have 1 or 2 regions so this should be a pretty
|
||||
* safe limit. We cap the limit at 65536 which is at a region size of 16x16 is equivalent to one node per region for a 4096x4096 map. */
|
||||
Tpf pf(std::min(static_cast<int>(MapSize() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES));
|
||||
Tpf pf(std::min(static_cast<uint32_t>(MapSize() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES));
|
||||
pf.SetDestination(start_water_region_patch);
|
||||
|
||||
if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||
|
Loading…
Reference in New Issue
Block a user