Add map bit to suppress water flooding checks

Set if all neighbour tiles are also water
This reduces the overhead of flood checks on large maps
pull/221/head
Jonathan G Rennison 3 years ago
parent 0df3e785cb
commit f595696e97

@ -1054,6 +1054,7 @@
<li>m1 bits 6..5 : Water class (sea, canal or river)
<li>m1 bits 4..0: <a href="#OwnershipInfo">owner</a> (for sea, rivers, and coasts normally <tt>11</tt>)</li>
<li>m2: Depot index (for depots only)</li>
<li style="color: blue">m3 bit 0: No flooding state, set if all neighbouring tiles are also water</li>
<li>m4: Random data for canal or river tiles</li>
<li>m5: tile type:
<table>

@ -241,7 +241,7 @@ the array so you can quickly see what is used and what is not.
<td class="caption">sea, shore</td>
<td class="bits" rowspan=4><span class="used" title="Ship docking tile status">X</span> <span class="used" title="Water class">XX</span> <span class="used" title="Owner">XXXXX</span></td>
<td class="bits" rowspan=3><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits" rowspan=4><span class="free">OOOO OOOO</span></td>
<td class="bits" rowspan=4><span class="free">OOOO OOO</span><span class="patch" title="No flooding state">P</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="used" title="Water tile type: coast, clear, lock, depot">O<span class="usable">OO</span>O</span> <span class="free">OOO</span><span class="used" title="Sea shore flag">X</span></td>
<td class="bits" rowspan=4><span class="free">OOOO OOOO</span></td>

@ -146,6 +146,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr },
{ XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 1, 1, "realistic_train_braking", nullptr, nullptr, "VLKA" },
{ XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr },
{ XSLFI_WATER_FLOODING, XSCF_NULL, 1, 1, "water_flooding", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
};

@ -100,6 +100,7 @@ enum SlXvFeatureIndex {
XSLFI_INDUSTRY_CARGO_ADJ, ///< Industry cargo adjustment patch
XSLFI_REALISTIC_TRAIN_BRAKING, ///< Realistic train braking
XSLFI_INFLATION_FIXED_DATES, ///< Inflation is applied between fixed dates
XSLFI_WATER_FLOODING, ///< Water flooding map bit
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

@ -88,6 +88,13 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
}
}
static void ClearNeighbourNonFloodingStates(TileIndex tile)
{
for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
TileIndex dest = tile + TileOffsByDir(dir);
if (IsValidTile(dest) && IsTileType(dest, MP_WATER)) SetNonFloodingWaterTile(dest, false);
}
}
/**
* Build a ship depot.
@ -400,6 +407,7 @@ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
MakeRiver(tile, Random());
} else {
DoClearSquare(tile);
ClearNeighbourNonFloodingStates(tile);
}
MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
@ -570,6 +578,7 @@ static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
DoClearSquare(tile);
MarkCanalsAndRiversAroundDirty(tile);
if (remove) RemoveDockingTile(tile);
ClearNeighbourNonFloodingStates(tile);
}
return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
@ -593,6 +602,7 @@ static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
DoClearSquare(tile);
MarkCanalsAndRiversAroundDirty(tile);
if (remove) RemoveDockingTile(tile);
ClearNeighbourNonFloodingStates(tile);
}
return ret;
}
@ -1248,14 +1258,19 @@ void TileLoop_Water(TileIndex tile)
{
if (IsTileType(tile, MP_WATER)) AmbientSoundEffect(tile);
if (IsNonFloodingWaterTile(tile)) return;
switch (GetFloodingBehaviour(tile)) {
case FLOOD_ACTIVE:
case FLOOD_ACTIVE: {
int non_water_neighbours = 0;
for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
TileIndex dest = tile + TileOffsByDir(dir);
if (!IsValidTile(dest)) continue;
/* do not try to flood water tiles - increases performance a lot */
if (IsTileType(dest, MP_WATER)) continue;
non_water_neighbours++;
/* TREE_GROUND_SHORE is the sign of a previous flood. */
if (IsTileType(dest, MP_TREES) && GetTreeGround(dest) == TREE_GROUND_SHORE) continue;
@ -1267,7 +1282,9 @@ void TileLoop_Water(TileIndex tile)
DoFloodTile(dest);
}
if (non_water_neighbours == 0 && IsTileType(tile, MP_WATER)) SetNonFloodingWaterTile(tile, true);
break;
}
case FLOOD_DRYUP: {
Slope slope_here = GetFoundationSlope(tile) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;

@ -504,4 +504,24 @@ static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc
MakeLockTile(t + delta, IsWaterTile(t + delta) ? GetTileOwner(t + delta) : o, LOCK_PART_UPPER, d, wc_upper);
}
/**
* Set the non-flooding water tile state of a tile.
* @param t the tile
* @param b the non-flooding water tile state
*/
static inline void SetNonFloodingWaterTile(TileIndex t, bool b)
{
assert(IsTileType(t, MP_WATER));
SB(_m[t].m3, 0, 1, b ? 1 : 0);
}
/**
* Checks whether the tile is marked as a non-flooding water tile.
* @return true iff the tile is marked as a non-flooding water tile.
*/
static inline bool IsNonFloodingWaterTile(TileIndex t)
{
return IsTileType(t, MP_WATER) && HasBit(_m[t].m3, 0);
}
#endif /* WATER_MAP_H */

Loading…
Cancel
Save