summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/terraform_cmd.cpp80
-rw-r--r--src/viewport.cpp14
-rw-r--r--src/viewport_func.h1
3 files changed, 95 insertions, 0 deletions
diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp
index 2d36a101e..bcc480897 100644
--- a/src/terraform_cmd.cpp
+++ b/src/terraform_cmd.cpp
@@ -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;
diff --git a/src/viewport.cpp b/src/viewport.cpp
index 81c630a3a..255b9c784 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -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.
*
diff --git a/src/viewport_func.h b/src/viewport_func.h
index 7eba50853..3e05162d8 100644
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -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);