(svn r26900) -Fix-ish: dirty the appropriate area around map edges when terraforming there to prevent any artefacts from occuring (ic111)

This commit is contained in:
rubidium 2014-09-21 17:29:48 +00:00
parent 4d619ad10e
commit 073aa05da5
3 changed files with 95 additions and 0 deletions

View File

@ -321,6 +321,86 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
/* Finally mark the dirty tiles dirty */
for (TileIndexSet::const_iterator it = ts.dirty_tiles.begin(); it != ts.dirty_tiles.end(); it++) {
MarkTileDirtyByTile(*it);
int height = TerraformGetHeightOfTile(&ts, *it);
/* Now, if we alter the height of the map edge, we need to take care
* about repainting the affected areas outside map as well.
* Remember:
* Outside map, we assume that our landscape descends to
* height zero as fast as possible.
* Those simulated tiles (they don't exist as datastructure,
* only as concept in code) need to be repainted properly,
* otherwise we will get ugly glitches.
*
* Furthermore, note that we have to take care about the possibility,
* that landscape was higher before the change,
* so also tiles a bit outside need to be repainted.
*/
int x = TileX(*it);
int y = TileY(*it);
if (x == 0) {
if (y == 0) {
/* Height of the northern corner is altered. */
for (int cx = 0; cx >= -height - 1; cx--) {
for (int cy = 0; cy >= -height - 1; cy--) {
/* This means, tiles in the sector north of that
* corner need to be repainted.
*/
if (cx + cy >= -height - 2) {
/* But only tiles that actually might have changed. */
MarkTileDirtyByTileOutsideMap(cx, cy);
}
}
}
} else if (y < (int)MapMaxY()) {
for (int cx = 0; cx >= -height - 1; cx--) {
MarkTileDirtyByTileOutsideMap(cx, y);
}
} else {
for (int cx = 0; cx >= -height - 1; cx--) {
for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
if (cx + ((int)MapMaxY() - cy) >= -height - 2) {
MarkTileDirtyByTileOutsideMap(cx, cy);
}
}
}
}
} else if (x < (int)MapMaxX()) {
if (y == 0) {
for (int cy = 0; cy >= -height - 1; cy--) {
MarkTileDirtyByTileOutsideMap(x, cy);
}
} else if (y < (int)MapMaxY()) {
/* Nothing to be done here, we are inside the map. */
} else {
for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
MarkTileDirtyByTileOutsideMap(x, cy);
}
}
} else {
if (y == 0) {
for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
for (int cy = 0; cy >= -height - 1; cy--) {
if (((int)MapMaxX() - cx) + cy >= -height - 2) {
MarkTileDirtyByTileOutsideMap(cx, cy);
}
}
}
} else if (y < (int)MapMaxY()) {
for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
MarkTileDirtyByTileOutsideMap(cx, y);
}
} else {
for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
if (((int)MapMaxX() - cx) + ((int)MapMaxY() - cy) >= -height - 2) {
MarkTileDirtyByTileOutsideMap(cx, cy);
}
}
}
}
}
}
if (c != NULL) c->terraform_limit -= ts.tile_to_new_height.size() << 16;

View File

@ -2139,6 +2139,20 @@ void MarkTileDirtyByTile(TileIndex tile)
);
}
void MarkTileDirtyByTileOutsideMap(int x, int y)
{
Point pt = RemapCoords(x * TILE_SIZE, y * TILE_SIZE, GetTilePixelZOutsideMap(x, y));
/* Since tiles painted outside the map don't contain buildings, trees, etc.,
* this reduced area for repainting should suffice. If not, adjust the offsets
* used below. */
MarkAllViewportsDirty(
pt.x - TILE_SIZE + 1,
pt.y,
pt.x + TILE_SIZE - 1,
pt.y + TILE_SIZE + TILE_HEIGHT - 1
);
}
/**
* Marks the selected tiles as dirty.
*

View File

@ -80,6 +80,7 @@ extern Point _tile_fract_coords;
void MarkTileDirtyByTile(TileIndex tile);
int GetRowAtTile(int viewport_y, Point tile, bool bridge_correct);
void MarkTileDirtyByTileOutsideMap(int x, int y);
Point GetViewportStationMiddle(const ViewPort *vp, const Station *st);