summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source.list1
-rw-r--r--src/industry_cmd.cpp25
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/newgrf_callbacks.h2
-rw-r--r--src/rail_cmd.cpp89
-rw-r--r--src/road_cmd.cpp45
-rw-r--r--src/saveload.cpp2
-rw-r--r--src/settings.cpp1
-rw-r--r--src/settings_gui.cpp1
-rw-r--r--src/slope.h13
-rw-r--r--src/station_cmd.cpp31
-rw-r--r--src/town_cmd.cpp10
-rw-r--r--src/tunnelbridge_cmd.cpp25
-rw-r--r--src/unmovable_cmd.cpp5
-rw-r--r--src/variables.h2
15 files changed, 237 insertions, 16 deletions
diff --git a/source.list b/source.list
index 40c077610..b2ecd8dee 100644
--- a/source.list
+++ b/source.list
@@ -100,6 +100,7 @@ aircraft.h
airport.h
airport_movement.h
articulated_vehicles.h
+autoslope.h
aystar.h
bmp.h
cargopacket.h
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index 97adbb84e..f1800ef40 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -36,6 +36,7 @@
#include "newgrf_industrytiles.h"
#include "newgrf_callbacks.h"
#include "misc/autoptr.hpp"
+#include "autoslope.h"
void ShowIndustryViewWindow(int industry);
void BuildOilRig(TileIndex tile);
@@ -1974,6 +1975,30 @@ Money IndustrySpec::GetConstructionCost() const
static CommandCost TerraformTile_Industry(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ if (AutoslopeEnabled()) {
+ /* We imitate here TTDP's behaviour:
+ * - Both new and old slope must not be steep.
+ * - TileMaxZ must not be changed.
+ * - Allow autoslope by default.
+ * - Disallow autoslope if callback succeeds and returns non-zero.
+ */
+ Slope tileh_old = GetTileSlope(tile, NULL);
+ /* TileMaxZ must not be changed. Slopes must not be steep. */
+ if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
+ const IndustryGfx gfx = GetIndustryGfx(tile);
+ const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
+
+ /* Call callback 3C 'disable autosloping for industry tiles'. */
+ if (HASBIT(itspec->callback_flags, CBM_INDT_AUTOSLOPE)) {
+ /* If the callback fails, allow autoslope. */
+ uint16 res = GetIndustryTileCallback(CBID_INDUSTRY_AUTOSLOPE, 0, 0, gfx, GetIndustryByTile(tile), tile);
+ if ((res == 0) || (res == CALLBACK_FAILED)) return _price.terraform;
+ } else {
+ // allow autoslope
+ return _price.terraform;
+ }
+ }
+ }
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); // funny magic bulldozer
}
diff --git a/src/lang/english.txt b/src/lang/english.txt
index bed65615b..22972d9e3 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1020,6 +1020,7 @@ STR_CONFIG_PATCHES_OFF :Off
STR_CONFIG_PATCHES_ON :On
STR_CONFIG_PATCHES_VEHICLESPEED :{LTBLUE}Show vehicle speed in status bar: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_BUILDONSLOPES :{LTBLUE}Allow building on slopes and coasts: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_AUTOSLOPE :{LTBLUE}Allow terraforming under buildings, tracks, etc. (autoslope): {ORANGE}{STRING1}
STR_CONFIG_PATCHES_CATCHMENT :{LTBLUE}Allow more realistically sized catchment areas: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_EXTRADYNAMITE :{LTBLUE}Allow removal of more town-owned roads, bridges, etc: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_MAMMOTHTRAINS :{LTBLUE}Enable building very long trains: {ORANGE}{STRING1}
diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h
index 59fd6da60..fefd4f27f 100644
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -160,7 +160,7 @@ enum CallbackID {
CBID_INDUSTRY_SPECIAL_EFFECT = 0x3B,
/** Called to determine if industry can alter the ground below industry tile */
- CBID_INDUSTRY_AUTOSLOPE = 0x3C, // not implemented
+ CBID_INDUSTRY_AUTOSLOPE = 0x3C,
/** Called to determine if the industry can still accept or refuse more cargo arrival */
CBID_INDUSTRY_REFUSE_CARGO = 0x3D,
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index f708fe02f..448068a1a 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -39,6 +39,7 @@
#include "newgrf_station.h"
#include "train.h"
#include "misc/autoptr.hpp"
+#include "autoslope.h"
const byte _track_sloped_sprites[14] = {
14, 15, 22, 13,
@@ -219,8 +220,11 @@ static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits ex
{
if (IsSteepSlope(tileh)) {
if (_patches.build_on_slopes && existing == 0) {
- TrackBits valid = TRACK_BIT_CROSS | (HASBIT(1 << SLOPE_STEEP_W | 1 << SLOPE_STEEP_E, tileh) ? TRACK_BIT_VERT : TRACK_BIT_HORZ);
- if (valid & rail_bits) return _price.terraform;
+ /* There may only be one track on steep slopes. (Autoslope calls with multiple bits in rail_bits) */
+ if (KILL_FIRST_BIT(rail_bits & TRACK_BIT_MASK) == 0) {
+ TrackBits valid = TRACK_BIT_CROSS | (HASBIT(1 << SLOPE_STEEP_W | 1 << SLOPE_STEEP_E, tileh) ? TRACK_BIT_VERT : TRACK_BIT_HORZ);
+ if (valid & rail_bits) return _price.terraform;
+ }
}
} else {
rail_bits |= existing;
@@ -2189,15 +2193,62 @@ static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
return VETSB_CONTINUE;
}
+/**
+ * Tests if autoslope is allowed.
+ *
+ * @param tile The tile.
+ * @param flags Terraform command flags.
+ * @param z_old Old TileZ.
+ * @param tileh_old Old TileSlope.
+ * @param z_new New TileZ.
+ * @param tileh_new New TileSlope.
+ * @param rail_bits Trackbits.
+ */
+static CommandCost TestAutoslopeOnRailTile(TileIndex tile, uint flags, uint z_old, Slope tileh_old, uint z_new, Slope tileh_new, TrackBits rail_bits)
+{
+ if (!_patches.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR;
+
+ /* Is the slope-rail_bits combination valid in general? I.e. is it save to call GetRailFoundation() ? */
+ if (CmdFailed(CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile))) return CMD_ERROR;
+
+ /* Get the slopes on top of the foundations */
+ z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old);
+ z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new);
+
+ Slope track_corner;
+ switch (rail_bits) {
+ case TRACK_BIT_LEFT: track_corner = SLOPE_W; break;
+ case TRACK_BIT_LOWER: track_corner = SLOPE_S; break;
+ case TRACK_BIT_RIGHT: track_corner = SLOPE_E; break;
+ case TRACK_BIT_UPPER: track_corner = SLOPE_N; break;
+
+ /* Surface slope must not be changed */
+ default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
+ }
+
+ /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
+ if ((tileh_old & track_corner) != 0) z_old += TILE_HEIGHT;
+ if ((tileh_new & track_corner) != 0) z_new += TILE_HEIGHT;
+ if (z_old != z_new) return CMD_ERROR;
+
+ /* Make the ground dirty, if surface slope has changed */
+ if ((tileh_old != tileh_new) && ((flags & DC_EXEC) != 0)) SetRailGroundType(tile, RAIL_GROUND_BARREN);
+
+ return _price.terraform;
+}
+
static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ uint z_old;
+ Slope tileh_old = GetTileSlope(tile, &z_old);
if (IsPlainRailTile(tile)) {
- uint z_old;
- Slope tileh_old = GetTileSlope(tile, &z_old);
TrackBits rail_bits = GetTrackBits(tile);
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
+ /* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
+ CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
+
/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
Slope allowed_corner;
switch (rail_bits) {
@@ -2205,7 +2256,7 @@ static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new,
case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
case TRACK_BIT_LEFT: allowed_corner = SLOPE_E; break;
case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
- default: return CMD_ERROR;
+ default: return autoslope_result;
}
Slope track_corners = ComplementSlope(allowed_corner);
@@ -2221,28 +2272,28 @@ static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new,
z_new += TILE_HEIGHT;
} else {
/* do not build a foundation */
- if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return CMD_ERROR;
+ if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result;
}
/* Track height must remain unchanged */
- if (z_old != z_new) return CMD_ERROR;
+ if (z_old != z_new) return autoslope_result;
break;
case FOUNDATION_LEVELED:
/* Is allowed_corner covered by the foundation? */
- if ((tileh_old & allowed_corner) == 0) return CMD_ERROR;
+ if ((tileh_old & allowed_corner) == 0) return autoslope_result;
/* allowed_corner may only be raised -> steep slope */
- if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return CMD_ERROR;
+ if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result;
break;
case FOUNDATION_STEEP_LOWER:
/* Only allow to lower highest corner */
- if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return CMD_ERROR;
+ if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result;
break;
case FOUNDATION_STEEP_HIGHER:
- return CMD_ERROR;
+ return autoslope_result;
default: NOT_REACHED();
}
@@ -2252,6 +2303,22 @@ static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new,
/* allow terraforming, no extra costs */
return CommandCost();
+ } else {
+ if (_patches.build_on_slopes && AutoslopeEnabled()) {
+ switch (GetRailTileType(tile)) {
+ case RAIL_TILE_WAYPOINT: {
+ CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
+ if (!CmdFailed(cost)) return cost; // allow autoslope
+ break;
+ }
+
+ case RAIL_TILE_DEPOT:
+ if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform;
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
}
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp
index cf2ae3638..003cf3348 100644
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -32,6 +32,12 @@
#include "station_map.h"
#include "tunnel_map.h"
#include "misc/autoptr.hpp"
+#include "autoslope.h"
+
+#define M(x) (1 << (x))
+/* Level crossings may only be built on these slopes */
+static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT));
+#undef M
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
{
@@ -405,12 +411,10 @@ CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
}
-#define M(x) (1 << (x))
/* Level crossings may only be built on these slopes */
- if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
+ if (!HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
}
-#undef M
if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
switch (GetTrackBits(tile)) {
@@ -1372,6 +1376,41 @@ static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID n
static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ if (_patches.build_on_slopes && AutoslopeEnabled()) {
+ switch (GetRoadTileType(tile)) {
+ case ROAD_TILE_CROSSING:
+ if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return _price.terraform;
+ break;
+
+ case ROAD_TILE_DEPOT:
+ if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return _price.terraform;
+ break;
+
+ case ROAD_TILE_NORMAL: {
+ RoadBits bits = GetAllRoadBits(tile);
+ RoadBits bits_copy = bits;
+ /* Check if the slope-road_bits combination is valid at all, i.e. it is save to call GetRoadFoundation(). */
+ if (!CmdFailed(CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE))) {
+ /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */
+ if (bits == bits_copy) {
+ uint z_old;
+ Slope tileh_old = GetTileSlope(tile, &z_old);
+
+ /* Get the slope on top of the foundation */
+ z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
+ z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
+
+ /* The surface slope must not be changed */
+ if ((z_old == z_new) && (tileh_old == tileh_new)) return _price.terraform;
+ }
+ }
+ break;
+ }
+
+ default: NOT_REACHED();
+ }
+ }
+
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/saveload.cpp b/src/saveload.cpp
index d9e0ddedd..3550e1cef 100644
--- a/src/saveload.cpp
+++ b/src/saveload.cpp
@@ -29,7 +29,7 @@
#include "strings.h"
#include <list>
-extern const uint16 SAVEGAME_VERSION = 74;
+extern const uint16 SAVEGAME_VERSION = 75;
uint16 _sl_version; ///< the major savegame version identifier
byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!
diff --git a/src/settings.cpp b/src/settings.cpp
index 9178650fc..e650cce29 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1362,6 +1362,7 @@ const SettingDesc _patch_settings[] = {
/***************************************************************************/
/* Construction section of the GUI-configure patches window */
SDT_BOOL(Patches, build_on_slopes, 0, 0, true, STR_CONFIG_PATCHES_BUILDONSLOPES, NULL),
+ SDT_CONDBOOL(Patches, autoslope, 75, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_AUTOSLOPE, NULL),
SDT_BOOL(Patches, extra_dynamite, 0, 0, false, STR_CONFIG_PATCHES_EXTRADYNAMITE, NULL),
SDT_BOOL(Patches, longbridges, 0, 0, true, STR_CONFIG_PATCHES_LONGBRIDGES, NULL),
SDT_BOOL(Patches, signal_side, N, 0, true, STR_CONFIG_PATCHES_SIGNALSIDE, RedrawScreen),
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index 72066c7aa..bb773df0e 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -664,6 +664,7 @@ static const char *_patches_ui[] = {
static const char *_patches_construction[] = {
"build_on_slopes",
+ "autoslope",
"extra_dynamite",
"longbridges",
"signal_side",
diff --git a/src/slope.h b/src/slope.h
index 0ed1c452c..dd04c24be 100644
--- a/src/slope.h
+++ b/src/slope.h
@@ -90,6 +90,19 @@ static inline byte GetHighestSlopeCorner(Slope s)
}
}
+/**
+ * Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
+ *
+ * @param s The #Slope.
+ * @return Relative height of highest corner.
+ */
+static inline uint GetSlopeMaxZ(Slope s)
+{
+ if (s == SLOPE_FLAT) return 0;
+ if (IsSteepSlope(s)) return 2 * TILE_HEIGHT;
+ return TILE_HEIGHT;
+}
+
/**
* Enumeration for Foundations.
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 6e9993f8a..6113276b3 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -42,6 +42,7 @@
#include "road.h"
#include "cargotype.h"
#include "strings.h"
+#include "autoslope.h"
DEFINE_OLD_POOL_GENERIC(Station, Station)
DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
@@ -2880,6 +2881,36 @@ void AfterLoadStations()
static CommandCost TerraformTile_Station(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ if (_patches.build_on_slopes && AutoslopeEnabled()) {
+ /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
+ * TTDP does not call it.
+ */
+ if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
+ switch (GetStationType(tile)) {
+ case STATION_RAIL: {
+ DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
+ if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
+ if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
+ return _price.terraform;
+ }
+
+ case STATION_AIRPORT:
+ return _price.terraform;
+
+ case STATION_TRUCK:
+ case STATION_BUS: {
+ DiagDirection direction = GetRoadStopDir(tile);
+ if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
+ if (IsDriveThroughStopTile(tile)) {
+ if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
+ }
+ return _price.terraform;
+ }
+
+ default: break;
+ }
+ }
+ }
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index f399f09a2..d192e1a28 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -41,6 +41,7 @@
#include "newgrf_commons.h"
#include "newgrf_townname.h"
#include "misc/autoptr.hpp"
+#include "autoslope.h"
/* Initialize the town-pool */
DEFINE_OLD_POOL_GENERIC(Town, Town)
@@ -2309,6 +2310,15 @@ void InitializeTowns()
static CommandCost TerraformTile_Town(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ if (AutoslopeEnabled()) {
+ HouseID house = GetHouseType(tile);
+ HouseSpec *hs = GetHouseSpecs(house);
+
+ /* Here we differ from TTDP by checking TILE_NOT_SLOPED */
+ if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) &&
+ (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) return _price.terraform;
+ }
+
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 87abd7470..2ddefb554 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -32,6 +32,7 @@
#include "yapf/yapf.h"
#include "date.h"
#include "newgrf_sound.h"
+#include "autoslope.h"
#include "table/bridge_land.h"
@@ -1416,6 +1417,30 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y
static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
{
+ if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
+ DiagDirection direction = GetBridgeRampDirection(tile);
+ Axis axis = DiagDirToAxis(direction);
+ CommandCost res;
+
+ /* Check if new slope is valid for bridges in general (so we can savely call GetBridgeFoundation()) */
+ if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
+ res = CheckBridgeSlopeSouth(axis, tileh_new);
+ } else {
+ res = CheckBridgeSlopeNorth(axis, tileh_new);
+ }
+
+ if (!CmdFailed(res)) {
+ uint z_old;
+ Slope tileh_old = GetTileSlope(tile, &z_old);
+
+ z_old += ApplyFoundationToSlope(GetBridgeFoundation(tileh_old, axis), &tileh_old);
+ z_new += ApplyFoundationToSlope(GetBridgeFoundation(tileh_new, axis), &tileh_new);
+
+ /* Surface slope remains unchanged? */
+ if ((z_old == z_new) && (tileh_old == tileh_new)) return _price.terraform;
+ }
+ }
+
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/unmovable_cmd.cpp b/src/unmovable_cmd.cpp
index c3495d715..8bc8f3fa1 100644
--- a/src/unmovable_cmd.cpp
+++ b/src/unmovable_cmd.cpp
@@ -24,6 +24,7 @@
#include "table/unmovable_land.h"
#include "genworld.h"
#include "bridge.h"
+#include "autoslope.h"
/** Destroy a HQ.
* During normal gameplay you can only implicitely destroy a HQ when you are
@@ -408,6 +409,10 @@ static CommandCost TerraformTile_Unmovable(TileIndex tile, uint32 flags, uint z_
/* Owned land remains unsold */
if (IsOwnedLand(tile) && CheckTileOwnership(tile)) return CommandCost();
+ if (AutoslopeEnabled() && (IsStatue(tile) || IsCompanyHQ(tile))) {
+ if (!IsSteepSlope(tileh_new) && (z_new + GetSlopeMaxZ(tileh_new) == GetTileMaxZ(tile))) return _price.terraform;
+ }
+
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/variables.h b/src/variables.h
index f367e7baf..5fbd6ee26 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -240,6 +240,8 @@ struct Patches {
bool timetabling; ///< Whether to allow timetabling.
bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days.
+
+ bool autoslope; ///< Allow terraforming under things.
};
VARDEF Patches _patches;