Merge branch 'custom_bridgeheads' into jgrpp
# Conflicts: # docs/landscape.html # src/bridge_map.h # src/pbs.cpp # src/saveload/company_sl.cpp # src/saveload/extended_ver_sl.cpp # src/settings_type.h # src/signal.cpp # src/train_cmd.cpp # src/tunnel_map.h # src/tunnelbridge_cmd.cpp # src/tunnelbridge_map.h # src/vehicle.cpp # src/viewport.cpp
This commit is contained in:
@@ -59,6 +59,7 @@ TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from
|
||||
/** Z position of the bridge sprites relative to bridge height (downwards) */
|
||||
static const int BRIDGE_Z_START = 3;
|
||||
|
||||
extern void DrawTrackBits(TileInfo *ti, TrackBits track);
|
||||
extern void DrawRoadBits(TileInfo *ti);
|
||||
extern const RoadBits _invalid_tileh_slopes_road[2][15];
|
||||
|
||||
@@ -102,6 +103,21 @@ void MarkBridgeOrTunnelDirty(TileIndex tile, const ZoomLevel mark_dirty_if_zooml
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark bridge or tunnel tiles dirty on tunnel/bridge head reservation change
|
||||
* @param tile Bridge head or tunnel entrance.
|
||||
*/
|
||||
void MarkBridgeOrTunnelDirtyOnReservationChange(TileIndex tile, const ZoomLevel mark_dirty_if_zoomlevel_is_below)
|
||||
{
|
||||
if (IsTunnelBridgeWithSignalSimulation(tile)) {
|
||||
MarkTileDirtyByTile(tile, mark_dirty_if_zoomlevel_is_below);
|
||||
} else if (IsBridge(tile)) {
|
||||
MarkBridgeDirty(tile, mark_dirty_if_zoomlevel_is_below);
|
||||
} else {
|
||||
MarkTileDirtyByTile(tile, mark_dirty_if_zoomlevel_is_below);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of signals on bridge or tunnel with signal simulation.
|
||||
* @param begin The begin of the tunnel or bridge.
|
||||
@@ -515,9 +531,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_RAIL:
|
||||
/* Add to company infrastructure count if required. */
|
||||
if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype, is_upgrade);
|
||||
MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype, is_upgrade);
|
||||
if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile_start) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile_end);
|
||||
break;
|
||||
|
||||
case TRANSPORT_ROAD: {
|
||||
@@ -982,7 +998,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
|
||||
Owner owner = GetTileOwner(tile);
|
||||
|
||||
Train *v = NULL;
|
||||
if (HasTunnelBridgeReservation(tile)) {
|
||||
if (HasTunnelReservation(tile)) {
|
||||
v = GetTrainForReservation(tile, track);
|
||||
if (v != NULL) FreeTrainTrackReservation(v);
|
||||
}
|
||||
@@ -1066,25 +1082,49 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
|
||||
ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
|
||||
}
|
||||
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
|
||||
const bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
|
||||
TrackBits tile_tracks = TRACK_BIT_NONE;
|
||||
TrackBits endtile_tracks = TRACK_BIT_NONE;
|
||||
if (rail) {
|
||||
tile_tracks = GetCustomBridgeHeadTrackBits(tile);
|
||||
endtile_tracks = GetCustomBridgeHeadTrackBits(endtile);
|
||||
cost.AddCost(RailClearCost(GetRailType(tile)) * (CountBits(tile_tracks) + CountBits(endtile_tracks) - 2));
|
||||
}
|
||||
|
||||
Money base_cost = (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) ? _price[PR_CLEAR_BRIDGE] : _price[PR_CLEAR_AQUEDUCT];
|
||||
uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
|
||||
uint middle_len = GetTunnelBridgeLength(tile, endtile);
|
||||
uint len = middle_len + 2; // Don't forget the end tiles.
|
||||
|
||||
cost.AddCost(len * base_cost);
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* read this value before actual removal of bridge */
|
||||
bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
|
||||
Owner owner = GetTileOwner(tile);
|
||||
int height = GetBridgeHeight(tile);
|
||||
Train *v = NULL;
|
||||
SmallVector<Train *, 2> vehicles_affected;
|
||||
|
||||
if (rail && HasTunnelBridgeReservation(tile)) {
|
||||
v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
|
||||
if (v != NULL) FreeTrainTrackReservation(v);
|
||||
if (rail) {
|
||||
auto find_train_reservations = [&vehicles_affected](TileIndex tile) {
|
||||
TrackBits reserved = GetBridgeReservationTrackBits(tile);
|
||||
Track track;
|
||||
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
|
||||
Train *v = GetTrainForReservation(tile, track);
|
||||
if (v != NULL) {
|
||||
FreeTrainTrackReservation(v);
|
||||
*vehicles_affected.Append() = v;
|
||||
}
|
||||
}
|
||||
};
|
||||
find_train_reservations(tile);
|
||||
find_train_reservations(endtile);
|
||||
}
|
||||
|
||||
/* Update company infrastructure counts. */
|
||||
if (rail) {
|
||||
if (Company::IsValidID(owner)) {
|
||||
Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= (middle_len * TUNNELBRIDGE_TRACKBIT_FACTOR) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(endtile);
|
||||
if (IsTunnelBridgeWithSignalSimulation(tile)) { // handle tunnel/bridge signals.
|
||||
Company::Get(GetTileOwner(tile))->infrastructure.signal -= GetTunnelBridgeSignalSimulationSignalCount(tile, endtile);
|
||||
}
|
||||
@@ -1113,18 +1153,28 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
|
||||
|
||||
if (rail) {
|
||||
/* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
|
||||
AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
|
||||
AddSideToSignalBuffer(endtile, direction, owner);
|
||||
|
||||
Track track = DiagDirToDiagTrack(direction);
|
||||
YapfNotifyTrackLayoutChange(tile, track);
|
||||
YapfNotifyTrackLayoutChange(endtile, track);
|
||||
auto notify_track_change = [owner](TileIndex tile, DiagDirection direction, TrackBits tracks) {
|
||||
auto check_dir = [&](DiagDirection d) {
|
||||
if (DiagdirReachesTracks(d) & tracks) AddSideToSignalBuffer(tile, d, owner);
|
||||
};
|
||||
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_90RIGHT));
|
||||
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_REVERSE));
|
||||
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_90LEFT));
|
||||
while (tracks != TRACK_BIT_NONE) {
|
||||
YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
|
||||
}
|
||||
};
|
||||
notify_track_change(tile, direction, tile_tracks);
|
||||
notify_track_change(endtile, ReverseDiagDir(direction), endtile_tracks);
|
||||
|
||||
if (v != NULL) TryPathReserve(v, true);
|
||||
for (uint i = 0; i < vehicles_affected.Length(); ++i) {
|
||||
TryPathReserve(vehicles_affected[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1489,7 +1539,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||
}
|
||||
|
||||
/* PBS debugging, draw reserved tracks darker */
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelReservation(ti->tile)) {
|
||||
if (rti->UsesOverlay()) {
|
||||
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
||||
DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
|
||||
@@ -1531,6 +1581,52 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||
DrawBridgeMiddle(ti);
|
||||
return;
|
||||
}
|
||||
if (transport_type == TRANSPORT_RAIL && IsRailCustomBridgeHead(ti->tile)) {
|
||||
DrawTrackBits(ti, GetCustomBridgeHeadTrackBits(ti->tile));
|
||||
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
|
||||
DrawRailCatenary(ti);
|
||||
}
|
||||
|
||||
if (IsTunnelBridgeWithSignalSimulation(ti->tile)) {
|
||||
extern void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition,
|
||||
SignalOffsets image, uint pos, SignalType type, SignalVariant variant, bool show_restricted);
|
||||
|
||||
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
|
||||
SignalVariant variant = IsTunnelBridgeSemaphore(ti->tile) ? SIG_SEMAPHORE : SIG_ELECTRIC;
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
|
||||
|
||||
Track t = FindFirstTrack(GetAcrossTunnelBridgeTrackBits(ti->tile));
|
||||
auto draw_signals = [&](uint position, SignalOffsets image, DiagDirection towards) {
|
||||
if (dir == towards) {
|
||||
/* flip signal directions */
|
||||
position ^= 1;
|
||||
image = (SignalOffsets)(image ^ 1);
|
||||
}
|
||||
if (IsTunnelBridgeSignalSimulationEntrance(ti->tile)) {
|
||||
DrawSingleSignal(ti->tile, rti, t, GetTunnelBridgeEntranceSignalState(ti->tile), image, position, SIGTYPE_NORMAL, variant, false);
|
||||
}
|
||||
if (IsTunnelBridgeSignalSimulationExit(ti->tile)) {
|
||||
SignalType type = SIGTYPE_NORMAL;
|
||||
if (IsTunnelBridgePBS(ti->tile)) {
|
||||
type = IsTunnelBridgeSignalSimulationEntrance(ti->tile) ? SIGTYPE_PBS : SIGTYPE_PBS_ONEWAY;
|
||||
}
|
||||
DrawSingleSignal(ti->tile, rti, t, GetTunnelBridgeExitSignalState(ti->tile), (SignalOffsets)(image ^ 1), position ^ 1, type, variant, false);
|
||||
}
|
||||
};
|
||||
switch (t) {
|
||||
default: NOT_REACHED();
|
||||
case TRACK_X: draw_signals( 8, SIGNAL_TO_SOUTHWEST, DIAGDIR_SW); break;
|
||||
case TRACK_Y: draw_signals(10, SIGNAL_TO_SOUTHEAST, DIAGDIR_NW); break;
|
||||
case TRACK_UPPER: draw_signals( 4, SIGNAL_TO_WEST, DIAGDIR_NW); break;
|
||||
case TRACK_LOWER: draw_signals( 6, SIGNAL_TO_WEST, DIAGDIR_SW); break;
|
||||
case TRACK_LEFT: draw_signals( 0, SIGNAL_TO_NORTH, DIAGDIR_NW); break;
|
||||
case TRACK_RIGHT: draw_signals( 2, SIGNAL_TO_NORTH, DIAGDIR_NE); break;
|
||||
}
|
||||
}
|
||||
|
||||
DrawBridgeMiddle(ti);
|
||||
return;
|
||||
}
|
||||
|
||||
const PalSpriteID *psid;
|
||||
int base_offset;
|
||||
@@ -1614,7 +1710,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||
}
|
||||
|
||||
/* PBS debugging, draw reserved tracks darker */
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && GetBridgeReservationTrackBits(ti->tile) != TRACK_BIT_NONE) {
|
||||
if (rti->UsesOverlay()) {
|
||||
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
||||
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
||||
@@ -1782,8 +1878,8 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
||||
}
|
||||
}
|
||||
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)
|
||||
&& !IsTunnelBridgeWithSignalSimulation(rampnorth)) {
|
||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES)
|
||||
&& !IsTunnelBridgeWithSignalSimulation(rampnorth) && (HasAcrossBridgeReservation(rampnorth) || HasAcrossBridgeReservation(rampsouth))) {
|
||||
if (rti->UsesOverlay()) {
|
||||
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
||||
AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
|
||||
@@ -1852,7 +1948,7 @@ static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
|
||||
/* In the tunnel entrance? */
|
||||
if (5 <= pos && pos <= 10) return z;
|
||||
} else { // IsBridge(tile)
|
||||
if (IsRoadCustomBridgeHeadTile(tile)) {
|
||||
if (IsCustomBridgeHeadTile(tile)) {
|
||||
return z + TILE_HEIGHT + (IsSteepSlope(tileh) ? TILE_HEIGHT : 0);
|
||||
}
|
||||
|
||||
@@ -1883,7 +1979,7 @@ static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
|
||||
|
||||
static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
|
||||
{
|
||||
if (IsRoadCustomBridgeHeadTile(tile)) return FOUNDATION_LEVELED;
|
||||
if (IsCustomBridgeHeadTile(tile)) return FOUNDATION_LEVELED;
|
||||
return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
|
||||
}
|
||||
|
||||
@@ -1997,15 +2093,14 @@ static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType
|
||||
|
||||
DiagDirection dir = GetTunnelBridgeDirection(tile);
|
||||
|
||||
if (side != INVALID_DIAGDIR && side == dir) return 0;
|
||||
if (mode == TRANSPORT_ROAD && IsRoadCustomBridgeHeadTile(tile)) {
|
||||
if (side != INVALID_DIAGDIR && side == dir) return 0;
|
||||
TrackBits bits = TRACK_BIT_NONE;
|
||||
if (sub_mode & ROADTYPES_TRAM) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_TRAM)];
|
||||
if (sub_mode & ROADTYPES_ROAD) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_ROAD)];
|
||||
return CombineTrackStatus(TrackBitsToTrackdirBits(bits), TRACKDIR_BIT_NONE);
|
||||
}
|
||||
if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
|
||||
return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
|
||||
return CombineTrackStatus(TrackBitsToTrackdirBits(mode == TRANSPORT_RAIL ? GetTunnelBridgeTrackBits(tile) : DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
|
||||
}
|
||||
|
||||
static void UpdateRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end, bool add) {
|
||||
@@ -2063,9 +2158,6 @@ void SubtractRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end) {
|
||||
static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
|
||||
{
|
||||
const TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
|
||||
/* Set number of pieces to zero if it's the southern tile as we
|
||||
* don't want to update the infrastructure counts twice. */
|
||||
const uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
|
||||
const TransportType tt = GetTunnelBridgeTransportType(tile);
|
||||
|
||||
if (tt == TRANSPORT_ROAD && tile < other_end) {
|
||||
@@ -2092,9 +2184,15 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner
|
||||
|
||||
Company *old = Company::Get(old_owner);
|
||||
if (tt == TRANSPORT_RAIL) {
|
||||
/* Set number of middle pieces to zero if it's the southern tile as we
|
||||
* don't want to update the infrastructure counts twice. */
|
||||
const uint num_pieces = GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile) + (tile < other_end ? GetTunnelBridgeLength(tile, other_end) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0);
|
||||
old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
|
||||
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
|
||||
} else if (tt == TRANSPORT_WATER) {
|
||||
/* Set number of pieces to zero if it's the southern tile as we
|
||||
* don't want to update the infrastructure counts twice. */
|
||||
const uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
|
||||
old->infrastructure.water -= num_pieces;
|
||||
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
|
||||
}
|
||||
@@ -2141,23 +2239,31 @@ extern const byte _tunnel_turnaround_pre_visibility_frame[DIAGDIR_END] = {31, 27
|
||||
|
||||
static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
|
||||
{
|
||||
/* Direction into the wormhole */
|
||||
const DiagDirection dir = GetTunnelBridgeDirection(tile);
|
||||
/* New position of the vehicle on the tile */
|
||||
int pos = (DiagDirToAxis(dir) == AXIS_X ? x - (TileX(tile) * TILE_SIZE) : y - (TileY(tile) * TILE_SIZE));
|
||||
/* Number of units moved by the vehicle since entering the tile */
|
||||
int frame = (dir == DIAGDIR_NE || dir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
|
||||
|
||||
if (frame > (int) TILE_SIZE || frame < 0) return VETSB_CANNOT_ENTER;
|
||||
if (frame == TILE_SIZE) {
|
||||
TileIndexDiffC offset = TileIndexDiffCByDiagDir(ReverseDiagDir(dir));
|
||||
x += offset.x;
|
||||
y += offset.y;
|
||||
}
|
||||
|
||||
int z = GetSlopePixelZ(x, y) - v->z_pos;
|
||||
|
||||
if (abs(z) > 2) return VETSB_CANNOT_ENTER;
|
||||
/* Direction into the wormhole */
|
||||
const DiagDirection dir = GetTunnelBridgeDirection(tile);
|
||||
/* Direction of the vehicle */
|
||||
const DiagDirection vdir = DirToDiagDir(v->direction);
|
||||
/* New position of the vehicle on the tile */
|
||||
byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
|
||||
/* Number of units moved by the vehicle since entering the tile */
|
||||
byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
|
||||
|
||||
if (IsTunnel(tile)) {
|
||||
/* Direction of the vehicle */
|
||||
const DiagDirection vdir = DirToDiagDir(v->direction);
|
||||
if (v->type == VEH_TRAIN) {
|
||||
Train *t = Train::From(v);
|
||||
|
||||
if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
|
||||
if (!(t->track & TRACK_BIT_WORMHOLE) && dir == vdir) {
|
||||
if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
|
||||
if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
|
||||
SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
|
||||
@@ -2173,7 +2279,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
}
|
||||
}
|
||||
|
||||
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
|
||||
if (dir == ReverseDiagDir(vdir) && frame == (int) (_tunnel_visibility_frame[dir] - 1) && z == 0) {
|
||||
/* We're at the tunnel exit ?? */
|
||||
if (t->tile != tile && GetOtherTunnelEnd(t->tile) != tile) return VETSB_CONTINUE; // In chunnel
|
||||
t->tile = tile;
|
||||
@@ -2203,7 +2309,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
}
|
||||
|
||||
/* We're at the tunnel exit ?? */
|
||||
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
|
||||
if (dir == ReverseDiagDir(vdir) && frame == (int) (_tunnel_visibility_frame[dir] - 1) && z == 0) {
|
||||
if (rv->tile != tile && GetOtherTunnelEnd(rv->tile) != tile) return VETSB_CONTINUE; // In chunnel
|
||||
rv->tile = tile;
|
||||
rv->cur_image_valid_dir = INVALID_DIR;
|
||||
@@ -2224,11 +2330,12 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
first->cur_speed = min(first->cur_speed, spd);
|
||||
}
|
||||
|
||||
if (vdir == dir) {
|
||||
/* Vehicle enters bridge at the last frame inside this tile. */
|
||||
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
|
||||
const Direction bridge_dir = DiagDirToDir(dir);
|
||||
if (v->direction == bridge_dir) {
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: {
|
||||
/* Trains enter bridge at the first frame beyond this tile. */
|
||||
if (frame != TILE_SIZE) return VETSB_CONTINUE;
|
||||
Train *t = Train::From(v);
|
||||
t->track = TRACK_BIT_WORMHOLE;
|
||||
ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
|
||||
@@ -2237,6 +2344,8 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
}
|
||||
|
||||
case VEH_ROAD: {
|
||||
/* Non-train vehicles enter bridge at the last frame inside this tile. */
|
||||
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
if (IsRoadCustomBridgeHeadTile(tile)) {
|
||||
RoadBits bits = ROAD_NONE;
|
||||
@@ -2253,29 +2362,36 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
}
|
||||
|
||||
case VEH_SHIP:
|
||||
/* Non-train vehicles enter bridge at the last frame inside this tile. */
|
||||
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
|
||||
Ship::From(v)->state = TRACK_BIT_WORMHOLE;
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
} else if (vdir == ReverseDiagDir(dir)) {
|
||||
v->tile = tile;
|
||||
} else if (v->direction == ReverseDir(bridge_dir)) {
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: {
|
||||
Train *t = Train::From(v);
|
||||
if (t->track == TRACK_BIT_WORMHOLE) {
|
||||
t->track = DiagDirToDiagTrackBits(vdir);
|
||||
if (t->track & TRACK_BIT_WORMHOLE) {
|
||||
if (IsRailCustomBridgeHeadTile(tile)) {
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
} else {
|
||||
v->tile = tile;
|
||||
t->track = DiagDirToDiagTrackBits(DirToDiagDir(v->direction));
|
||||
}
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_ROAD: {
|
||||
v->tile = tile;
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
if (rv->state == RVSB_WORMHOLE) {
|
||||
rv->cur_image_valid_dir = INVALID_DIR;
|
||||
rv->state = DiagDirToDiagTrackdir(vdir);
|
||||
rv->state = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
|
||||
rv->frame = 0;
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
}
|
||||
@@ -2283,9 +2399,10 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
}
|
||||
|
||||
case VEH_SHIP: {
|
||||
v->tile = tile;
|
||||
Ship *ship = Ship::From(v);
|
||||
if (ship->state == TRACK_BIT_WORMHOLE) {
|
||||
ship->state = DiagDirToDiagTrackBits(vdir);
|
||||
ship->state = DiagDirToDiagTrackBits(DirToDiagDir(v->direction));
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
}
|
||||
break;
|
||||
@@ -2293,6 +2410,29 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
} else if (v->type == VEH_TRAIN && IsRailCustomBridgeHeadTile(tile)) {
|
||||
DirDiff dir_diff = DirDifference(v->direction, bridge_dir);
|
||||
DirDiff reverse_dir_diff = DirDifference(v->direction, ReverseDir(bridge_dir));
|
||||
|
||||
if (dir_diff == DIRDIFF_45RIGHT || dir_diff == DIRDIFF_45LEFT) {
|
||||
if (frame != TILE_SIZE) return VETSB_CONTINUE;
|
||||
|
||||
Train *t = Train::From(v);
|
||||
TileIndex other = GetOtherTunnelBridgeEnd(tile);
|
||||
if (GetTunnelBridgeLength(tile, other) == 0 && IsRailCustomBridgeHead(other)) {
|
||||
t->track |= TRACK_BIT_WORMHOLE;
|
||||
} else {
|
||||
t->direction = bridge_dir;
|
||||
t->track = TRACK_BIT_WORMHOLE;
|
||||
}
|
||||
ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
|
||||
ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
|
||||
return VETSB_ENTERED_WORMHOLE;
|
||||
}
|
||||
if (reverse_dir_diff == DIRDIFF_45RIGHT || reverse_dir_diff == DIRDIFF_45LEFT) {
|
||||
Train *t = Train::From(v);
|
||||
if (t->track & TRACK_BIT_WORMHOLE) return VETSB_ENTERED_WORMHOLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VETSB_CONTINUE;
|
||||
@@ -2318,6 +2458,16 @@ static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flag
|
||||
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
if (IsRailCustomBridgeHeadTile(tile)) {
|
||||
extern bool IsValidFlatRailBridgeHeadTrackBits(Slope normalised_slope, DiagDirection bridge_direction, TrackBits tracks);
|
||||
|
||||
/* Steep slopes behave the same as slopes with one corner raised. */
|
||||
const Slope normalised_tileh_new = IsSteepSlope(tileh_new) ? SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh_new)) : tileh_new;
|
||||
|
||||
if (!IsValidFlatRailBridgeHeadTrackBits(normalised_tileh_new, direction, GetCustomBridgeHeadTrackBits(tile))) {
|
||||
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
|
||||
if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
|
||||
|
Reference in New Issue
Block a user