summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-09-14 22:27:40 +0000
committerrubidium <rubidium@openttd.org>2007-09-14 22:27:40 +0000
commitfef64185b87e4517b7760e017171d646eaa1eb69 (patch)
tree66f89fc328e49813581c22632a0a9cb21d7c2eb8
parent5647bd5157b623348feb202623057fd84eb9c3c5 (diff)
downloadopenttd-fef64185b87e4517b7760e017171d646eaa1eb69.tar.xz
(svn r11107) -Feature: some tool so one can still build tunnels under rails (and other structures) when the owner of the structure built it on foundations and if you have enough "empty" space ofcourse. One could use the tool for some other construction needs too. Patch by frosch.
-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;