mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 06:15:04 +00:00
Change: Store water tile flooding state in the map.
This allows water tiles which cannot flood any further to not even try to flood. On a large map with lots of water tiles this can noticeably reduce game loop processing time. Mostly ported from JGRPP.
This commit is contained in:
parent
4cd46e54aa
commit
8f9836793f
@ -98,6 +98,12 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span style="font-weight: bold;">m3:</span><br>
|
||||
<ul>
|
||||
<li>
|
||||
Bit 0: Non-flooding state.
|
||||
</li>
|
||||
</ul>
|
||||
<li><span style="font-weight: bold;">m4:</span><br>
|
||||
<a name="RoadType"></a>
|
||||
Road roadtype. Used for all tiles with road (road, station, tunnelbridge).
|
||||
|
@ -244,7 +244,7 @@ the array so you can quickly see what is used and what is not.
|
||||
<td class="caption">sea</td>
|
||||
<td class="bits" rowspan=5><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=4><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits" rowspan=5><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits" rowspan=5><span class="free">OOOO OOO</span><span class="used" title="Non-flooding state">X</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">0000</span> <span class="free">OOO0</span></td>
|
||||
<td class="bits" rowspan=5><span class="free">OOOO OOOO</span></td>
|
||||
|
@ -537,6 +537,7 @@ void DoClearSquare(TileIndex tile)
|
||||
MarkTileDirtyByTile(tile);
|
||||
if (remove) RemoveDockingTile(tile);
|
||||
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
InvalidateWaterRegion(tile);
|
||||
}
|
||||
|
||||
@ -693,6 +694,7 @@ CommandCost CmdLandscapeClear(DoCommandFlag flags, TileIndex tile)
|
||||
}
|
||||
}
|
||||
DoClearSquare(tile);
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
|
@ -120,6 +120,8 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u
|
||||
assert(o->town != nullptr);
|
||||
|
||||
for (TileIndex t : ta) {
|
||||
if (IsWaterTile(t)) ClearNeighbourNonFloodingStates(t);
|
||||
if (HasTileWaterGround(t)) InvalidateWaterRegion(t);
|
||||
WaterClass wc = (IsWaterTile(t) ? GetWaterClass(t) : WATER_CLASS_INVALID);
|
||||
/* Update company infrastructure counts for objects build on canals owned by nobody. */
|
||||
if (wc == WATER_CLASS_CANAL && owner != OWNER_NONE && (IsTileOwner(t, OWNER_NONE) || IsTileOwner(t, OWNER_WATER))) {
|
||||
@ -364,7 +366,6 @@ CommandCost CmdBuildObject(DoCommandFlag flags, TileIndex tile, ObjectType type,
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
BuildObject(type, tile, _current_company == OWNER_DEITY ? OWNER_NONE : _current_company, nullptr, view);
|
||||
for (TileIndex t : ta) InvalidateWaterRegion(t);
|
||||
|
||||
/* Make sure the HQ starts at the right size. */
|
||||
if (type == OBJECT_HQ) UpdateCompanyHQ(tile, hq_score);
|
||||
|
@ -2218,6 +2218,13 @@ bool AfterLoadGame()
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_NONFLOODING_WATER_TILES)) {
|
||||
for (auto t : Map::Iterate()) {
|
||||
if (!IsTileType(t, MP_WATER)) continue;
|
||||
SetNonFloodingWaterTile(t, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_124) && !IsSavegameVersionBefore(SLV_1)) {
|
||||
/* The train station tile area was added, but for really old (TTDPatch) it's already valid. */
|
||||
for (Waypoint *wp : Waypoint::Iterate()) {
|
||||
|
@ -390,6 +390,7 @@ enum SaveLoadVersion : uint16_t {
|
||||
SLV_WATER_TILE_TYPE, ///< 342 PR#13030 Simplify water tile type.
|
||||
SLV_PRODUCTION_HISTORY, ///< 343 PR#10541 Industry production history.
|
||||
SLV_ROAD_TYPE_LABEL_MAP, ///< 344 PR#13021 Add road type label map to allow upgrade/conversion of road types.
|
||||
SLV_NONFLOODING_WATER_TILES, ///< 345 PR#13013 Store water tile non-flooding state.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
@ -102,6 +102,7 @@ static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, Tree
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_WATER:
|
||||
ground = TREE_GROUND_SHORE;
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
break;
|
||||
|
||||
case MP_CLEAR:
|
||||
|
@ -24,6 +24,7 @@ enum FloodingBehaviour {
|
||||
};
|
||||
|
||||
FloodingBehaviour GetFloodingBehaviour(TileIndex tile);
|
||||
void ClearNeighbourNonFloodingStates(TileIndex tile);
|
||||
|
||||
void TileLoop_Water(TileIndex tile);
|
||||
bool FloodHalftile(TileIndex t);
|
||||
|
@ -90,6 +90,17 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear non-flooding state of the tiles around a tile.
|
||||
* @param tile The centre of the tile where other tiles' non-flooding state is cleared.
|
||||
*/
|
||||
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.
|
||||
@ -403,6 +414,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));
|
||||
@ -565,6 +577,7 @@ static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
|
||||
}
|
||||
DoClearSquare(tile);
|
||||
MarkCanalsAndRiversAroundDirty(tile);
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
}
|
||||
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
|
||||
@ -580,6 +593,7 @@ static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
|
||||
if (flags & DC_EXEC) {
|
||||
DoClearSquare(tile);
|
||||
MarkCanalsAndRiversAroundDirty(tile);
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
}
|
||||
if (IsSlopeWithOneCornerRaised(slope)) {
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER]);
|
||||
@ -1230,10 +1244,14 @@ static void DoDryUp(TileIndex tile)
|
||||
*/
|
||||
void TileLoop_Water(TileIndex tile)
|
||||
{
|
||||
if (IsTileType(tile, MP_WATER)) AmbientSoundEffect(tile);
|
||||
if (IsTileType(tile, MP_WATER)) {
|
||||
AmbientSoundEffect(tile);
|
||||
if (IsNonFloodingWaterTile(tile)) return;
|
||||
}
|
||||
|
||||
switch (GetFloodingBehaviour(tile)) {
|
||||
case FLOOD_ACTIVE:
|
||||
case FLOOD_ACTIVE: {
|
||||
bool continue_flooding = false;
|
||||
for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
|
||||
TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(dir));
|
||||
/* Contrary to drying up, flooding does not consider MP_VOID tiles. */
|
||||
@ -1241,6 +1259,9 @@ void TileLoop_Water(TileIndex tile)
|
||||
/* do not try to flood water tiles - increases performance a lot */
|
||||
if (IsTileType(dest, MP_WATER)) continue;
|
||||
|
||||
/* This neighbour tile might be floodable later if the tile is cleared, so allow flooding to continue. */
|
||||
continue_flooding = true;
|
||||
|
||||
/* TREE_GROUND_SHORE is the sign of a previous flood. */
|
||||
if (IsTileType(dest, MP_TREES) && GetTreeGround(dest) == TREE_GROUND_SHORE) continue;
|
||||
|
||||
@ -1251,7 +1272,9 @@ void TileLoop_Water(TileIndex tile)
|
||||
|
||||
DoFloodTile(dest);
|
||||
}
|
||||
if (!continue_flooding && IsTileType(tile, MP_WATER)) SetNonFloodingWaterTile(tile, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case FLOOD_DRYUP: {
|
||||
Slope slope_here = std::get<0>(GetFoundationSlope(tile)) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
|
||||
|
@ -516,4 +516,24 @@ inline void MakeLock(Tile t, Owner o, DiagDirection d, WaterClass wc_lower, Wate
|
||||
MakeLockTile(upper_tile, IsWaterTile(upper_tile) ? GetTileOwner(upper_tile) : 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
|
||||
*/
|
||||
inline void SetNonFloodingWaterTile(Tile t, bool b)
|
||||
{
|
||||
assert(IsTileType(t, MP_WATER));
|
||||
AssignBit(t.m3(), 0, b);
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
inline bool IsNonFloodingWaterTile(Tile t)
|
||||
{
|
||||
assert(IsTileType(t, MP_WATER));
|
||||
return HasBit(t.m3(), 0);
|
||||
}
|
||||
|
||||
#endif /* WATER_MAP_H */
|
||||
|
@ -505,6 +505,7 @@ CommandCost CmdBuildBuoy(DoCommandFlag flags, TileIndex tile)
|
||||
MakeBuoy(tile, wp->index, GetWaterClass(tile));
|
||||
CheckForDockingTile(tile);
|
||||
MarkTileDirtyByTile(tile);
|
||||
ClearNeighbourNonFloodingStates(tile);
|
||||
|
||||
wp->UpdateVirtCoord();
|
||||
InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
|
||||
|
Loading…
Reference in New Issue
Block a user