|
@@ -25,24 +25,26 @@
|
|
|
#include "player.h"
|
|
|
#include "town.h"
|
|
|
#include "gfx.h"
|
|
|
#include "sound.h"
|
|
|
#include "yapf/yapf.h"
|
|
|
#include "depot.h"
|
|
|
#include "newgrf.h"
|
|
|
#include "station_map.h"
|
|
|
#include "tunnel_map.h"
|
|
|
#include "misc/autoptr.hpp"
|
|
|
#include "autoslope.h"
|
|
|
#include "transparency.h"
|
|
|
#include "tunnelbridge_map.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)
|
|
|
{
|
|
|
RoadBits present;
|
|
|
RoadBits n;
|
|
|
*edge_road = true;
|
|
|
|
|
@@ -124,28 +126,28 @@ CommandCost CmdRemoveRoad(TileIndex tile
|
|
|
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
|
|
|
break;
|
|
|
|
|
|
case MP_STATION:
|
|
|
if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
|
|
|
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
|
|
|
break;
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
{
|
|
|
TileIndex endtile;
|
|
|
if (IsTunnel(tile)) {
|
|
|
if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
endtile = GetOtherTunnelEnd(tile);
|
|
|
} else {
|
|
|
if (GetBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
endtile = GetOtherBridgeEnd(tile);
|
|
|
}
|
|
|
|
|
|
if (GetVehicleTunnelBridge(tile, endtile) != NULL) return CMD_ERROR;
|
|
|
} break;
|
|
|
|
|
|
default:
|
|
|
return CMD_ERROR;
|
|
|
}
|
|
|
|
|
|
RoadBits pieces = Extract<RoadBits, 0>(p1);
|
|
|
RoadTypes rts = GetRoadTypes(tile);
|
|
@@ -166,25 +168,25 @@ CommandCost CmdRemoveRoad(TileIndex tile
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
|
|
TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
|
|
|
/* Pay for *every* tile of the bridge or tunnel */
|
|
|
cost.AddCost((DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road);
|
|
|
if (flags & DC_EXEC) {
|
|
|
SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
|
|
|
SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
|
|
|
|
|
|
/* Mark tiles diry that have been repaved */
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
MarkTileDirtyByTile(other_end);
|
|
|
if (IsBridge(tile)) {
|
|
|
TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
|
|
|
TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
|
|
|
|
|
|
for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
cost.AddCost(_price.remove_road);
|
|
|
if (flags & DC_EXEC) {
|
|
|
SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
}
|
|
|
}
|
|
|
return CommandCost(cost);
|
|
@@ -505,28 +507,28 @@ CommandCost CmdBuildRoad(TileIndex tile,
|
|
|
|
|
|
case MP_STATION:
|
|
|
if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
|
|
|
if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
|
|
|
/* Don't allow "upgrading" the roadstop when vehicles are already driving on it */
|
|
|
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
|
|
|
break;
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
{
|
|
|
TileIndex endtile;
|
|
|
if (IsTunnel(tile)) {
|
|
|
if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
endtile = GetOtherTunnelEnd(tile);
|
|
|
} else {
|
|
|
if (GetBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR;
|
|
|
endtile = GetOtherBridgeEnd(tile);
|
|
|
}
|
|
|
if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
|
|
|
/* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */
|
|
|
if (GetVehicleTunnelBridge(tile, endtile) != NULL) return CMD_ERROR;
|
|
|
} break;
|
|
|
|
|
|
default:
|
|
|
do_clear:;
|
|
|
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
|
|
if (CmdFailed(ret)) return ret;
|
|
|
cost.AddCost(ret);
|
|
@@ -567,25 +569,25 @@ do_clear:;
|
|
|
} break;
|
|
|
|
|
|
case MP_TUNNELBRIDGE: {
|
|
|
TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
|
|
|
|
|
|
SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt));
|
|
|
SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
|
|
|
|
|
|
/* Mark tiles diry that have been repaved */
|
|
|
MarkTileDirtyByTile(other_end);
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
if (IsBridge(tile)) {
|
|
|
TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
|
|
|
TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
|
|
|
|
|
|
for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t);
|
|
|
}
|
|
|
} break;
|
|
|
|
|
|
case MP_STATION:
|
|
|
SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player);
|
|
|
break;
|
|
@@ -682,30 +684,30 @@ CommandCost CmdBuildLongRoad(TileIndex e
|
|
|
if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
|
|
|
if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
|
|
|
|
|
|
ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
|
|
|
if (CmdFailed(ret)) {
|
|
|
if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
|
|
|
_error_message = INVALID_STRING_ID;
|
|
|
} else {
|
|
|
had_success = true;
|
|
|
/* Only pay for the upgrade on one side of the bridges and tunnels */
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
|
|
if (IsBridge(tile)) {
|
|
|
if ((!had_bridge || GetBridgeRampDirection(tile) == DIAGDIR_SE || GetBridgeRampDirection(tile) == DIAGDIR_SW)) {
|
|
|
if ((!had_bridge || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
|
|
|
cost.AddCost(ret);
|
|
|
}
|
|
|
had_bridge = true;
|
|
|
} else {
|
|
|
if ((!had_tunnel || GetTunnelDirection(tile) == DIAGDIR_SE || GetTunnelDirection(tile) == DIAGDIR_SW)) {
|
|
|
if ((!had_tunnel || GetTunnelBridgeDirection(tile) == DIAGDIR_SE || GetTunnelBridgeDirection(tile) == DIAGDIR_SW)) {
|
|
|
cost.AddCost(ret);
|
|
|
}
|
|
|
had_tunnel = true;
|
|
|
}
|
|
|
} else {
|
|
|
cost.AddCost(ret);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (tile == end_tile) break;
|
|
|
|
|
|
tile += HasBit(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
|