summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcelestar <celestar@openttd.org>2006-06-02 13:05:41 +0000
committercelestar <celestar@openttd.org>2006-06-02 13:05:41 +0000
commit25a63ec7af6fadb2d33ef84f79597c14b10e7f39 (patch)
treed5df4e2831609eca45d7ea4558e09a600089ead2
parentd680fcec772d422b88ea4802add2e6195c6327a2 (diff)
downloadopenttd-25a63ec7af6fadb2d33ef84f79597c14b10e7f39.tar.xz
(svn r5070) Merged the bridge branch
-Feature: Bridges can now be placed above: Any railway track combination (excluding depots and waypoints) Any road combination (excluding depots) Clear tiles (duh), including fields Tunnel entrances Bridge heads Thanks to Tron for idea and implementation, KUDr for the yapf synchronization and many others for hours of testing There are still a number of visual problems remaining, especially when electric railways are on or under the bridge. DO NOT REPORT THOSE BUGS FOR THE TIME BEING please.
-rw-r--r--BUGS7
-rw-r--r--ai/default/default.c5
-rw-r--r--bridge.h1
-rw-r--r--bridge_map.c37
-rw-r--r--bridge_map.h146
-rw-r--r--clear_cmd.c10
-rw-r--r--elrail.c66
-rw-r--r--landscape.c3
-rw-r--r--misc.c39
-rw-r--r--npf.c27
-rw-r--r--openttd.c81
-rw-r--r--pathfind.c99
-rw-r--r--rail.c18
-rw-r--r--rail_cmd.c75
-rw-r--r--rail_map.h10
-rw-r--r--road_cmd.c145
-rw-r--r--road_map.c18
-rw-r--r--roadveh_cmd.c18
-rw-r--r--saveload.c2
-rw-r--r--station_cmd.c5
-rw-r--r--table/sprites.h21
-rw-r--r--terraform_gui.c18
-rw-r--r--town_cmd.c6
-rw-r--r--train_cmd.c61
-rw-r--r--tree_cmd.c15
-rw-r--r--tunnelbridge_cmd.c655
-rw-r--r--variables.h1
-rw-r--r--vehicle.h1
-rw-r--r--water_cmd.c63
-rw-r--r--waypoint.c3
-rw-r--r--yapf/follow_track.hpp59
-rw-r--r--yapf/yapf.h2
-rw-r--r--yapf/yapf_road.cpp2
33 files changed, 757 insertions, 962 deletions
diff --git a/BUGS b/BUGS
index bcdcee6f2..12b059cc6 100644
--- a/BUGS
+++ b/BUGS
@@ -1,7 +1,12 @@
-/* $Id */
+/* $Id$ */
KNOWN BUGS / PROBLEMS:
+bridges:
+Graphical problems, especially in conjunction with signals and catenary
+
+electrified rails:
Normal and elrail depots look the same. Use 'X' (transparent buildings)
to distinguish between them
Missing curors / icons for construction (currently using the conventional ones)
+
diff --git a/ai/default/default.c b/ai/default/default.c
index 4b1bcfc92..7563e391a 100644
--- a/ai/default/default.c
+++ b/ai/default/default.c
@@ -2158,9 +2158,7 @@ static bool AiRemoveTileAndGoForward(Player *p)
return false;
p->ai.cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDir(p->ai.cur_dir_a));
return true;
- }
-
- if (IsBridgeRamp(tile)) {
+ } else {
// Check if the bridge points in the right direction.
// This is not really needed the first place AiRemoveTileAndGoForward is called.
if (DiagDirToAxis(GetBridgeRampDirection(tile)) != (p->ai.cur_dir_a & 1U)) return false;
@@ -3692,7 +3690,6 @@ pos_3:
} else if (IsTileType(tile, MP_TUNNELBRIDGE)) {
if (!IsTileOwner(tile, _current_player) ||
!IsBridge(tile) ||
- !IsBridgeRamp(tile) ||
GetBridgeTransportType(tile) != TRANSPORT_RAIL) {
return;
}
diff --git a/bridge.h b/bridge.h
index 95c6b2004..efeba7dba 100644
--- a/bridge.h
+++ b/bridge.h
@@ -27,5 +27,6 @@ extern const Bridge orig_bridge[MAX_BRIDGES];
extern Bridge _bridge[MAX_BRIDGES];
uint GetBridgeFoundation(Slope tileh, Axis axis);
+uint SetSpeedLimitOnBridge(Vehicle *);
#endif /* BRIDGE_H */
diff --git a/bridge_map.c b/bridge_map.c
index cbb955c37..e21c5928c 100644
--- a/bridge_map.c
+++ b/bridge_map.c
@@ -3,22 +3,25 @@
#include "stdafx.h"
#include "openttd.h"
#include "bridge_map.h"
+#include "variables.h"
TileIndex GetBridgeEnd(TileIndex tile, DiagDirection dir)
{
TileIndexDiff delta = TileOffsByDir(dir);
- assert(DiagDirToAxis(dir) == GetBridgeAxis(tile));
-
- do {
- tile += delta;
- } while (!IsBridgeRamp(tile));
+ do { tile += delta; } while (IsBridgeAbove(tile) && IsBridgeOfAxis(tile, DiagDirToAxis(dir)));
return tile;
}
+TileIndex GetNorthernBridgeEnd(TileIndex t)
+{
+ return GetBridgeEnd(t, ReverseDiagDir(AxisToDiagDir(GetBridgeAxis(t))));
+}
+
+
TileIndex GetSouthernBridgeEnd(TileIndex t)
{
return GetBridgeEnd(t, AxisToDiagDir(GetBridgeAxis(t)));
@@ -27,11 +30,25 @@ TileIndex GetSouthernBridgeEnd(TileIndex t)
TileIndex GetOtherBridgeEnd(TileIndex tile)
{
- TileIndexDiff delta = TileOffsByDir(GetBridgeRampDirection(tile));
+ assert(IsBridgeTile(tile));
+ return GetBridgeEnd(tile, GetBridgeRampDirection(tile));
+}
- do {
- tile += delta;
- } while (!IsBridgeRamp(tile));
+uint GetBridgeHeight(TileIndex tile, Axis a)
+{
+ uint h, f;
+ uint tileh = GetTileSlope(tile, &h);
- return tile;
+ f = GetBridgeFoundation(tileh, a);
+
+ if (f) {
+ if (f < 15) {
+ h += TILE_HEIGHT;
+ tileh = SLOPE_FLAT;
+ } else {
+ tileh = _inclined_tileh[f - 15];
+ }
+ }
+
+ return h + TILE_HEIGHT;
}
diff --git a/bridge_map.h b/bridge_map.h
index f2b5d4ee4..9470204e0 100644
--- a/bridge_map.h
+++ b/bridge_map.h
@@ -11,6 +11,9 @@
#include "tile.h"
+void DrawBridgeMiddle(const TileInfo* ti); // XXX
+
+
static inline bool IsBridge(TileIndex t)
{
assert(IsTileType(t, MP_TUNNELBRIDGE));
@@ -23,28 +26,38 @@ static inline bool IsBridgeTile(TileIndex t)
}
-static inline bool IsBridgeRamp(TileIndex t)
+static inline bool MayHaveBridgeAbove(TileIndex t)
{
- assert(IsBridgeTile(t));
- return !HASBIT(_m[t].m5, 6);
+ return
+ IsTileType(t, MP_CLEAR) ||
+ IsTileType(t, MP_RAILWAY) ||
+ IsTileType(t, MP_STREET) ||
+ IsTileType(t, MP_WATER) ||
+ IsTileType(t, MP_TUNNELBRIDGE);
}
-static inline bool IsBridgeMiddle(TileIndex t)
+
+static inline bool IsXBridgeAbove(TileIndex t)
{
- assert(IsBridgeTile(t));
- return HASBIT(_m[t].m5, 6);
+ assert(MayHaveBridgeAbove(t));
+ return GB(_m[t].extra, 6, 1) != 0;
+}
+
+static inline bool IsYBridgeAbove(TileIndex t)
+{
+ assert(MayHaveBridgeAbove(t));
+ return GB(_m[t].extra, 7, 1) != 0;
}
+static inline bool IsBridgeOfAxis(TileIndex t, Axis a)
+{
+ if (a == AXIS_X) return IsXBridgeAbove(t);
+ return IsYBridgeAbove(t);
+}
-/**
- * Determines which piece of a bridge is contained in the current tile
- * @param tile The tile to analyze
- * @return the piece
- */
-static inline uint GetBridgePiece(TileIndex t)
+static inline bool IsBridgeAbove(TileIndex t)
{
- assert(IsBridgeMiddle(t));
- return GB(_m[t].m2, 0, 4);
+ return (IsXBridgeAbove(t) || IsYBridgeAbove(t));
}
@@ -65,7 +78,6 @@ static inline uint GetBridgeType(TileIndex t)
*/
static inline DiagDirection GetBridgeRampDirection(TileIndex t)
{
- assert(IsBridgeRamp(t));
/* Heavy wizardry to convert the X/Y (bit 0) + N/S (bit 5) encoding of
* bridges to a DiagDirection
*/
@@ -75,8 +87,9 @@ static inline DiagDirection GetBridgeRampDirection(TileIndex t)
static inline Axis GetBridgeAxis(TileIndex t)
{
- assert(IsBridgeMiddle(t));
- return (Axis)GB(_m[t].m5, 0, 1);
+ static const Axis BridgeAxis[] = {AXIS_END, AXIS_X, AXIS_Y, AXIS_END};
+ assert(IsBridgeAbove(t));
+ return BridgeAxis[GB(_m[t].extra, 6, 2)];
}
@@ -87,50 +100,17 @@ static inline TransportType GetBridgeTransportType(TileIndex t)
}
-static inline bool IsClearUnderBridge(TileIndex t)
-{
- assert(IsBridgeMiddle(t));
- return GB(_m[t].m5, 3, 3) == 0;
-}
-
-static inline bool IsWaterUnderBridge(TileIndex t)
-{
- assert(IsBridgeMiddle(t));
- return GB(_m[t].m5, 3, 3) == 1;
-}
-
-
-static inline bool IsTransportUnderBridge(TileIndex t)
-{
- assert(IsBridgeMiddle(t));
- return HASBIT(_m[t].m5, 5);
-}
-
-static inline TransportType GetTransportTypeUnderBridge(TileIndex t)
-{
- assert(IsTransportUnderBridge(t));
- return (TransportType)GB(_m[t].m5, 3, 2);
-}
-
-static inline RoadBits GetRoadBitsUnderBridge(TileIndex t)
-{
- assert(GetTransportTypeUnderBridge(t) == TRANSPORT_ROAD);
- return GetBridgeAxis(t) == AXIS_X ? ROAD_Y : ROAD_X;
-}
-
-static inline TrackBits GetRailBitsUnderBridge(TileIndex t)
-{
- assert(GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL);
- return GetBridgeAxis(t) == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X;
-}
-
-
/**
* Finds the end of a bridge in the specified direction starting at a middle tile
*/
TileIndex GetBridgeEnd(TileIndex, DiagDirection);
/**
+ * Finds the northern end of a bridge starting at a middle tile
+ */
+TileIndex GetNorthernBridgeEnd(TileIndex t);
+
+/**
* Finds the southern end of a bridge starting at a middle tile
*/
TileIndex GetSouthernBridgeEnd(TileIndex t);
@@ -141,38 +121,26 @@ TileIndex GetSouthernBridgeEnd(TileIndex t);
*/
TileIndex GetOtherBridgeEnd(TileIndex);
-uint GetBridgeHeight(TileIndex t);
+uint GetBridgeHeight(TileIndex tile, Axis a);
+uint GetBridgeFoundation(Slope tileh, Axis axis);
-static inline void SetClearUnderBridge(TileIndex t)
+static inline void ClearSingleBridgeMiddle(TileIndex t, Axis a)
{
- assert(IsBridgeMiddle(t));
- SetTileOwner(t, OWNER_NONE);
- SB(_m[t].m5, 3, 3, 0 << 2 | 0);
- SB(_m[t].m3, 0, 4, 0);
+ assert(MayHaveBridgeAbove(t));
+ CLRBIT(_m[t].extra, 6 + a);
}
-static inline void SetWaterUnderBridge(TileIndex t)
-{
- assert(IsBridgeMiddle(t));
- SetTileOwner(t, OWNER_WATER);
- SB(_m[t].m5, 3, 3, 0 << 2 | 1);
- SB(_m[t].m3, 0, 4, 0);
-}
-static inline void SetRailUnderBridge(TileIndex t, Owner o, RailType r)
+static inline void ClearBridgeMiddle(TileIndex t)
{
- assert(IsBridgeMiddle(t));
- SetTileOwner(t, o);
- SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_RAIL);
- SB(_m[t].m3, 0, 4, r);
+ ClearSingleBridgeMiddle(t, AXIS_X);
+ ClearSingleBridgeMiddle(t, AXIS_Y);
}
-static inline void SetRoadUnderBridge(TileIndex t, Owner o)
+static inline void SetBridgeMiddle(TileIndex t, Axis a)
{
- assert(IsBridgeMiddle(t));
- SetTileOwner(t, o);
- SB(_m[t].m5, 3, 3, 1 << 2 | TRANSPORT_ROAD);
- SB(_m[t].m3, 0, 4, 0);
+ assert(MayHaveBridgeAbove(t));
+ SETBIT(_m[t].extra, 6 + a);
}
@@ -200,26 +168,4 @@ static inline void MakeRailBridgeRamp(TileIndex t, Owner o, uint bridgetype, Dia
}
-static inline void MakeBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, TransportType tt)
-{
- SetTileType(t, MP_TUNNELBRIDGE);
- SetTileOwner(t, OWNER_NONE);
- _m[t].m2 = bridgetype << 4 | piece;
- _m[t].m3 = 0;
- _m[t].m4 = 0;
- _m[t].m5 = 1 << 7 | 1 << 6 | 0 << 5 | 0 << 3 | tt << 1 | a;
-}
-
-static inline void MakeRoadBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a)
-{
- MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_ROAD);
-}
-
-static inline void MakeRailBridgeMiddle(TileIndex t, uint bridgetype, uint piece, Axis a, RailType r)
-{
- MakeBridgeMiddle(t, bridgetype, piece, a, TRANSPORT_RAIL);
- SB(_m[t].m3, 4, 4, r);
-}
-
-
#endif
diff --git a/clear_cmd.c b/clear_cmd.c
index 259146965..ca4cfa24b 100644
--- a/clear_cmd.c
+++ b/clear_cmd.c
@@ -11,6 +11,7 @@
#include "viewport.h"
#include "command.h"
#include "tunnel_map.h"
+#include "bridge_map.h"
#include "variables.h"
#include "table/sprites.h"
#include "unmovable_map.h"
@@ -259,6 +260,14 @@ int32 CmdTerraformLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
} else return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
}
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
+ byte height = GetBridgeHeight(GetNorthernBridgeEnd(tile), GetBridgeAxis(tile));
+
+ height /= TILE_HEIGHT;
+
+ if (a >= height || b >= height || c >= height || d >= height) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+ }
+
if (direction == -1 && IsTunnelInWay(tile, min)) return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
_terraform_err_tile = 0;
@@ -501,6 +510,7 @@ static void DrawTile_Clear(TileInfo *ti)
}
DrawClearLandFence(ti);
+ DrawBridgeMiddle(ti);
}
static uint GetSlopeZ_Clear(const TileInfo* ti)
diff --git a/elrail.c b/elrail.c
index f0476d210..24bd2415a 100644
--- a/elrail.c
+++ b/elrail.c
@@ -91,18 +91,10 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
return DiagDirToAxis(GetTunnelDirection(t)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y;
} else {
if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
- if (IsBridgeMiddle(t)) {
- if (IsTransportUnderBridge(t) &&
- GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL) {
- return GetRailBitsUnderBridge(t);
- } else {
- return 0;
- }
- } else {
- if (override != NULL && DistanceMax(t, GetOtherBridgeEnd(t)) > 1) *override = 1 << GetBridgeRampDirection(t);
-
- return DiagDirToAxis(GetBridgeRampDirection(t)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y;
+ if (override != NULL && DistanceMax(t, GetOtherBridgeEnd(t)) > 1) {
+ *override = 1 << GetBridgeRampDirection(t);
}
+ return DiagDirToAxis(GetBridgeRampDirection(t)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y;
}
case MP_STREET:
if (GetRoadTileType(t) != ROAD_TILE_CROSSING) return 0;
@@ -125,7 +117,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
static void AdjustTileh(TileIndex tile, Slope* tileh)
{
if (IsTunnelTile(tile)) *tileh = SLOPE_FLAT;
- if (IsBridgeTile(tile) && IsBridgeRamp(tile)) {
+ if (IsBridgeTile(tile)) {
if (*tileh != SLOPE_FLAT) {
*tileh = SLOPE_FLAT;
} else {
@@ -193,9 +185,10 @@ static void DrawCatenaryRailway(const TileInfo *ti)
for (k = 0; k < NUM_TRACKS_AT_PCP; k++) {
/* Next to us, we have a bridge head, don't worry about that one, if it shows away from us */
if (TrackSourceTile[i][k] == TS_NEIGHBOUR &&
- IsBridgeTile(neighbour) && IsBridgeRamp(neighbour) &&
- GetBridgeRampDirection(neighbour) == ReverseDiagDir(i)
- ) continue;
+ IsBridgeTile(neighbour) &&
+ GetBridgeRampDirection(neighbour) == ReverseDiagDir(i)) {
+ continue;
+ }
/* We check whether the track in question (k) is present in the tile
(TrackSourceTile) */
@@ -219,7 +212,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
/* Read the foundataions if they are present, and adjust the tileh */
if (IsTileType(neighbour, MP_RAILWAY)) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
- if (IsBridgeTile(neighbour) && IsBridgeRamp(neighbour)) {
+ if (IsBridgeTile(neighbour)) {
foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
}
@@ -247,6 +240,14 @@ static void DrawCatenaryRailway(const TileInfo *ti)
Remove those (simply by ANDing with allowed, since these markers are never allowed) */
if ( (PPPallowed[i] & PPPpreferred[i]) != 0) PPPallowed[i] &= PPPpreferred[i];
+ if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile)) {
+ Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
+ uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile), GetBridgeAxis(ti->tile));
+
+ if ((height <= TilePixelHeight(ti->tile) + TILE_HEIGHT) &&
+ (i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) SETBIT(OverridePCP, i);
+ }
+
if (PPPallowed[i] != 0 && HASBIT(PCPstatus, i) && !HASBIT(OverridePCP, i)) {
for (k = 0; k < DIR_END; k++) {
byte temp = PPPorder[i][GetTLG(ti->tile)][k];
@@ -279,12 +280,11 @@ static void DrawCatenaryRailway(const TileInfo *ti)
const SortableSpriteStruct *sss;
int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; /* tileh for the slopes, 0 otherwise */
- if ( /* We are not drawing a wire under a low bridge */
- IsBridgeTile(ti->tile) &&
- IsBridgeMiddle(ti->tile) &&
- !(_display_opt & DO_TRANS_BUILDINGS) &&
- GetBridgeHeight(ti->tile) <= TilePixelHeight(ti->tile)
- ) return;
+ if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !(_display_opt & DO_TRANS_BUILDINGS)) {
+ uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile), GetBridgeAxis(ti->tile));
+
+ if (height <= TilePixelHeight(ti->tile) + TILE_HEIGHT) return;
+ }
assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
assert(!IsSteepSlope(tileh[TS_HOME]));
@@ -320,30 +320,37 @@ static void DrawCatenaryOnBridge(const TileInfo *ti)
}
AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
- sss->x_size, sss->y_size, sss->z_size, GetBridgeHeight(ti->tile) + sss->z_offset + 8);
+ sss->x_size, sss->y_size, sss->z_size, GetBridgeHeight(end, axis) + sss->z_offset);
/* Finished with wires, draw pylons */
/* every other tile needs a pylon on the northern end */
if (num % 2) {
if (axis == AXIS_X) {
- AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
+ AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(end, axis));
} else {
- AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
+ AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, GetBridgeHeight(end, axis));
}
}
/* need a pylon on the southern end of the bridge */
if (DistanceMax(ti->tile, start) == length) {
if (axis == AXIS_X) {
- AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
+ AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(end, axis));
} else {
- AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
+ AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, GetBridgeHeight(end, axis));
}
}
}
void DrawCatenary(const TileInfo *ti)
{
+ if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile)) {
+ TileIndex head = GetNorthernBridgeEnd(ti->tile);
+
+ if (GetBridgeTransportType(head) == TRANSPORT_RAIL && GetRailType(head) == RAILTYPE_ELECTRIC) {
+ DrawCatenaryOnBridge(ti);
+ }
+ }
switch (GetTileType(ti->tile)) {
case MP_RAILWAY:
if (GetRailTileType(ti->tile) == RAIL_TILE_DEPOT_WAYPOINT && GetRailTileSubtype(ti->tile) == RAIL_SUBTYPE_DEPOT) {
@@ -354,9 +361,8 @@ void DrawCatenary(const TileInfo *ti)
}
/* Fall through */
case MP_TUNNELBRIDGE:
- if (IsBridgeTile(ti->tile) && IsBridgeMiddle(ti->tile) && GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenaryOnBridge(ti);
- /* Fall further */
- case MP_STREET: case MP_STATION:
+ case MP_STREET:
+ case MP_STATION:
DrawCatenaryRailway(ti);
break;
default:
diff --git a/landscape.c b/landscape.c
index cc044eab2..1209940f2 100644
--- a/landscape.c
+++ b/landscape.c
@@ -2,6 +2,7 @@
#include "stdafx.h"
#include "openttd.h"
+#include "bridge_map.h"
#include "clear_map.h"
#include "functions.h"
#include "map.h"
@@ -387,6 +388,8 @@ void InitializeLandscape(void)
for (x = 0; x < maxx; x++) {
MakeClear(sizex * y + x, CLEAR_GRASS, 3);
SetTileHeight(sizex * y + x, 0);
+ _m[sizex * y + x].extra = 0;
+ ClearBridgeMiddle(sizex * y + x);
}
MakeVoid(sizex * y + x);
}
diff --git a/misc.c b/misc.c
index 71e9e25fa..689340d3d 100644
--- a/misc.c
+++ b/misc.c
@@ -859,16 +859,26 @@ static void Load_MAPE(void)
uint size = MapSize();
uint i;
- for (i = 0; i != size;) {
- uint8 buf[1024];
- uint j;
+ if (CheckSavegameVersion(29)) {
+ for (i = 0; i != size;) {
+ uint8 buf[1024];
+ uint j;
+
+ SlArray(buf, lengthof(buf), SLE_UINT8);
+ for (j = 0; j != lengthof(buf); j++) {
+ _m[i++].extra = GB(buf[j], 0, 2);
+ _m[i++].extra = GB(buf[j], 2, 2);
+ _m[i++].extra = GB(buf[j], 4, 2);
+ _m[i++].extra = GB(buf[j], 6, 2);
+ }
+ }
+ } else {
+ for (i = 0; i != size;) {
+ byte buf[4096];
+ uint j;
- SlArray(buf, lengthof(buf), SLE_UINT8);
- for (j = 0; j != lengthof(buf); j++) {
- _m[i++].extra = GB(buf[j], 0, 2);
- _m[i++].extra = GB(buf[j], 2, 2);
- _m[i++].extra = GB(buf[j], 4, 2);
- _m[i++].extra = GB(buf[j], 6, 2);
+ SlArray(buf, lengthof(buf), SLE_UINT8);
+ for (j = 0; j != lengthof(buf); j++) _m[i++].extra = buf[j];
}
}
}
@@ -878,17 +888,12 @@ static void Save_MAPE(void)
uint size = MapSize();
uint i;
- SlSetLength(size / 4);
+ SlSetLength(size);
for (i = 0; i != size;) {
- uint8 buf[1024];
+ uint8 buf[4096];
uint j;
- for (j = 0; j != lengthof(buf); j++) {
- buf[j] = _m[i++].extra << 0;
- buf[j] |= _m[i++].extra << 2;
- buf[j] |= _m[i++].extra << 4;
- buf[j] |= _m[i++].extra << 6;
- }
+ for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].extra;
SlArray(buf, lengthof(buf), SLE_UINT8);
}
}
diff --git a/npf.c b/npf.c
index d13c36007..346405ef0 100644
--- a/npf.c
+++ b/npf.c
@@ -479,17 +479,7 @@ static bool VehicleMayEnterTile(Owner owner, TileIndex tile, DiagDirection enter
case MP_TUNNELBRIDGE:
if ((IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) ||
- (IsBridge(tile) && (
- (
- IsBridgeRamp(tile) &&
- GetBridgeTransportType(tile) == TRANSPORT_RAIL
- ) || (
- IsBridgeMiddle(tile) &&
- IsTransportUnderBridge(tile) &&
- GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL &&
- GetBridgeAxis(tile) != DiagDirToAxis(enterdir)
- )
- ))) {
+ (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL)) {
return IsTileOwner(tile, owner);
}
break;
@@ -516,6 +506,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
int i;
TrackdirBits trackdirbits, ts;
TransportType type = aystar->user_data[NPF_TYPE];
+ bool override_dst_check = false;
/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
aystar->num_neighbours = 0;
DEBUG(npf, 4)("Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile);
@@ -526,6 +517,10 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
* otherwise we wouldn't have got here. It is also facing us,
* so we should skip it's body */
dst_tile = GetOtherTunnelEnd(src_tile);
+ override_dst_check = true;
+ } else if (IsBridgeTile(src_tile) && GetBridgeRampDirection(src_tile) == src_exitdir) {
+ dst_tile = GetOtherBridgeEnd(src_tile);
+ override_dst_check = true;
} else if (type != TRANSPORT_WATER && (IsRoadStopTile(src_tile) || IsTileDepotType(src_tile, type))) {
/* This is a road station or a train or road depot. We can enter and exit
* those from one side only. Trackdirs don't support that (yet), so we'll
@@ -573,8 +568,14 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
/* I can't enter a tunnel entry/exit tile from a tile above the tunnel. Note
* that I can enter the tunnel from a tile below the tunnel entrance. This
* solves the problem of vehicles wanting to drive off a tunnel entrance */
- if (IsTunnelTile(dst_tile) && GetTileZ(dst_tile) < GetTileZ(src_tile)) {
- return;
+ if (!override_dst_check) {
+ if (IsTileType(dst_tile, MP_TUNNELBRIDGE)) {
+ if (IsTunnel(dst_tile)) {
+ if (GetTunnelDirection(dst_tile) != src_exitdir) return;
+ } else {
+ if (GetBridgeRampDirection(dst_tile) != src_exitdir) return;
+ }
+ }
}
/* check correct rail type (mono, maglev, etc) */
diff --git a/openttd.c b/openttd.c
index 0589f84b7..7cef648e3 100644
--- a/openttd.c
+++ b/openttd.c
@@ -49,6 +49,12 @@
#include "yapf/yapf.h"
#include "settings.h"
+#include "bridge_map.h"
+#include "clear_map.h"
+#include "rail_map.h"
+#include "road_map.h"
+#include "water_map.h"
+
#include <stdarg.h>
void GenerateWorld(int mode, uint size_x, uint size_y);
@@ -1256,6 +1262,72 @@ bool AfterLoadGame(void)
}
}
+ if (CheckSavegameVersion(29)) {
+ TileIndex map_end = MapSize();
+ TileIndex tile;
+ Vehicle* v;
+
+ for (tile = 0; tile != map_end; tile++) {
+ if (MayHaveBridgeAbove(tile)) ClearBridgeMiddle(tile);
+ if (IsTileType(tile, MP_TUNNELBRIDGE) &&
+ _m[tile].m5 & 0x80 && // bridge
+ _m[tile].m5 & 0x40) { // middle part
+ Axis axis = (Axis)GB(_m[tile].m5, 0, 1);
+
+ if (_m[tile].m5 & 0x20) { // transport route under bridge?
+ if (GB(_m[tile].m5, 3, 2) == TRANSPORT_RAIL) {
+ MakeRailNormal(
+ tile,
+ GetTileOwner(tile),
+ axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X,
+ GetRailType(tile)
+ );
+ } else {
+ uint town = IsTileOwner(tile, OWNER_TOWN) ? ClosestTownFromTile(tile, (uint)-1)->index : 0;
+
+ MakeRoadNormal(
+ tile,
+ GetTileOwner(tile),
+ axis == AXIS_X ? ROAD_Y : ROAD_X,
+ town
+ );
+ }
+ } else {
+ if (GB(_m[tile].m5, 3, 2) == 0) {
+ MakeClear(tile, CLEAR_GRASS, 3);
+ } else {
+ MakeWater(tile);
+ }
+ }
+ SetBridgeMiddle(tile, axis);
+ }
+ }
+
+ FOR_ALL_VEHICLES(v) {
+ if (v->type != VEH_Train && v->type != VEH_Road) continue;
+ if (IsBridgeTile(v->tile)) {
+ DiagDirection dir = GetBridgeRampDirection(v->tile);
+
+ if (dir != DirToDiagDir(v->direction)) continue;
+ switch (dir) {
+ default:
+ case DIAGDIR_NE: if ((v->x_pos & 0xF) != 0) continue;
+ case DIAGDIR_SE: if ((v->y_pos & 0xF) != 15) continue;
+ case DIAGDIR_SW: if ((v->x_pos & 0xF) != 15) continue;
+ case DIAGDIR_NW: if ((v->y_pos & 0xF) != 0) continue;
+ }
+ } else if (v->z_pos <= GetSlopeZ(v->x_pos, v->y_pos)) {
+ continue;
+ }
+ if (!IsBridgeTile(v->tile)) v->tile = GetNorthernBridgeEnd(v->tile);
+ if (v->type == VEH_Train) {
+ v->u.rail.track = 0x40;
+ } else {
+ v->u.road.state = 0xFF;
+ }
+ }
+ }
+
/* Elrails got added in rev 24 */
if (CheckSavegameVersion(24)) {
Vehicle* v;
@@ -1306,15 +1378,6 @@ bool AfterLoadGame(void)
}
} else {
if (GetBridgeTransportType(t) == TRANSPORT_RAIL) {
- if (IsBridgeRamp(t)) {
- SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
- } else {
- SetRailTypeOnBridge(t, UpdateRailType(GetRailTypeOnBridge(t), min_rail));
- }
- }
- if (IsBridgeMiddle(t) &&
- IsTransportUnderBridge(t) &&
- GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL) {
SetRailType(t, UpdateRailType(GetRailType(t), min_rail));
}
}
diff --git a/pathfind.c b/pathfind.c
index 622b820f0..77bc9804a 100644
--- a/pathfind.c
+++ b/pathfind.c
@@ -256,21 +256,27 @@ static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection directi
RememberData rd;
TileIndex tile_org = tile;
- // check if the old tile can be left at that direction
- if (tpf->tracktype == TRANSPORT_ROAD) {
- // road stops and depots now have a track (r4419)
- // don't enter road stop from the back
- if (IsRoadStopTile(tile) && GetRoadStopDir(tile) != direction) return;
- // don't enter road depot from the back
- if (IsTileDepotType(tile, TRANSPORT_ROAD) && GetRoadDepotDirection(tile) != direction) return;
- }
-
- if (IsTunnelTile(tile)) {
- if (GetTunnelDirection(tile) != direction ||
- GetTunnelTransportType(tile) != tpf->tracktype) {
- return;
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ if (IsTunnel(tile)) {
+ if (GetTunnelDirection(tile) != direction ||
+ GetTunnelTransportType(tile) != tpf->tracktype) {
+ return;
+ }
+ tile = SkipToEndOfTunnel(tpf, tile, direction);
+ } else {
+ TileIndex tile_end;
+ if (GetBridgeRampDirection(tile) != direction ||
+ GetBridgeTransportType(tile) != tpf->tracktype) {
+ return;
+ }
+ //fprintf(stderr, "%s: Planning over bridge\n", __func__);
+ // TODO doesn't work - WHAT doesn't work?
+ TPFSetTileBit(tpf, tile, 14);
+ tile_end = GetOtherBridgeEnd(tile);
+ tpf->rd.cur_length += DistanceManhattan(tile, tile_end);
+ tile = tile_end;
+ TPFSetTileBit(tpf, tile, 14);
}
- tile = SkipToEndOfTunnel(tpf, tile, direction);
}
tile += TileOffsByDir(direction);
@@ -281,11 +287,7 @@ static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection directi
if (IsTileType(tile_org, MP_RAILWAY) || IsTileType(tile_org, MP_STATION) || IsTileType(tile_org, MP_TUNNELBRIDGE))
if (IsTileType(tile, MP_RAILWAY) || IsTileType(tile, MP_STATION) || IsTileType(tile, MP_TUNNELBRIDGE))
- /* Check if we are on a bridge (middle parts don't have an owner */
- if (!IsBridgeTile(tile) || !IsBridgeMiddle(tile))
- if (!IsBridgeTile(tile_org) || !IsBridgeMiddle(tile_org))
- if (GetTileOwner(tile_org) != GetTileOwner(tile))
- return;
+ if (GetTileOwner(tile_org) != GetTileOwner(tile)) return;
}
// check if the new tile can be entered from that direction
@@ -673,7 +675,6 @@ static void NTPEnum(NewTrackPathFinder* tpf, TileIndex tile, DiagDirection direc
uint track;
TileIndex tile_org;
StackedItem si;
- FindLengthOfTunnelResult flotr;
int estimation;
@@ -711,22 +712,40 @@ callback_and_continue:
start_at:
// If the tile is the entry tile of a tunnel, and we're not going out of the tunnel,
// need to find the exit of the tunnel.
- if (IsTunnelTile(tile) &&
- GetTunnelDirection(tile) != ReverseDiagDir(direction)) {
- /* We are not just driving out of the tunnel */
- if (GetTunnelDirection(tile) != direction ||
- GetTunnelTransportType(tile) != tpf->tracktype) {
- // We are not driving into the tunnel, or it is an invalid tunnel
- continue;
- }
- if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
- bits = 0;
- break;
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ if (IsTunnel(tile)) {
+ if (GetTunnelDirection(tile) != ReverseDiagDir(direction)) {
+ FindLengthOfTunnelResult flotr;
+
+ /* We are not just driving out of the tunnel */
+ if (GetTunnelDirection(tile) != direction ||
+ GetTunnelTransportType(tile) != tpf->tracktype) {
+ // We are not driving into the tunnel, or it is an invalid tunnel
+ continue;
+ }
+ if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
+ bits = 0;
+ break;
+ }
+ flotr = FindLengthOfTunnel(tile, direction);
+ si.cur_length += flotr.length * DIAG_FACTOR;
+ tile = flotr.tile;
+ // tile now points to the exit tile of the tunnel
+ }
+ } else {
+ TileIndex tile_end;
+ if (GetBridgeRampDirection(tile) != ReverseDiagDir(direction)) {
+ // We are not just leaving the bridge
+ if (GetBridgeRampDirection(tile) != direction ||
+ GetBridgeTransportType(tile) != tpf->tracktype) {
+ // Not entering the bridge or not compatible
+ continue;
+ }
+ }
+ tile_end = GetOtherBridgeEnd(tile);
+ si.cur_length += DistanceManhattan(tile, tile_end) * DIAG_FACTOR;
+ tile = tile_end;
}
- flotr = FindLengthOfTunnel(tile, direction);
- si.cur_length += flotr.length * DIAG_FACTOR;
- tile = flotr.tile;
- // tile now points to the exit tile of the tunnel
}
// This is a special loop used to go through
@@ -754,13 +773,9 @@ start_at:
// Check that the tile contains exactly one track
if (bits == 0 || KILL_FIRST_BIT(bits) != 0) break;
- /* Check the rail type only if the train is *NOT* on top of
- * a bridge. */
- if (!(IsBridgeTile(tile) && IsBridgeMiddle(tile) && GetBridgeAxis(tile) == DiagDirToAxis(direction))) {
- if (IsTileType(tile, MP_STREET) ? !HASBIT(tpf->railtypes, GetRailTypeCrossing(tile)) : !HASBIT(tpf->railtypes, GetRailType(tile))) {
- bits = 0;
- break;
- }
+ if (IsTileType(tile, MP_STREET) ? !HASBIT(tpf->railtypes, GetRailTypeCrossing(tile)) : !HASBIT(tpf->railtypes, GetRailType(tile))) {
+ bits = 0;
+ break;
}
///////////////////
diff --git a/rail.c b/rail.c
index 5b6650667..aa2865cb3 100644
--- a/rail.c
+++ b/rail.c
@@ -104,7 +104,6 @@ const Trackdir _dir_to_diag_trackdir[] = {
RailType GetTileRailType(TileIndex tile, Trackdir trackdir)
{
- DiagDirection exitdir = TrackdirToExitdir(trackdir);
switch (GetTileType(tile)) {
case MP_RAILWAY:
return GetRailType(tile);
@@ -124,21 +123,8 @@ RailType GetTileRailType(TileIndex tile, Trackdir trackdir)
return GetRailType(tile);
}
} else {
- if (IsBridgeRamp(tile)) {
- if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
- return GetRailType(tile);
- }
- } else {
- if (GetBridgeAxis(tile) == DiagDirToAxis(exitdir)) {
- if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
- return GetRailTypeOnBridge(tile);
- }
- } else {
- if (IsTransportUnderBridge(tile) &&
- GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
- return GetRailType(tile);
- }
- }
+ if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
+ return GetRailType(tile);
}
}
break;
diff --git a/rail_cmd.c b/rail_cmd.c
index 8e7792601..61e316af2 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -231,29 +231,6 @@ int32 CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
switch (GetTileType(tile)) {
- case MP_TUNNELBRIDGE:
- if (!IsBridge(tile) ||
- !IsBridgeMiddle(tile) ||
- (GetBridgeAxis(tile) == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) != trackbit) {
- // Get detailed error message
- return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
- }
-
- if (IsClearUnderBridge(tile)) {
- ret = CheckRailSlope(tileh, trackbit, 0, tile);
- if (CmdFailed(ret)) return ret;
- cost += ret;
-
- if (flags & DC_EXEC) SetRailUnderBridge(tile, _current_player, p1);
- } else if (IsTransportUnderBridge(tile) &&
- GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
- return_cmd_error(STR_1007_ALREADY_BUILT);
- } else {
- // Get detailed error message
- return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
- }
- break;
-
case MP_RAILWAY:
if (!CheckTrackCombination(tile, trackbit, flags) ||
!EnsureNoVehicle(tile)) {
@@ -341,20 +318,6 @@ int32 CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
switch (GetTileType(tile)) {
- case MP_TUNNELBRIDGE:
- if (!IsBridge(tile) ||
- !IsBridgeMiddle(tile) ||
- !IsTransportUnderBridge(tile) ||
- GetTransportTypeUnderBridge(tile) != TRANSPORT_RAIL ||
- GetRailBitsUnderBridge(tile) != trackbit ||
- (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
- !EnsureNoVehicleOnGround(tile)) {
- return CMD_ERROR;
- }
-
- if (flags & DC_EXEC) SetClearUnderBridge(tile);
- break;
-
case MP_STREET: {
if (!IsLevelCrossing(tile) ||
GetCrossingRailBits(tile) != trackbit ||
@@ -591,6 +554,8 @@ int32 CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (CmdFailed(ret)) return CMD_ERROR;
cost = ret;
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
d = AllocateDepot();
if (d == NULL) return CMD_ERROR;
@@ -1416,6 +1381,7 @@ static void DrawTile_Track(TileInfo *ti)
);
}
}
+ DrawBridgeMiddle(ti);
}
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype)
@@ -1525,19 +1491,11 @@ typedef struct SignalVehicleCheckStruct {
static void *SignalVehicleCheckProc(Vehicle *v, void *data)
{
const SignalVehicleCheckStruct* dest = data;
- TileIndex tile;
if (v->type != VEH_Train) return NULL;
- /* Find the tile outside the tunnel, for signalling */
- if (v->u.rail.track == 0x40) {
- tile = GetVehicleOutOfTunnelTile(v);
- } else {
- tile = v->tile;
- }
-
/* Wrong tile, or no train? Not a match */
- if (tile != dest->tile) return NULL;
+ if (v->tile != dest->tile) return NULL;
/* Are we on the same piece of track? */
if (dest->track & (v->u.rail.track + (v->u.rail.track << 8))) return v;
@@ -1553,15 +1511,18 @@ static bool SignalVehicleCheck(TileIndex tile, uint track)
dest.tile = tile;
dest.track = track;
- /** @todo "Hackish" fix for the tunnel problems. This is needed because a tunnel
- * is some kind of invisible black hole, and there is some special magic going
- * on in there. This 'workaround' can be removed once the maprewrite is done.
- */
- if (IsTunnelTile(tile)) {
- // It is a tunnel we're checking, we need to do some special stuff
- // because VehicleFromPos will not find the vihicle otherwise
- TileIndex end = GetOtherTunnelEnd(tile);
- DiagDirection direction = GetTunnelDirection(tile);
+ /* Locate vehicles in tunnels or on bridges */
+ if (IsTunnelTile(tile) || IsBridgeTile(tile)) {
+ TileIndex end;
+ DiagDirection direction;
+
+ if (IsTunnelTile(tile)) {
+ end = GetOtherTunnelEnd(tile);
+ direction = GetTunnelDirection(tile);
+ } else {
+ end = GetOtherBridgeEnd(tile);
+ direction = GetBridgeRampDirection(tile);
+ }
dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible)
@@ -1571,9 +1532,9 @@ static bool SignalVehicleCheck(TileIndex tile, uint track)
// check for a vehicle with that trackdir on the end tile of the tunnel
if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
- // now check all tiles from start to end for a "hidden" vehicle
+ // now check all tiles from start to end for a warping vehicle
// NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile?
- dest.track = 0x40; // trackbit for vehicles "hidden" inside a tunnel
+ dest.track = 0x40;
for (; tile != end; tile += TileOffsByDir(direction)) {
if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL)
return true;
diff --git a/rail_map.h b/rail_map.h
index 44a42f9aa..43166d671 100644
--- a/rail_map.h
+++ b/rail_map.h
@@ -81,11 +81,6 @@ static inline RailType GetRailTypeCrossing(TileIndex t)
return (RailType)GB(_m[t].m4, 0, 4);
}
-static inline RailType GetRailTypeOnBridge(TileIndex t)
-{
- return (RailType)GB(_m[t].m3, 4, 4);
-}
-
static inline void SetRailType(TileIndex t, RailType r)
{
SB(_m[t].m3, 0, 4, r);
@@ -97,11 +92,6 @@ static inline void SetRailTypeCrossing(TileIndex t, RailType r)
SB(_m[t].m4, 0, 4, r);
}
-static inline void SetRailTypeOnBridge(TileIndex t, RailType r)
-{
- SB(_m[t].m3, 4, 4, r);
-}
-
/** These are used to specify a single track.
* Can be translated to a trackbit with TrackToTrackbit */
diff --git a/road_cmd.c b/road_cmd.c
index 832ca7a24..30f683b41 100644
--- a/road_cmd.c
+++ b/road_cmd.c
@@ -108,97 +108,70 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (p1 >> 4) return CMD_ERROR;
pieces = p1;
- if (!IsTileType(tile, MP_STREET) && !IsTileType(tile, MP_TUNNELBRIDGE)) return CMD_ERROR;
+ if (!IsTileType(tile, MP_STREET)) return CMD_ERROR;
owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile);
if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
- if (IsTileType(tile, MP_TUNNELBRIDGE)) { // index of town is not saved for bridge (no space)
- t = ClosestTownFromTile(tile, _patches.dist_local_authority);
- } else {
- t = GetTownByTile(tile);
- }
+ t = GetTownByTile(tile);
} else {
t = NULL;
}
if (!CheckAllowRemoveRoad(tile, pieces, &edge_road)) return CMD_ERROR;
- switch (GetTileType(tile)) {
- case MP_TUNNELBRIDGE:
- if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
-
- if (!IsBridge(tile) ||
- !IsBridgeMiddle(tile) ||
- !IsTransportUnderBridge(tile) ||
- GetTransportTypeUnderBridge(tile) != TRANSPORT_ROAD ||
- (pieces & ComplementRoadBits(GetRoadBitsUnderBridge(tile))) != 0) {
- return CMD_ERROR;
- }
-
- if (flags & DC_EXEC) {
- ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
- SetClearUnderBridge(tile);
- MarkTileDirtyByTile(tile);
- }
- return _price.remove_road * 2;
+ if (!EnsureNoVehicle(tile)) return CMD_ERROR;
- case MP_STREET:
- if (!EnsureNoVehicle(tile)) return CMD_ERROR;
+ // check if you're allowed to remove the street owned by a town
+ // removal allowance depends on difficulty setting
+ if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
- // check if you're allowed to remove the street owned by a town
- // removal allowance depends on difficulty setting
- if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
+ switch (GetRoadTileType(tile)) {
+ case ROAD_TILE_NORMAL: {
+ RoadBits present = GetRoadBits(tile);
+ RoadBits c = pieces;
- switch (GetRoadTileType(tile)) {
- case ROAD_TILE_NORMAL: {
- RoadBits present = GetRoadBits(tile);
- RoadBits c = pieces;
-
- if (GetTileSlope(tile, NULL) != SLOPE_FLAT &&
- (present == ROAD_Y || present == ROAD_X)) {
- c |= (c & 0xC) >> 2;
- c |= (c & 0x3) << 2;
- }
+ if (GetTileSlope(tile, NULL) != SLOPE_FLAT &&
+ (present == ROAD_Y || present == ROAD_X)) {
+ c |= (c & 0xC) >> 2;
+ c |= (c & 0x3) << 2;
+ }
- // limit the bits to delete to the existing bits.
- c &= present;
- if (c == 0) return CMD_ERROR;
+ // limit the bits to delete to the existing bits.
+ c &= present;
+ if (c == 0) return CMD_ERROR;
- if (flags & DC_EXEC) {
- ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+ if (flags & DC_EXEC) {
+ ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
- present ^= c;
- if (present == 0) {
- DoClearSquare(tile);
- } else {
- SetRoadBits(tile, present);
- MarkTileDirtyByTile(tile);
- }
- }
- return CountRoadBits(c) * _price.remove_road;
+ present ^= c;
+ if (present == 0) {
+ DoClearSquare(tile);
+ } else {
+ SetRoadBits(tile, present);
+ MarkTileDirtyByTile(tile);
}
+ }
+ return CountRoadBits(c) * _price.remove_road;
+ }
- case ROAD_TILE_CROSSING: {
- if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
- return CMD_ERROR;
- }
-
- if (flags & DC_EXEC) {
- ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+ case ROAD_TILE_CROSSING: {
+ if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
+ return CMD_ERROR;
+ }
- MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailTypeCrossing(tile));
- MarkTileDirtyByTile(tile);
- }
- return _price.remove_road * 2;
- }
+ if (flags & DC_EXEC) {
+ ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
- default:
- case ROAD_TILE_DEPOT:
- return CMD_ERROR;
+ MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailTypeCrossing(tile));
+ MarkTileDirtyByTile(tile);
}
+ return _price.remove_road * 2;
+ }
- default: return CMD_ERROR;
+ case ROAD_TILE_DEPOT:
+ default:
+ return CMD_ERROR;
}
}
@@ -348,37 +321,6 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
return _price.build_road * 2;
}
- case MP_TUNNELBRIDGE:
- /* check for flat land */
- if (IsSteepSlope(tileh)) {
- return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
- }
-
- if (!IsBridge(tile) || !IsBridgeMiddle(tile)) goto do_clear;
-
- /* only allow roads pertendicular to bridge */
- if ((pieces & (GetBridgeAxis(tile) == AXIS_X ? ROAD_X : ROAD_Y)) != 0) {
- goto do_clear;
- }
-
- /* check if clear land under bridge */
- if (IsTransportUnderBridge(tile)) {
- switch (GetTransportTypeUnderBridge(tile)) {
- case TRANSPORT_ROAD: return_cmd_error(STR_1007_ALREADY_BUILT);
- default: return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
- }
- } else {
- if (IsWaterUnderBridge(tile)) {
- return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
- }
- }
-
- if (flags & DC_EXEC) {
- SetRoadUnderBridge(tile, _current_player);
- MarkTileDirtyByTile(tile);
- }
- return _price.build_road * 2;
-
default:
do_clear:;
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -575,6 +517,8 @@ int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(cost)) return CMD_ERROR;
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
dep = AllocateDepot();
if (dep == NULL) return CMD_ERROR;
@@ -798,6 +742,7 @@ static void DrawTile_Road(TileInfo *ti)
break;
}
}
+ DrawBridgeMiddle(ti);
}
void DrawRoadDepotSprite(int x, int y, int image)
diff --git a/road_map.c b/road_map.c
index 8702f7692..1c1040476 100644
--- a/road_map.c
+++ b/road_map.c
@@ -27,22 +27,12 @@ RoadBits GetAnyRoadBits(TileIndex tile)
return DiagDirToRoadBits(GetRoadStopDir(tile));
case MP_TUNNELBRIDGE:
- if (IsBridge(tile)) {
- if (IsBridgeMiddle(tile)) {
- if (!IsTransportUnderBridge(tile) ||
- GetBridgeTransportType(tile) != TRANSPORT_ROAD) {
- return 0;
- }
- return GetRoadBitsUnderBridge(tile);
- } else {
- // ending
- if (GetBridgeTransportType(tile) != TRANSPORT_ROAD) return 0;
- return DiagDirToRoadBits(ReverseDiagDir(GetBridgeRampDirection(tile)));
- }
- } else {
- // tunnel
+ if (IsTunnel(tile)) {
if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) return 0;
return DiagDirToRoadBits(ReverseDiagDir(GetTunnelDirection(tile)));
+ } else {
+ if (GetBridgeTransportType(tile) != TRANSPORT_ROAD) return 0;
+ return DiagDirToRoadBits(ReverseDiagDir(GetBridgeRampDirection(tile)));
}
default: return 0;
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index 6a7a62c82..e57a4aaef 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -20,7 +20,9 @@
#include "player.h"
#include "sound.h"
#include "depot.h"
+#include "bridge.h"
#include "tunnel_map.h"
+#include "bridge_map.h"
#include "vehicle_gui.h"
#include "newgrf_engine.h"
#include "yapf/yapf.h"
@@ -313,8 +315,6 @@ static const Depot* FindClosestRoadDepot(const Vehicle* v)
{
TileIndex tile = v->tile;
- if (v->u.road.state == 255) tile = GetVehicleOutOfTunnelTile(v);
-
if (_patches.yapf.road_use_yapf) {
Depot* ret = YapfFindNearestRoadDepot(v);
return ret;
@@ -411,14 +411,19 @@ int32 CmdTurnRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR;
- if (v->vehstatus & (VS_HIDDEN | VS_STOPPED) ||
+ if (v->vehstatus & VS_STOPPED ||
v->u.road.crashed_ctr != 0 ||
v->breakdown_ctr != 0 ||
v->u.road.overtaking != 0 ||
+ v->u.road.state == 255 ||
+ v->u.road.state == 254 ||
v->cur_speed < 5) {
return CMD_ERROR;
}
+ if (IsTunnelTile(v->tile) && DirToDiagDir(v->direction) == GetTunnelDirection(v->tile)) return CMD_ERROR;
+ if (IsBridgeTile(v->tile) && DirToDiagDir(v->direction) == GetBridgeRampDirection(v->tile)) return CMD_ERROR;
+
if (flags & DC_EXEC) v->u.road.reverse_ctr = 180;
return 0;
@@ -485,11 +490,9 @@ static byte SetRoadVehPosition(Vehicle *v, int x, int y)
byte new_z, old_z;
// need this hint so it returns the right z coordinate on bridges.
- _get_z_hint = v->z_pos;
v->x_pos = x;
v->y_pos = y;
new_z = GetSlopeZ(x, y);
- _get_z_hint = 0;
old_z = v->z_pos;
v->z_pos = new_z;
@@ -824,6 +827,7 @@ static bool RoadVehAccelerate(Vehicle *v)
// Clamp
spd = min(spd, v->max_speed);
+ if (v->u.road.state == 255) spd = min(spd, SetSpeedLimitOnBridge(v));
//updates statusbar only if speed have changed to save CPU time
if (spd != v->cur_speed) {
@@ -1285,8 +1289,7 @@ static void RoadVehController(Vehicle *v)
return;
}
- if (IsTunnelTile(gp.new_tile) &&
- VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 4) {
+ if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 4) {
//new_dir = RoadGetNewDirection(v, gp.x, gp.y)
v->cur_image = GetRoadVehImage(v, v->direction);
UpdateRoadVehDeltaXY(v);
@@ -1297,6 +1300,7 @@ static void RoadVehController(Vehicle *v)
v->x_pos = gp.x;
v->y_pos = gp.y;
VehiclePositionChanged(v);
+ if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
return;
}
diff --git a/saveload.c b/saveload.c
index 4f6854a96..48535b18b 100644
--- a/saveload.c
+++ b/saveload.c
@@ -30,7 +30,7 @@
#include "variables.h"
#include <setjmp.h>
-const uint16 SAVEGAME_VERSION = 28;
+const uint16 SAVEGAME_VERSION = 29;
uint16 _sl_version; /// the major savegame version identifier
byte _sl_minor_version; /// the minor savegame version, DO NOT USE!
diff --git a/station_cmd.c b/station_cmd.c
index 0339ec0a6..dfd8df362 100644
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -5,6 +5,7 @@
#include "stdafx.h"
#include "openttd.h"
+#include "bridge_map.h"
#include "debug.h"
#include "functions.h"
#include "station_map.h"
@@ -782,6 +783,10 @@ int32 CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint invali
int flat_z;
BEGIN_TILE_LOOP(tile_cur, w, h, tile)
+ if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) {
+ return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+ }
+
if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
tileh = GetTileSlope(tile_cur, &z);
diff --git a/table/sprites.h b/table/sprites.h
index c74239e35..1af230eca 100644
--- a/table/sprites.h
+++ b/table/sprites.h
@@ -708,6 +708,27 @@ enum Sprites {
SPR_BTTUB_X_RAIL_REAR_BEG = 2569,
SPR_BTTUB_X_RAIL_REAR_MID = 2570,
SPR_BTTUB_X_RAIL_REAR_END = 2571,
+ SPR_BTTUB_Y_RAIL_REAR_BEG = 2572,
+ SPR_BTTUB_Y_RAIL_REAR_MID = 2573,
+ SPR_BTTUB_Y_RAIL_REAR_END = 2574,
+ SPR_BTTUB_X_ROAD_REAR_BEG = 2575,
+ SPR_BTTUB_X_ROAD_REAR_MID = 2576,
+ SPR_BTTUB_X_ROAD_REAR_END = 2577,
+ SPR_BTTUB_Y_ROAD_REAR_BEG = 2578,
+ SPR_BTTUB_Y_ROAD_REAR_MID = 2579,
+ SPR_BTTUB_Y_ROAD_REAR_END = 2580,
+ SPR_BTTUB_X_MONO_REAR_BEG = 2581,
+ SPR_BTTUB_X_MONO_REAR_MID = 2582,
+ SPR_BTTUB_X_MONO_REAR_END = 2583,
+ SPR_BTTUB_Y_MONO_REAR_BEG = 2584,
+ SPR_BTTUB_Y_MONO_REAR_MID = 2585,
+ SPR_BTTUB_Y_MONO_REAR_END = 2586,
+ SPR_BTTUB_X_MGLV_REAR_BEG = 2587,
+ SPR_BTTUB_X_MGLV_REAR_MID = 2588,
+ SPR_BTTUB_X_MGLV_REAR_END = 2589,
+ SPR_BTTUB_Y_MGLV_REAR_BEG = 2590,
+ SPR_BTTUB_Y_MGLV_REAR_MID = 2591,
+ SPR_BTTUB_Y_MGLV_REAR_END = 2592,
/* ramps (for all bridges except wood and tubular?)*/
diff --git a/terraform_gui.c b/terraform_gui.c
index 72b2a53a7..571f1298e 100644
--- a/terraform_gui.c
+++ b/terraform_gui.c
@@ -2,6 +2,7 @@
#include "stdafx.h"
#include "openttd.h"
+#include "bridge_map.h"
#include "clear_map.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -81,11 +82,20 @@ static void GenerateRockyArea(TileIndex end, TileIndex start)
size_y = (ey - sy) + 1;
BEGIN_TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
- if (IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES)) {
- MakeClear(tile, CLEAR_ROCKS, 3);
- MarkTileDirtyByTile(tile);
- success = true;
+ switch (GetTileType(tile)) {
+ case MP_CLEAR:
+ MakeClear(tile, CLEAR_ROCKS, 3);
+ break;
+
+ case MP_TREES:
+ MakeClear(tile, CLEAR_ROCKS, 3);
+ ClearBridgeMiddle(tile);
+ break;
+
+ default: continue;
}
+ MarkTileDirtyByTile(tile);
+ success = true;
} END_TILE_LOOP(tile, size_x, size_y, 0);
if (success) SndPlayTileFx(SND_1F_SPLAT, end);
diff --git a/town_cmd.c b/town_cmd.c
index 2c7a8653c..590641406 100644
--- a/town_cmd.c
+++ b/town_cmd.c
@@ -26,6 +26,7 @@
#include "water_map.h"
#include "variables.h"
#include "bridge.h"
+#include "bridge_map.h"
#include "table/town_land.h"
enum {
@@ -1093,6 +1094,8 @@ static bool CheckBuildHouseMode(TileIndex tile, Slope tileh, int mode)
slope = GetTileSlope(tile, NULL);
if (IsSteepSlope(slope)) return false;
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false;
+
b = 0;
if ((slope != SLOPE_FLAT && ~slope & _masks[mode])) b = ~b;
if ((tileh != SLOPE_FLAT && ~tileh & _masks[mode+4])) b = ~b;
@@ -1136,6 +1139,8 @@ static bool CheckFree2x2Area(TileIndex tile)
if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return false;
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false;
+
if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_FORCETEST, CMD_LANDSCAPE_CLEAR)))
return false;
}
@@ -1270,6 +1275,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
// make sure it's possible
if (!EnsureNoVehicle(tile)) return false;
if (IsSteepSlope(GetTileSlope(tile, NULL))) return false;
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return false;
r = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(r)) return false;
diff --git a/train_cmd.c b/train_cmd.c
index 47858434b..9b008682b 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -25,6 +25,7 @@
#include "waypoint.h"
#include "vehicle_gui.h"
#include "train.h"
+#include "bridge.h"
#include "newgrf_callbacks.h"
#include "newgrf_engine.h"
#include "newgrf_text.h"
@@ -91,10 +92,7 @@ void TrainPowerChanged(Vehicle* v)
/* Power is not added for articulated parts */
if (IsArticulatedPart(u)) continue;
- if (IsBridgeTile(u->tile) && IsBridgeMiddle(u->tile) && DiagDirToAxis(DirToDiagDir(u->direction)) == GetBridgeAxis(u->tile)) {
- if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeOnBridge(u->tile))) engine_has_power = false;
- if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeOnBridge(u->tile))) wagon_has_power = false;
- } else if (IsLevelCrossingTile(u->tile)) {
+ if (IsLevelCrossingTile(u->tile)) {
if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile))) engine_has_power = false;
if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile))) wagon_has_power = false;
} else {
@@ -1529,13 +1527,14 @@ static void ReverseTrainSwapVeh(Vehicle *v, int l, int r)
UpdateVarsAfterSwap(a);
UpdateVarsAfterSwap(b);
- VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
- VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
+ /* call the proper EnterTile function unless we are in a wormhole */
+ if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
+ if (!(b->u.rail.track & 0x40)) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
} else {
if (!(a->u.rail.track & 0x80)) a->direction = ReverseDir(a->direction);
UpdateVarsAfterSwap(a);
- VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
+ if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
}
/* Update train's power incase tiles were different rail type */
@@ -1848,8 +1847,6 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
return tfdd;
}
- if (v->u.rail.track == 0x40) tile = GetVehicleOutOfTunnelTile(v);
-
if (_patches.yapf.rail_use_yapf) {
bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
@@ -2567,9 +2564,7 @@ static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
byte new_z, old_z;
// need this hint so it returns the right z coordinate on bridges.
- _get_z_hint = v->z_pos;
new_z = GetSlopeZ(v->x_pos, v->y_pos);
- _get_z_hint = 0;
old_z = v->z_pos;
v->z_pos = new_z;
@@ -2645,13 +2640,6 @@ static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
// normal tracks, jump to owner check
break;
- case MP_TUNNELBRIDGE:
- if (IsBridge(tile) && IsBridgeMiddle(tile)) {
- // is train going over the bridge?
- if (v->z_pos > GetTileMaxZ(tile)) return true;
- }
- break;
-
case MP_STREET:
// tracks over roads, do owner check of tracks
return
@@ -2992,15 +2980,16 @@ static void TrainController(Vehicle *v)
v->direction = chosen_dir;
}
} else {
- /* in tunnel */
+ /* in tunnel on on a bridge */
GetNewVehiclePos(v, &gp);
- // Check if to exit the tunnel...
- if (!IsTunnelTile(gp.new_tile) ||
- !(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&0x4) ) {
+ SetSpeedLimitOnBridge(v);
+
+ if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 0x4)) {
v->x_pos = gp.x;
v->y_pos = gp.y;
VehiclePositionChanged(v);
+ if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
continue;
}
}
@@ -3097,7 +3086,7 @@ static void DeleteLastWagon(Vehicle *v)
* others are on it */
DisableTrainCrossing(v->tile);
- if (v->u.rail.track == 0x40) { // inside a tunnel
+ if ( (v->u.rail.track == 0x40 && v->vehstatus & VS_HIDDEN) ) { // inside a tunnel
TileIndex endtile = CheckTunnelBusy(v->tile, NULL);
if (endtile == INVALID_TILE) return; // tunnel is busy (error returned)
@@ -3128,15 +3117,16 @@ static void ChangeTrainDirRandomly(Vehicle *v)
};
do {
- //I need to buffer the train direction
- if (!(v->u.rail.track & 0x40)) {
- v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
- }
+ /* We don't need to twist around vehicles if they're not visible */
if (!(v->vehstatus & VS_HIDDEN)) {
+ v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
BeginVehicleMove(v);
UpdateTrainDeltaXY(v, v->direction);
v->cur_image = GetTrainImage(v, v->direction);
- AfterSetTrainPos(v, false);
+ /* Refrain from updating the z position of the vehicle when on
+ a bridge, because AfterSetTrainPos will put the vehicle under
+ the bridge in that case */
+ if (!(v->u.rail.track & 0x40)) AfterSetTrainPos(v, false);
}
} while ((v = v->next) != NULL);
}
@@ -3147,7 +3137,7 @@ static void HandleCrashedTrain(Vehicle *v)
uint32 r;
Vehicle *u;
- if (state == 4 && v->u.rail.track != 0x40) {
+ if (state == 4 && !(v->u.rail.track & VS_HIDDEN)) {
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
}
@@ -3234,10 +3224,15 @@ static bool TrainCheckIfLineEnds(Vehicle *v)
tile = v->tile;
- // tunnel entrance?
- if (IsTunnelTile(tile) &&
- DiagDirToDir(GetTunnelDirection(tile)) == v->direction) {
- return true;
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ DiagDirection dir;
+
+ if (IsTunnel(tile)) {
+ dir = GetTunnelDirection(tile);
+ } else {
+ dir = GetBridgeRampDirection(tile);
+ }
+ if (DiagDirToDir(dir) == v->direction) return true;
}
// depot?
diff --git a/tree_cmd.c b/tree_cmd.c
index 808243b14..018835d5b 100644
--- a/tree_cmd.c
+++ b/tree_cmd.c
@@ -2,6 +2,7 @@
#include "stdafx.h"
#include "openttd.h"
+#include "bridge_map.h"
#include "clear_map.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -68,6 +69,7 @@ static void DoPlaceMoreTrees(TileIndex tile)
if (dist <= 13 &&
IsTileType(cur_tile, MP_CLEAR) &&
+ !IsBridgeAbove(cur_tile) &&
!IsClearGround(cur_tile, CLEAR_FIELDS) &&
!IsClearGround(cur_tile, CLEAR_ROCKS)) {
PlaceTree(cur_tile, r);
@@ -92,6 +94,7 @@ void PlaceTreesRandomly(void)
uint32 r = Random();
TileIndex tile = RandomTileSeed(r);
if (IsTileType(tile, MP_CLEAR) &&
+ !IsBridgeAbove(tile) &&
!IsClearGround(tile, CLEAR_FIELDS) &&
!IsClearGround(tile, CLEAR_ROCKS)) {
PlaceTree(tile, r);
@@ -105,7 +108,9 @@ void PlaceTreesRandomly(void)
do {
uint32 r = Random();
TileIndex tile = RandomTileSeed(r);
- if (IsTileType(tile, MP_CLEAR) && GetTropicZone(tile) == TROPICZONE_RAINFOREST) {
+ if (IsTileType(tile, MP_CLEAR) &&
+ !IsBridgeAbove(tile) &&
+ GetTropicZone(tile) == TROPICZONE_RAINFOREST) {
PlaceTree(tile, r);
}
} while (--i);
@@ -175,7 +180,8 @@ int32 CmdPlantTree(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
break;
case MP_CLEAR:
- if (!IsTileOwner(tile, OWNER_NONE)) {
+ if (!IsTileOwner(tile, OWNER_NONE) ||
+ IsBridgeAbove(tile)) {
msg = STR_2804_SITE_UNSUITABLE;
continue;
}
@@ -480,7 +486,7 @@ static void TileLoop_Trees(TileIndex tile)
tile += ToTileIndexDiff(_tileloop_trees_dir[Random() & 7]);
- if (!IsTileType(tile, MP_CLEAR)) return;
+ if (!IsTileType(tile, MP_CLEAR) || IsBridgeAbove(tile)) return;
switch (GetClearGround(tile)) {
case CLEAR_GRASS:
@@ -513,6 +519,7 @@ static void TileLoop_Trees(TileIndex tile)
case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break;
default: MakeClear(tile, CLEAR_SNOW, GetTreeDensity(tile)); break;
}
+ ClearBridgeMiddle(tile);
}
break;
@@ -535,6 +542,7 @@ void OnTick_Trees(void)
if (_opt.landscape == LT_DESERT &&
(r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) &&
IsTileType(tile, MP_CLEAR) &&
+ !IsBridgeAbove(tile) &&
(ct = GetClearGround(tile), ct == CLEAR_GRASS || ct == CLEAR_ROUGH) &&
(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) {
MakeTree(tile, tree, 0, 0, ct == CLEAR_ROUGH ? TREE_GROUND_ROUGH : TREE_GROUND_GRASS, 0);
@@ -547,6 +555,7 @@ void OnTick_Trees(void)
r = Random();
tile = TILE_MASK(r);
if (IsTileType(tile, MP_CLEAR) &&
+ !IsBridgeAbove(tile) &&
(ct = GetClearGround(tile), ct == CLEAR_GRASS || ct == CLEAR_ROUGH || ct == CLEAR_SNOW) &&
(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) {
switch (ct) {
diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c
index 54355bba6..2ffb77db1 100644
--- a/tunnelbridge_cmd.c
+++ b/tunnelbridge_cmd.c
@@ -30,11 +30,6 @@
#include "table/bridge_land.h"
-extern const byte _track_sloped_sprites[14];
-extern const SpriteID _water_shore_sprites[15];
-
-extern void DrawCanalWater(TileIndex tile);
-
const Bridge orig_bridge[] = {
/*
year of availablity
@@ -197,7 +192,6 @@ int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
TileIndex tile;
TileIndexDiff delta;
uint bridge_len;
- uint odd_middle_part;
Axis direction;
uint i;
int32 cost, terraformcost, ret;
@@ -289,6 +283,26 @@ int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
cost += terraformcost;
+ {
+ TileIndex Heads[] = {tile_start, tile_end};
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (MayHaveBridgeAbove(Heads[i])) {
+ if (IsBridgeAbove(Heads[i])) {
+ TileIndex north_head = GetNorthernBridgeEnd(Heads[i]);
+ int z1, z2;
+
+ if (direction == GetBridgeAxis(Heads[i])) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
+ z1 = GetBridgeHeight(north_head, GetBridgeAxis(Heads[i]));
+ z2 = GetBridgeHeight(Heads[i], direction);
+
+ if (z1 == z2) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+ }
+ }
+ }
+ }
/* do the drill? */
if (flags & DC_EXEC) {
@@ -305,47 +319,42 @@ int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
MarkTileDirtyByTile(tile_end);
}
- // position of middle part of the odd bridge (larger than MAX(i) otherwise)
- odd_middle_part = (bridge_len % 2) ? (bridge_len / 2) : bridge_len;
-
tile = tile_start;
delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
for (i = 0; i != bridge_len; i++) {
- TransportType transport_under;
- Owner owner_under = OWNER_NONE;
- RailType rail_under = INVALID_RAILTYPE;
uint z;
tile += delta;
- if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) {
- return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
+ if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
+
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
+ /* Disallow crossing bridges for the time being */
+ return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
}
switch (GetTileType(tile)) {
case MP_WATER:
if (!EnsureNoVehicle(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY);
if (!(IsWater(tile) || IsCoast(tile))) goto not_valid_below;
- transport_under = TRANSPORT_WATER;
break;
case MP_RAILWAY:
- if (GetRailTileType(tile) != RAIL_TILE_NORMAL ||
- GetTrackBits(tile) != (direction == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X)) {
- goto not_valid_below;
- }
- transport_under = TRANSPORT_RAIL;
- owner_under = GetTileOwner(tile);
- rail_under = GetRailType(tile);
+ if (!IsPlainRailTile(tile)) goto not_valid_below;
break;
case MP_STREET:
- if (GetRoadTileType(tile) != ROAD_TILE_NORMAL ||
- GetRoadBits(tile) != (direction == AXIS_X ? ROAD_Y : ROAD_X)) {
- goto not_valid_below;
- }
- transport_under = TRANSPORT_ROAD;
- owner_under = GetTileOwner(tile);
+ if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) goto not_valid_below;
+ break;
+
+ case MP_TUNNELBRIDGE:
+ if (IsTunnel(tile)) break;
+ if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below;
+ if (GetBridgeHeight(tile_start, direction) == GetBridgeHeight(tile, DiagDirToAxis(GetBridgeRampDirection(tile)))) goto not_valid_below;
+ break;
+
+ case MP_CLEAR:
+ if (IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
break;
default:
@@ -354,50 +363,11 @@ not_valid_below:;
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return ret;
cost += ret;
- transport_under = INVALID_TRANSPORT;
break;
}
if (flags & DC_EXEC) {
- uint piece;
-
- //bridges pieces sequence (middle parts)
- // bridge len 1: 0
- // bridge len 2: 0 1
- // bridge len 3: 0 4 1
- // bridge len 4: 0 2 3 1
- // bridge len 5: 0 2 5 3 1
- // bridge len 6: 0 2 3 2 3 1
- // bridge len 7: 0 2 3 4 2 3 1
- // #0 - always as first, #1 - always as last (if len>1)
- // #2,#3 are to pair in order
- // for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
-
- if (i == 0) { // first tile
- piece = 0;
- } else if (i == bridge_len - 1) { // last tile
- piece = 1;
- } else if (i == odd_middle_part) { // we are on the middle of odd bridge: #5 on even pos, #4 on odd
- piece = 5 - (i % 2);
- } else {
- // generate #2 and #3 in turns [i%2==0], after the middle of odd bridge
- // this sequence swaps [... XOR (i>odd_middle_part)],
- // for even bridges XOR does not apply as odd_middle_part==bridge_len
- piece = 2 + ((i % 2 == 0) ^ (i > odd_middle_part));
- }
-
- if (transport == TRANSPORT_RAIL) {
- MakeRailBridgeMiddle(tile, bridge_type, piece, direction, railtype);
- } else {
- MakeRoadBridgeMiddle(tile, bridge_type, piece, direction);
- }
- switch (transport_under) {
- case TRANSPORT_RAIL: SetRailUnderBridge(tile, owner_under, rail_under); break;
- case TRANSPORT_ROAD: SetRoadUnderBridge(tile, owner_under); break;
- case TRANSPORT_WATER: SetWaterUnderBridge(tile); break;
- default: SetClearUnderBridge(tile); break;
- }
-
+ SetBridgeMiddle(tile, direction);
MarkTileDirtyByTile(tile);
}
}
@@ -582,7 +552,7 @@ static int32 DoClearTunnel(TileIndex tile, uint32 flags)
return _price.clear_tunnel * (length + 1);
}
-
+#if 0
static uint GetBridgeHeightRamp(TileIndex t)
{
/* Return the height there (the height of the NORTH CORNER)
@@ -590,6 +560,7 @@ static uint GetBridgeHeightRamp(TileIndex t)
* the z coordinate is 1 height level too low. Compensate for that */
return TilePixelHeight(t) + (GetTileSlope(t, NULL) == SLOPE_WSE ? TILE_HEIGHT : 0);
}
+#endif
static int32 DoClearBridge(TileIndex tile, uint32 flags)
@@ -597,47 +568,10 @@ static int32 DoClearBridge(TileIndex tile, uint32 flags)
DiagDirection direction;
TileIndexDiff delta;
TileIndex endtile;
- Vehicle *v;
Town *t;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
- if (IsBridgeMiddle(tile)) {
- if (IsTransportUnderBridge(tile)) {
- /* delete transport route under the bridge */
- int32 cost;
-
- // check if we own the tile below the bridge..
- if (_current_player != OWNER_WATER && (!CheckTileOwnership(tile) || !EnsureNoVehicleOnGround(tile)))
- return CMD_ERROR;
-
- if (GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
- cost = _price.remove_rail;
- } else {
- cost = _price.remove_road * 2;
- }
-
- if (flags & DC_EXEC) {
- SetClearUnderBridge(tile);
- MarkTileDirtyByTile(tile);
- }
- return cost;
- } else if (IsWaterUnderBridge(tile) && TilePixelHeight(tile) != 0) {
- /* delete canal under bridge */
-
- // check for vehicles under bridge
- if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
-
- if (flags & DC_EXEC) {
- SetClearUnderBridge(tile);
- MarkTileDirtyByTile(tile);
- }
- return _price.clear_water;
- }
-
- tile = GetSouthernBridgeEnd(tile);
- }
-
// floods, scenario editor can always destroy bridges
if (_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !CheckTileOwnership(tile)) {
if (!(_patches.extra_dynamite || _cheats.magic_bulldozer.value) || !IsTileOwner(tile, OWNER_TOWN))
@@ -651,18 +585,6 @@ static int32 DoClearBridge(TileIndex tile, uint32 flags)
direction = GetBridgeRampDirection(tile);
delta = TileOffsByDir(direction);
- /* Make sure there's no vehicle on the bridge
- Omit tile and endtile, since these are already checked, thus solving the problem
- of bridges over water, or higher bridges, where z is not increased, eg level bridge
- */
- /* Bridges on slopes might have their Z-value offset..correct this */
- v = FindVehicleBetween(
- tile + delta,
- endtile - delta,
- GetBridgeHeightRamp(tile) + TILE_HEIGHT
- );
- if (v != NULL) return_cmd_error(VehicleInTheWayErrMsg(v));
-
t = ClosestTownFromTile(tile, (uint)-1); //needed for town rating penalty
// check if you're allowed to remove the bridge owned by a town.
// removal allowal depends on difficulty settings
@@ -681,26 +603,8 @@ static int32 DoClearBridge(TileIndex tile, uint32 flags)
DoClearSquare(tile);
DoClearSquare(endtile);
for (c = tile + delta; c != endtile; c += delta) {
- if (IsTransportUnderBridge(c)) {
- if (GetTransportTypeUnderBridge(c) == TRANSPORT_RAIL) {
- MakeRailNormal(c, GetTileOwner(c), GetRailBitsUnderBridge(c), GetRailType(c));
- } else {
- uint town = IsTileOwner(c, OWNER_TOWN) ? ClosestTownFromTile(c, (uint)-1)->index : 0;
- MakeRoadNormal(c, GetTileOwner(c), GetRoadBitsUnderBridge(c), town);
- }
- MarkTileDirtyByTile(c);
- } else {
- if (IsClearUnderBridge(c)) {
- DoClearSquare(c);
- } else {
- if (GetTileSlope(c, NULL) == SLOPE_FLAT) {
- MakeWater(c);
- } else {
- MakeShore(c);
- }
- MarkTileDirtyByTile(c);
- }
- }
+ ClearBridgeMiddle(c);
+ MarkTileDirtyByTile(c);
}
UpdateSignalsOnSegment(tile, ReverseDiagDir(direction));
@@ -753,29 +657,7 @@ int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
YapfNotifyTrackLayoutChange(endtile, endtrack);
}
return (length + 1) * (_price.build_rail >> 1);
- } else if (IsBridge(tile) &&
- IsBridgeMiddle(tile) &&
- IsTransportUnderBridge(tile) &&
- GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
- // only check for train under bridge
- if (!CheckTileOwnership(tile) || !EnsureNoVehicleOnGround(tile))
- return CMD_ERROR;
-
- if (GetRailType(tile) == totype) return CMD_ERROR;
-
- if (exec) {
- TrackBits tracks;
- SetRailType(tile, totype);
- MarkTileDirtyByTile(tile);
-
- // notify YAPF about the track layout change
- for (tracks = GetRailBitsUnderBridge(tile); tracks != TRACK_BIT_NONE; tracks = KILL_FIRST_BIT(tracks))
- YapfNotifyTrackLayoutChange(tile, FIND_FIRST_BIT(tracks));
- }
- return _price.build_rail >> 1;
- } else if (IsBridge(tile) && IsBridgeRamp(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
- TileIndexDiff delta;
- int32 cost;
+ } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
uint z = TilePixelHeight(tile);
z += TILE_HEIGHT;
@@ -796,53 +678,29 @@ int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
if (GetRailType(tile) == totype) return CMD_ERROR;
if (exec) {
- Track track, endtrack;
+ TileIndexDiff delta;
+
SetRailType(tile, totype);
SetRailType(endtile, totype);
MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(endtile);
- // notify YAPF about the track layout change
- track = TrackdirToTrack(DiagdirToDiagTrackdir(GetBridgeRampDirection(tile)));
- endtrack = TrackdirToTrack(DiagdirToDiagTrackdir(GetBridgeRampDirection(endtile)));
- YapfNotifyTrackLayoutChange(tile, track);
- YapfNotifyTrackLayoutChange(endtile, endtrack);
- }
- cost = 2 * (_price.build_rail >> 1);
- delta = TileOffsByDir(GetBridgeRampDirection(tile));
- for (tile += delta; tile != endtile; tile += delta) {
- if (exec) {
- SetRailTypeOnBridge(tile, totype);
- MarkTileDirtyByTile(tile);
+ delta = TileOffsByDir(GetBridgeRampDirection(tile));
+ for (tile += delta; tile != endtile; tile += delta) {
+ MarkTileDirtyByTile(tile); // TODO encapsulate this into a function
}
- cost += _price.build_rail >> 1;
}
- return cost;
+ return (DistanceManhattan(tile, endtile) + 1) * (_price.build_rail >> 1);
} else
return CMD_ERROR;
}
-// fast routine for getting the height of a middle bridge tile. 'tile' MUST be a middle bridge tile.
-uint GetBridgeHeight(TileIndex t)
-{
- return GetBridgeHeightRamp(GetSouthernBridgeEnd(t));
-}
-
-static const byte _bridge_foundations[2][16] = {
-// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- {0,16,18,3,20,5,0,7,22,0,10,11,12,13,14},
- {0,15,17,0,19,5,6,7,21,9,10,11, 0,13,14},
-};
-
-extern const byte _road_sloped_sprites[14];
-
-static void DrawBridgePillars(PalSpriteID image, const TileInfo *ti, int x, int y, int z)
+static void DrawBridgePillars(PalSpriteID image, const TileInfo* ti, Axis axis, uint type, int x, int y, int z)
{
if (image != 0) {
- Axis axis = GetBridgeAxis(ti->tile);
- bool drawfarpillar = !HASBIT(GetBridgeFlags(GetBridgeType(ti->tile)), 0);
+ bool drawfarpillar = !HASBIT(GetBridgeFlags(type), 0);
int back_height, front_height;
int i = z;
const byte *p;
@@ -905,17 +763,11 @@ uint GetBridgeFoundation(Slope tileh, Axis axis)
* <li>Bit 2: Set if the bridge head is sloped</li>
* <li>Bit 3 and more: Railtype Specific subset</li>
* </ul>
- * For middle parts:
- * <ul><li>Bits 0-1: need to be 0</li>
- * <li>Bit 2: direction</li>
- * <li>Bit 3 and above: Railtype Specific subset</li>
- * </ul>
* Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
*/
static void DrawTile_TunnelBridge(TileInfo *ti)
{
uint32 image;
- const PalSpriteID *b;
bool ice = _m[ti->tile].m4 & 0x80;
if (IsTunnel(ti->tile)) {
@@ -932,19 +784,12 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
+ DrawBridgeMiddle(ti);
} else if (IsBridge(ti->tile)) { // XXX is this necessary?
int base_offset;
if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
- RailType rt;
-
- if (IsBridgeRamp(ti->tile)) {
- rt = GetRailType(ti->tile);
- } else {
- rt = GetRailTypeOnBridge(ti->tile);
- }
-
- base_offset = GetRailTypeInfo(rt)->bridge_offset;
+ base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
assert(base_offset != 8); /* This one is used for roads */
} else {
base_offset = 8;
@@ -953,124 +798,152 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
/* as the lower 3 bits are used for other stuff, make sure they are clear */
assert( (base_offset & 0x07) == 0x00);
- if (IsBridgeRamp(ti->tile)) {
- if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
- int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
- if (f) DrawFoundation(ti, f);
- }
+ if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
+ int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
+ if (f) DrawFoundation(ti, f);
+ }
- // HACK Wizardry to convert the bridge ramp direction into a sprite offset
- base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
+ // HACK Wizardry to convert the bridge ramp direction into a sprite offset
+ base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
- if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
+ if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
- /* Table number 6 always refers to the bridge heads for any bridge type */
- image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
+ /* Table number 6 always refers to the bridge heads for any bridge type */
+ image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
- if (!ice) {
- DrawClearLandTile(ti, 3);
- } else {
- DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
- }
+ if (!ice) {
+ DrawClearLandTile(ti, 3);
+ } else {
+ DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
+ }
- if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+ if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
- // draw ramp
- if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
- AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z);
- } else {
- // bridge middle part.
- Axis axis = GetBridgeAxis(ti->tile);
- uint z;
- int x,y;
-
- if (IsTransportUnderBridge(ti->tile)) {
- uint f = _bridge_foundations[axis][ti->tileh];
-
- if (f != 0) DrawFoundation(ti, f);
-
- if (GetTransportTypeUnderBridge(ti->tile) == TRANSPORT_RAIL) {
- const RailtypeInfo* rti = GetRailTypeInfo(GetRailType(ti->tile));
-
- if (ti->tileh == SLOPE_FLAT) {
- image = (axis == AXIS_X ? SPR_RAIL_TRACK_Y : SPR_RAIL_TRACK_X);
- } else {
- image = SPR_RAIL_TRACK_Y + _track_sloped_sprites[ti->tileh - 1];
- }
- image += rti->total_offset;
- if (ice) image += rti->snow_offset;
- } else {
- if (ti->tileh == SLOPE_FLAT) {
- image = (axis == AXIS_X ? SPR_ROAD_Y : SPR_ROAD_X);
- } else {
- image = _road_sloped_sprites[ti->tileh - 1] + 0x53F;
- }
- if (ice) image += 19;
- }
- DrawGroundSprite(image);
- } else {
- if (IsClearUnderBridge(ti->tile)) {
- image = (ice ? SPR_FLAT_SNOWY_TILE : SPR_FLAT_GRASS_TILE);
- DrawGroundSprite(image + _tileh_to_sprite[ti->tileh]);
- } else {
- if (ti->tileh == SLOPE_FLAT) {
- DrawGroundSprite(SPR_FLAT_WATER_TILE);
- if (ti->z != 0) DrawCanalWater(ti->tile);
- } else {
- DrawGroundSprite(_water_shore_sprites[ti->tileh]);
- }
- }
- }
+ // draw ramp
+ if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+ AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 16, 7, ti->z);
- if (axis != AXIS_X) base_offset += 4;
+ DrawBridgeMiddle(ti);
+ }
+}
- /* base_offset needs to be 0 due to the structure of the sprite table see table/bridge_land.h */
- assert( (base_offset & 0x03) == 0x00);
- // get bridge sprites
- b = GetBridgeSpriteTable(GetBridgeType(ti->tile), GetBridgePiece(ti->tile)) + base_offset;
- z = GetBridgeHeight(ti->tile) + 5;
+//bridges pieces sequence (middle parts)
+// bridge len 1: 0
+// bridge len 2: 0 1
+// bridge len 3: 0 4 1
+// bridge len 4: 0 2 3 1
+// bridge len 5: 0 2 5 3 1
+// bridge len 6: 0 2 3 2 3 1
+// bridge len 7: 0 2 3 4 2 3 1
+// #0 - always as first, #1 - always as last (if len>1)
+// #2,#3 are to pair in order
+// for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
+static uint CalcBridgePiece(uint north, uint south)
+{
+ if (north == 1) {
+ return 0;
+ } else if (south == 1) {
+ return 1;
+ } else if (north < south) {
+ return north & 1 ? 3 : 2;
+ } else if (north > south) {
+ return south & 1 ? 2 : 3;
+ } else {
+ return north & 1 ? 5 : 4;
+ }
+}
- // draw rail or road component
- image = b[0];
- if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
- if (axis == AXIS_X) {
- AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 11, 1, z);
- } else {
- AddSortableSpriteToDraw(image, ti->x, ti->y, 11, 16, 1, z);
- }
+void DrawBridgeMiddle(const TileInfo* ti)
+{
+ const PalSpriteID* b;
+ PalSpriteID image;
+ uint base_offset;
+ TileIndex rampnorth;
+ TileIndex rampsouth;
+ Axis axis;
+ uint piece;
+ uint type;
+ int x;
+ int y;
+ uint z;
+
+ if (!IsBridgeAbove(ti->tile)) return;
+
+ rampnorth = GetNorthernBridgeEnd(ti->tile);
+ rampsouth = GetSouthernBridgeEnd(ti->tile);
+
+ axis = GetBridgeAxis(ti->tile);
+ piece = CalcBridgePiece(
+ DistanceManhattan(ti->tile, rampnorth),
+ DistanceManhattan(ti->tile, rampsouth)
+ );
+ type = GetBridgeType(rampsouth);
- x = ti->x;
- y = ti->y;
- image = b[1];
- if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+ if (GetBridgeTransportType(rampsouth) == TRANSPORT_RAIL) {
+ base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
+ } else {
+ base_offset = 8;
+ }
- // draw roof, the component of the bridge which is logically between the vehicle and the camera
- if (axis == AXIS_X) {
- y += 12;
- if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 16, 1, 0x28, z);
- } else {
- x += 12;
- if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z);
- }
+ b = base_offset + GetBridgeSpriteTable(type, piece);
+ if (axis != AXIS_X) b += 4;
- if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC || GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+ x = ti->x;
+ y = ti->y;
+ z = GetBridgeHeight(rampsouth, axis) - 3;
- if (ti->z + 5 == z) {
- // draw poles below for small bridges
- image = b[2];
- if (image != 0) {
- if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
- DrawGroundSpriteAt(image, x, y, z);
- }
- } else if (_patches.bridge_pillars) {
- // draw pillars below for high bridges
- DrawBridgePillars(b[2], ti, x, y, z);
- }
+ image = b[0];
+ if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+ if (axis == AXIS_X) {
+ AddSortableSpriteToDraw(image, x, y, 16, 11, 1, z);
+ } else {
+ AddSortableSpriteToDraw(image, x, y, 11, 16, 1, z);
+ }
+
+ image = b[1];
+ if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+
+ // draw roof, the component of the bridge which is logically between the vehicle and the camera
+ if (axis == AXIS_X) {
+ y += 12;
+ if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 16, 1, 0x28, z);
+ } else {
+ x += 12;
+ if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z);
+ }
+
+ if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+
+ if (ti->z + 5 == z) {
+ // draw poles below for small bridges
+ image = b[2];
+ if (image != 0) {
+ if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+ DrawGroundSpriteAt(image, x, y, z);
}
+ } else if (_patches.bridge_pillars) {
+ // draw pillars below for high bridges
+ DrawBridgePillars(b[2], ti, axis, type, x, y, z);
}
}
+
+uint SetSpeedLimitOnBridge(Vehicle *v)
+{
+ uint bridge_speed;
+ if (v->vehstatus & VS_HIDDEN) return v->max_speed; /* in tunnel */
+
+ bridge_speed = _bridge[GetBridgeType(v->tile)].speed;
+
+ if (v->type == VEH_Road) bridge_speed *= 2; /* XXX give vehicles proper speeds */
+
+ if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
+ return bridge_speed;
+}
+
+
+
static uint GetSlopeZ_TunnelBridge(const TileInfo* ti)
{
TileIndex tile = ti->tile;
@@ -1085,44 +958,30 @@ static uint GetSlopeZ_TunnelBridge(const TileInfo* ti)
// In the tunnel entrance?
if (5 <= pos && pos <= 10) return z;
} else {
- if (IsBridgeRamp(tile)) {
- DiagDirection dir = GetBridgeRampDirection(tile);
- uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
-
- // On the bridge ramp?
- if (5 <= pos && pos <= 10) {
- uint delta;
-
- if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
-
- if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
- switch (dir) {
- default:
- case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
- case DIAGDIR_SE: delta = y / 2; break;
- case DIAGDIR_SW: delta = x / 2; break;
- case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
- }
- return z + 1 + delta;
- } else {
- uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
-
- if (f != 0) {
- if (f < 15) return z + TILE_HEIGHT;
- tileh = _inclined_tileh[f - 15];
- }
+ DiagDirection dir = GetBridgeRampDirection(tile);
+ uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
+
+ // On the bridge ramp?
+ if (5 <= pos && pos <= 10) {
+ uint delta;
+
+ if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
+
+ if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
+ switch (dir) {
+ default:
+ case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
+ case DIAGDIR_SE: delta = y / 2; break;
+ case DIAGDIR_SW: delta = x / 2; break;
+ case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
}
+ return z + 1 + delta;
} else {
- // HACK on the bridge?
- if (_get_z_hint >= z + TILE_HEIGHT + (tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT)) return _get_z_hint;
+ uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
- if (IsTransportUnderBridge(tile)) {
- uint f = _bridge_foundations[GetBridgeAxis(tile)][tileh];
-
- if (f != 0) {
- if (f < 15) return z + TILE_HEIGHT;
- tileh = _inclined_tileh[f - 15];
- }
+ if (f != 0) {
+ if (f < 15) return z + TILE_HEIGHT;
+ tileh = _inclined_tileh[f - 15];
}
}
}
@@ -1181,9 +1040,6 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
} else {
td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
-
- // the owner is stored at the end of the bridge
- if (IsBridgeMiddle(tile)) tile = GetSouthernBridgeEnd(tile);
}
td->owner = GetTileOwner(tile);
}
@@ -1218,10 +1074,6 @@ static void TileLoop_TunnelBridge(TileIndex tile)
}
break;
}
-
- if (IsBridge(tile) && IsBridgeMiddle(tile) && IsWaterUnderBridge(tile)) {
- TileLoop_Water(tile);
- }
}
static void ClickTile_TunnelBridge(TileIndex tile)
@@ -1232,37 +1084,13 @@ static void ClickTile_TunnelBridge(TileIndex tile)
static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode)
{
- uint32 result;
-
if (IsTunnel(tile)) {
if (GetTunnelTransportType(tile) == mode) {
return DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? 0x101 : 0x202;
}
} else if (IsBridge(tile)) { // XXX is this necessary?
- if (IsBridgeRamp(tile)) {
- if (GetBridgeTransportType(tile) != mode) return 0;
- return (DiagDirToAxis(GetBridgeRampDirection(tile)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y) * 0x101;
- } else {
- result = 0;
- if (GetBridgeTransportType(tile) == mode) {
- result = (GetBridgeAxis(tile) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y) * 0x101;
- }
- if (IsTransportUnderBridge(tile)) {
- if (GetTransportTypeUnderBridge(tile) != mode) return result;
- } else {
- if (IsClearUnderBridge(tile)) {
- return result;
- } else {
- if (mode != TRANSPORT_WATER) return result;
- }
- }
- /* If we've not returned yet, there is a compatible
- * transport or water beneath, so we can add it to
- * result */
- /* Why is this xor'd ? Can't it just be or'd? */
- result ^= (GetBridgeAxis(tile) == AXIS_X ? 0x202 : 0x101);
- }
- return result;
+ if (GetBridgeTransportType(tile) != mode) return 0;
+ return (DiagDirToAxis(GetBridgeRampDirection(tile)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y) * 0x101;
} else {
assert(0); /* This should never occur */
}
@@ -1276,16 +1104,7 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, Pl
if (new_player != OWNER_SPECTATOR) {
SetTileOwner(tile, new_player);
} else {
- if (IsBridge(tile) && IsBridgeMiddle(tile) && IsTransportUnderBridge(tile)) {
- // the stuff BELOW the middle part is owned by the deleted player.
- if (GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
- SetClearUnderBridge(tile);
- } else {
- SetTileOwner(tile, OWNER_NONE);
- }
- } else {
- DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
- }
+ DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
}
}
@@ -1305,14 +1124,15 @@ static const byte _tunnel_fractcoord_7[4] = {0x52, 0x85, 0x96, 0x49};
static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
{
+ int z = GetSlopeZ(x, y) - v->z_pos;
+
+ if (myabs(z) > 2) return 8;
+
if (IsTunnel(tile)) {
- int z = GetSlopeZ(x, y) - v->z_pos;
byte fc;
DiagDirection dir;
DiagDirection vdir;
- if (myabs(z) > 2) return 8;
-
if (v->type == VEH_Train) {
fc = (x & 0xF) + (y << 4);
@@ -1373,30 +1193,53 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y
}
}
} else if (IsBridge(tile)) { // XXX is this necessary?
+ DiagDirection dir;
+
if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
- if (IsBridgeRamp(tile) || v->z_pos > GetTileMaxZ(tile)) {
- /* modify speed of vehicle */
- uint16 spd = _bridge[GetBridgeType(tile)].speed;
- if (v->type == VEH_Road) spd *= 2;
- if (v->cur_speed > spd) v->cur_speed = spd;
+ /* modify speed of vehicle */
+ uint16 spd = _bridge[GetBridgeType(tile)].speed;
+
+ if (v->type == VEH_Road) spd *= 2;
+ if (v->cur_speed > spd) v->cur_speed = spd;
+ }
+
+ dir = GetBridgeRampDirection(tile);
+ if (DirToDiagDir(v->direction) == dir) {
+ switch (dir) {
+ default:
+ case DIAGDIR_NE: if ((x & 0xF) != 0) return 0; break;
+ case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
+ case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
+ case DIAGDIR_NW: if ((y & 0xF) != 0) return 0; break;
}
+ if (v->type == VEH_Train) {
+ v->u.rail.track = 0x40;
+ CLRBIT(v->u.rail.flags, VRF_GOINGUP);
+ CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
+ } else {
+ v->u.road.state = 0xFF;
+ }
+ return 4;
+ } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
+ v->tile = tile;
+ if (v->type == VEH_Train) {
+ if (v->u.rail.track == 0x40) {
+ v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
+ return 4;
+ }
+ } else {
+ if (v->u.road.state == 0xFF) {
+ v->u.road.state = _road_exit_tunnel_state[dir];
+ v->u.road.frame = 0;
+ return 4;
+ }
+ }
+ return 0;
}
}
return 0;
}
-TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v)
-{
- TileIndex tile;
- TileIndexDiff delta = (v->direction & 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
- byte z = v->z_pos;
-
- for (tile = v->tile;; tile += delta) {
- if (IsTunnelTile(tile) && GetTileZ(tile) == z) break;
- }
- return tile;
-}
-
const TileTypeProcs _tile_type_tunnelbridge_procs = {
DrawTile_TunnelBridge, /* draw_tile_proc */
GetSlopeZ_TunnelBridge, /* get_slope_z_proc */
diff --git a/variables.h b/variables.h
index c42f590c7..85eac88a9 100644
--- a/variables.h
+++ b/variables.h
@@ -309,7 +309,6 @@ VARDEF bool _exit_game;
VARDEF SmallFiosItem _file_to_saveload;
VARDEF byte _make_screenshot;
-VARDEF byte _get_z_hint; // used as a hint to getslopez to return the right height at a bridge.
VARDEF char *_newgrf_files[32];
diff --git a/vehicle.h b/vehicle.h
index 5d22820be..aecb3c0af 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -286,7 +286,6 @@ uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y);
StringID VehicleInTheWayErrMsg(const Vehicle* v);
Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z);
-TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v);
bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction);
void SetSignalsOnBothDir(TileIndex tile, byte track);
diff --git a/water_cmd.c b/water_cmd.c
index 086ff36f1..ff48573f3 100644
--- a/water_cmd.c
+++ b/water_cmd.c
@@ -20,7 +20,7 @@
#include "train.h"
#include "water_map.h"
-const SpriteID _water_shore_sprites[15] = {
+static const SpriteID _water_shore_sprites[] = {
0,
SPR_SHORE_TILEH_1,
SPR_SHORE_TILEH_2,
@@ -65,6 +65,8 @@ int32 CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2))
return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
+ if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return CMD_ERROR;
ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -139,6 +141,8 @@ static int32 DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 flags)
return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
}
+ if (IsBridgeAbove(tile) || IsBridgeAbove(tile - delta) || IsBridgeAbove(tile + delta)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
if (flags & DC_EXEC) {
MakeLock(tile, dir);
MarkTileDirtyByTile(tile);
@@ -227,6 +231,8 @@ int32 CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
cost = 0;
BEGIN_TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
+ int32 ret;
+
if (GetTileSlope(tile, NULL) != SLOPE_FLAT) {
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
}
@@ -234,26 +240,12 @@ int32 CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
// can't make water of water!
if (IsTileType(tile, MP_WATER)) continue;
- /* is middle piece of a bridge? */
- if (IsBridgeTile(tile) && IsBridgeMiddle(tile)) {
- if (IsTransportUnderBridge(tile)) {
- return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
- }
-
- if (IsWaterUnderBridge(tile)) return_cmd_error(STR_1007_ALREADY_BUILT);
-
- if (flags & DC_EXEC) SetWaterUnderBridge(tile);
- } else {
- /* no bridge, try to clear it. */
- int32 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-
- if (CmdFailed(ret)) return ret;
- cost += ret;
-
- if (flags & DC_EXEC) MakeWater(tile);
- }
+ ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+ if (CmdFailed(ret)) return ret;
+ cost += ret;
if (flags & DC_EXEC) {
+ MakeWater(tile);
MarkTileDirtyByTile(tile);
MarkTilesAroundDirty(tile);
}
@@ -336,17 +328,9 @@ static int32 ClearTile_Water(TileIndex tile, byte flags)
static bool IsWateredTile(TileIndex tile)
{
switch (GetTileType(tile)) {
- case MP_WATER:
- return !IsCoast(tile);
-
- case MP_STATION:
- return IsOilRig(tile) || IsDock(tile) || IsBuoy_(tile);
-
- case MP_TUNNELBRIDGE:
- return IsBridge(tile) && IsBridgeMiddle(tile) && IsWaterUnderBridge(tile);
-
- default:
- return false;
+ case MP_WATER: return !IsCoast(tile);
+ case MP_STATION: return IsOilRig(tile) || IsDock(tile) || IsBuoy_(tile);
+ default: return false;
}
}
@@ -422,11 +406,13 @@ static void DrawTile_Water(TileInfo *ti)
case WATER_CLEAR:
DrawGroundSprite(SPR_FLAT_WATER_TILE);
if (ti->z != 0) DrawCanalWater(ti->tile);
+ DrawBridgeMiddle(ti);
break;
case WATER_COAST:
assert(!IsSteepSlope(ti->tileh));
DrawGroundSprite(_water_shore_sprites[ti->tileh]);
+ DrawBridgeMiddle(ti);
break;
case WATER_LOCK: {
@@ -536,27 +522,10 @@ static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
}
break;
- case MP_TUNNELBRIDGE:
- if (IsBridge(target) && IsBridgeMiddle(target) && IsClearUnderBridge(target)) {
- SetWaterUnderBridge(target);
- MarkTileDirtyByTile(target);
- }
- break;
-
default:
break;
}
} else {
- if (IsBridgeTile(target) && IsBridgeMiddle(target)) {
- if (IsWaterUnderBridge(target) ||
- (IsTransportUnderBridge(target) && GetTransportTypeUnderBridge(target) == TRANSPORT_WATER)) { // XXX does this happen at all?
- return;
- }
- SetWaterUnderBridge(target);
- MarkTileDirtyByTile(target);
- return;
- }
-
_current_player = OWNER_WATER;
{
Vehicle *v = FindVehicleOnTileZ(target, 0);
diff --git a/waypoint.c b/waypoint.c
index 7d4efd0a1..519abedfb 100644
--- a/waypoint.c
+++ b/waypoint.c
@@ -9,6 +9,7 @@
#include "map.h"
#include "order.h"
#include "rail_map.h"
+#include "bridge_map.h"
#include "saveload.h"
#include "station.h"
#include "tile.h"
@@ -201,6 +202,8 @@ int32 CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
}
+ if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+
/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
wp = FindDeletedWaypointCloseTo(tile);
if (wp == NULL) {
diff --git a/yapf/follow_track.hpp b/yapf/follow_track.hpp
index 7a191f311..394130932 100644
--- a/yapf/follow_track.hpp
+++ b/yapf/follow_track.hpp
@@ -27,7 +27,7 @@ struct CFollowTrackT : public FollowTrack_t
m_new_tile = INVALID_TILE;
m_new_td_bits = TRACKDIR_BIT_NONE;
m_exitdir = INVALID_DIAGDIR;
- m_is_station = m_is_tunnel = false;
+ m_is_station = m_is_bridge = m_is_tunnel = false;
m_tiles_skipped = 0;
}
@@ -60,6 +60,9 @@ protected:
/** Follow the m_exitdir from m_old_tile and fill m_new_tile and m_tiles_skipped */
FORCEINLINE void FollowTileExit()
{
+ m_is_station = m_is_bridge = m_is_tunnel = false;
+ m_tiles_skipped = 0;
+
// extra handling for tunnels in our direction
if (IsTunnelTile(m_old_tile)) {
DiagDirection tunnel_enterdir = GetTunnelDirection(m_old_tile);
@@ -73,11 +76,22 @@ protected:
}
assert(ReverseDiagDir(tunnel_enterdir) == m_exitdir);
}
- // not a tunnel or station
- m_is_tunnel = false;
- m_tiles_skipped = 0;
- // normal or station tile
+ // extra handling for bridge ramp in our direction
+ if (IsBridgeTile(m_old_tile)) {
+ DiagDirection bridge_enterdir = GetBridgeRampDirection(m_old_tile);
+ if (bridge_enterdir == m_exitdir) {
+ // we are entering the bridge ramp
+ m_new_tile = GetOtherBridgeEnd(m_old_tile);
+ uint32 bridge_length = GetBridgeLength(m_old_tile, m_new_tile);
+ m_tiles_skipped = bridge_length;
+ m_is_bridge = true;
+ return;
+ }
+ assert(ReverseDiagDir(bridge_enterdir) == m_exitdir);
+ }
+
+ // normal or station tile, do one step
TileIndexDiff diff = TileOffsByDir(m_exitdir);
m_new_tile = TILE_ADD(m_old_tile, diff);
@@ -148,22 +162,7 @@ protected:
// rail transport is possible only on tiles with the same owner as vehicle
if (IsRailTT() && GetTileOwner(m_new_tile) != m_veh->owner) {
// different owner
- if (IsBridgeTile(m_new_tile)) {
- if (IsBridgeMiddle(m_new_tile)) {
- // bridge middle has no owner - tile is owned by the owner of the under-bridge track
- if (GetBridgeAxis(m_new_tile) != DiagDirToAxis(m_exitdir)) {
- // so it must be under bridge track (and wrong owner)
- return false;
- }
- // in the middle of the bridge - when we came here, it should be ok
- } else {
- // different owner, on the bridge ramp
- return false;
- }
- } else {
- // different owner, not a bridge
- return false;
- }
+ return false;
}
// rail transport is possible only on compatible rail types
@@ -224,20 +223,10 @@ public:
int max_speed = INT_MAX; // no limit
// for now we handle only on-bridge speed limit
- if (IsBridgeTile(m_old_tile) && !IsWaterTT() && IsDiagonalTrackdir(m_old_td)) {
- bool is_on_bridge = true;
- if (IsBridgeMiddle(m_old_tile)) {
- // get track axis
- Axis track_axis = DiagDirToAxis(TrackdirToExitdir(m_old_td));
- // get under-bridge axis
- Axis bridge_axis = GetBridgeAxis(m_old_tile);
- if (track_axis != bridge_axis) is_on_bridge = false;
- }
- if (is_on_bridge) {
- int spd = _bridge[GetBridgeType(m_old_tile)].speed;
- if (IsRoadTT()) spd *= 2;
- if (max_speed > spd) max_speed = spd;
- }
+ if (!IsWaterTT() && IsBridgeTile(m_old_tile)) {
+ int spd = _bridge[GetBridgeType(m_old_tile)].speed;
+ if (IsRoadTT()) spd *= 2;
+ if (max_speed > spd) max_speed = spd;
}
// if min speed was requested, return it
diff --git a/yapf/yapf.h b/yapf/yapf.h
index 4fc0b0043..f9aec4dcc 100644
--- a/yapf/yapf.h
+++ b/yapf/yapf.h
@@ -34,9 +34,9 @@ typedef struct FollowTrack_t
Trackdir m_old_td;
TileIndex m_new_tile;
TrackdirBits m_new_td_bits;
-// TrackdirBits m_red_td_bits;
DiagDirection m_exitdir;
bool m_is_tunnel;
+ bool m_is_bridge;
bool m_is_station;
int m_tiles_skipped;
} FollowTrack_t;
diff --git a/yapf/yapf_road.cpp b/yapf/yapf_road.cpp
index 3f2a9fe40..5bf679b56 100644
--- a/yapf/yapf_road.cpp
+++ b/yapf/yapf_road.cpp
@@ -423,7 +423,9 @@ uint YapfRoadVehDistanceToTile(const Vehicle* v, TileIndex tile)
Depot* YapfFindNearestRoadDepot(const Vehicle *v)
{
TileIndex tile = v->tile;
+#if 0 /* NOT NEEDED, function does/did nothing */
if (v->u.road.state == 255) tile = GetVehicleOutOfTunnelTile(v);
+#endif
Trackdir trackdir = GetVehicleTrackdir(v);
if ((GetTileTrackStatus(tile, TRANSPORT_ROAD) & TrackdirToTrackdirBits(trackdir)) == 0)
return NULL;