summaryrefslogtreecommitdiff
path: root/tunnelbridge_cmd.c
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 /tunnelbridge_cmd.c
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.
Diffstat (limited to 'tunnelbridge_cmd.c')
-rw-r--r--tunnelbridge_cmd.c655
1 files changed, 249 insertions, 406 deletions
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 */