Initial implementation of two rail types per tile
This commit is contained in:
172
src/elrail.cpp
172
src/elrail.cpp
@@ -79,46 +79,77 @@ static inline TLG GetTLG(TileIndex t)
|
||||
return (TLG)((HasBit(TileX(t), 0) << 1) + HasBit(TileY(t), 0));
|
||||
}
|
||||
|
||||
struct DualTrackBits {
|
||||
TrackBitsByte primary;
|
||||
TrackBitsByte secondary;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds which Electrified Rail Bits are present on a given tile.
|
||||
* @param t tile to check
|
||||
* @param override pointer to PCP override, can be NULL
|
||||
* @return trackbits of tile if it is electrified
|
||||
*/
|
||||
static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
|
||||
static DualTrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
|
||||
{
|
||||
DualTrackBits out;
|
||||
out.primary = TRACK_BIT_NONE;
|
||||
out.secondary = TRACK_BIT_NONE;
|
||||
switch (GetTileType(t)) {
|
||||
case MP_RAILWAY:
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
case MP_RAILWAY: {
|
||||
switch (GetRailTileType(t)) {
|
||||
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
|
||||
return GetTrackBits(t);
|
||||
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS: {
|
||||
RailType secondary = GetTileSecondaryRailTypeIfValid(t);
|
||||
TrackBits present_bits = GetTrackBits(t);
|
||||
if (secondary != INVALID_RAILTYPE) {
|
||||
if (HasRailCatenary(GetSecondaryRailType(t))) {
|
||||
out.secondary = present_bits & TRACK_BIT_RT_2;
|
||||
}
|
||||
present_bits &= TRACK_BIT_RT_1;
|
||||
}
|
||||
if (HasRailCatenary(GetRailType(t))) {
|
||||
out.primary = present_bits;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return TRACK_BIT_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
|
||||
case MP_TUNNELBRIDGE: {
|
||||
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) break;
|
||||
TrackBits primary_bits = GetPrimaryTunnelBridgeTrackBits(t);
|
||||
TrackBits secondary_bits = GetSecondaryTunnelBridgeTrackBits(t);
|
||||
if (HasRailCatenary(GetRailType(t))) {
|
||||
out.primary = primary_bits;
|
||||
}
|
||||
if (secondary_bits && HasRailCatenary(GetSecondaryRailType(t))) {
|
||||
out.secondary = secondary_bits;
|
||||
}
|
||||
if ((out.primary | out.secondary) && override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
|
||||
*override = 1 << GetTunnelBridgeDirection(t);
|
||||
}
|
||||
return GetTunnelBridgeTrackBits(t);
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_ROAD:
|
||||
if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
return GetCrossingRailBits(t);
|
||||
if (!IsLevelCrossing(t)) break;
|
||||
if (!HasRailCatenary(GetRailType(t))) break;
|
||||
out.primary = GetCrossingRailBits(t);
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
if (!HasStationRail(t)) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
return TrackToTrackBits(GetRailStationTrack(t));
|
||||
if (!HasStationRail(t)) break;
|
||||
if (!HasRailCatenary(GetRailType(t))) break;
|
||||
out.primary = TrackToTrackBits(GetRailStationTrack(t));
|
||||
break;
|
||||
|
||||
default:
|
||||
return TRACK_BIT_NONE;
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +166,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
|
||||
* as needing no catenary. We make an exception for blocked station tiles with a matching
|
||||
* axis that still display wires to preserve visual continuity. */
|
||||
TileIndex next_tile = TileAddByDiagDir(t, d);
|
||||
RailType rt = GetTileRailType(next_tile);
|
||||
RailType rt = GetTileRailTypeByEntryDir(next_tile, d);
|
||||
if (rt == INVALID_RAILTYPE || !HasRailCatenary(rt) ||
|
||||
((TrackStatusToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE &&
|
||||
(!HasStationTileRail(next_tile) || GetRailStationAxis(next_tile) != DiagDirToAxis(d) || !CanStationTileHaveWires(next_tile)))) {
|
||||
@@ -173,9 +204,9 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
|
||||
/**
|
||||
* Get the base wire sprite to use.
|
||||
*/
|
||||
static inline SpriteID GetWireBase(TileIndex tile, TileContext context = TCX_NORMAL)
|
||||
static inline SpriteID GetWireBase(TileIndex tile, RailType rt, TileContext context = TCX_NORMAL)
|
||||
{
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||
SpriteID wires = GetCustomRailSprite(rti, tile, RTSG_WIRES, context);
|
||||
return wires == 0 ? SPR_WIRE_BASE : wires;
|
||||
}
|
||||
@@ -183,9 +214,9 @@ static inline SpriteID GetWireBase(TileIndex tile, TileContext context = TCX_NOR
|
||||
/**
|
||||
* Get the base pylon sprite to use.
|
||||
*/
|
||||
static inline SpriteID GetPylonBase(TileIndex tile, TileContext context = TCX_NORMAL)
|
||||
static inline SpriteID GetPylonBase(TileIndex tile, RailType rt, TileContext context = TCX_NORMAL)
|
||||
{
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||
SpriteID pylons = GetCustomRailSprite(rti, tile, RTSG_PYLONS, context);
|
||||
return pylons == 0 ? SPR_PYLON_BASE : pylons;
|
||||
}
|
||||
@@ -256,7 +287,7 @@ void DrawRailCatenaryOnTunnel(const TileInfo *ti)
|
||||
|
||||
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
|
||||
|
||||
SpriteID wire_base = GetWireBase(ti->tile);
|
||||
SpriteID wire_base = GetWireBase(ti->tile, GetRailType(ti->tile));
|
||||
|
||||
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Tunnel[dir];
|
||||
const int *BB_data = _tunnel_wire_BB[dir];
|
||||
@@ -304,15 +335,52 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
* 2) on the "far" end of a bridge head (the one that connects to bridge middle),
|
||||
* because that one is drawn on the bridge. Exception is for length 0 bridges
|
||||
* which have no middle tiles */
|
||||
trackconfig[TS_HOME] = GetRailTrackBitsUniversal(ti->tile, &OverridePCP);
|
||||
DualTrackBits home_track_config = GetRailTrackBitsUniversal(ti->tile, &OverridePCP);
|
||||
trackconfig[TS_HOME] = home_track_config.primary | home_track_config.secondary;
|
||||
wireconfig[TS_HOME] = MaskWireBits(ti->tile, trackconfig[TS_HOME]);
|
||||
/* If a track bit is present that is not in the main direction, the track is level */
|
||||
isflat[TS_HOME] = ((trackconfig[TS_HOME] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
|
||||
|
||||
AdjustTileh(ti->tile, &tileh[TS_HOME]);
|
||||
|
||||
SpriteID pylon_normal = GetPylonBase(ti->tile);
|
||||
SpriteID pylon_halftile = (halftile_corner != CORNER_INVALID) ? GetPylonBase(ti->tile, TCX_UPPER_HALFTILE) : pylon_normal;
|
||||
SpriteID pylon_normal = 0;
|
||||
SpriteID pylon_halftile = 0;
|
||||
SpriteID pylon_normal_secondary = 0;
|
||||
SpriteID pylon_halftile_secondary = 0;
|
||||
|
||||
auto get_pylon_sprite = [&](DiagDirection edge, bool halftile) -> SpriteID {
|
||||
static const uint edge_tracks[] = {
|
||||
TRACK_BIT_UPPER | TRACK_BIT_RIGHT, // DIAGDIR_NE
|
||||
TRACK_BIT_LOWER | TRACK_BIT_RIGHT, // DIAGDIR_SE
|
||||
TRACK_BIT_LOWER | TRACK_BIT_LEFT, // DIAGDIR_SW
|
||||
TRACK_BIT_UPPER | TRACK_BIT_LEFT, // DIAGDIR_NW
|
||||
};
|
||||
if (home_track_config.secondary && (home_track_config.secondary & edge_tracks[edge])) {
|
||||
if (pylon_normal_secondary == 0) {
|
||||
pylon_normal_secondary = GetPylonBase(ti->tile, GetSecondaryRailType(ti->tile));
|
||||
}
|
||||
if (halftile) {
|
||||
if (pylon_halftile_secondary == 0) {
|
||||
pylon_halftile_secondary = (halftile_corner != CORNER_INVALID) ? GetPylonBase(ti->tile, GetSecondaryRailType(ti->tile), TCX_UPPER_HALFTILE) : pylon_normal_secondary;
|
||||
}
|
||||
return pylon_halftile_secondary;
|
||||
} else {
|
||||
return pylon_normal_secondary;
|
||||
}
|
||||
} else {
|
||||
if (pylon_normal == 0) {
|
||||
pylon_normal = GetPylonBase(ti->tile, GetRailType(ti->tile));
|
||||
}
|
||||
if (halftile) {
|
||||
if (pylon_halftile == 0) {
|
||||
pylon_halftile = (halftile_corner != CORNER_INVALID) ? GetPylonBase(ti->tile, GetRailType(ti->tile), TCX_UPPER_HALFTILE) : pylon_normal;
|
||||
}
|
||||
return pylon_halftile;
|
||||
} else {
|
||||
return pylon_normal;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
|
||||
static const uint edge_corners[] = {
|
||||
@@ -321,14 +389,15 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
1 << CORNER_S | 1 << CORNER_W, // DIAGDIR_SW
|
||||
1 << CORNER_N | 1 << CORNER_W, // DIAGDIR_NW
|
||||
};
|
||||
SpriteID pylon_base = (halftile_corner != CORNER_INVALID && HasBit(edge_corners[i], halftile_corner)) ? pylon_halftile : pylon_normal;
|
||||
SpriteID pylon_base = get_pylon_sprite(i, halftile_corner != CORNER_INVALID && HasBit(edge_corners[i], halftile_corner));
|
||||
TileIndex neighbour = ti->tile + TileOffsByDiagDir(i);
|
||||
int elevation = GetPCPElevation(ti->tile, i);
|
||||
|
||||
/* Here's one of the main headaches. GetTileSlope does not correct for possibly
|
||||
* existing foundataions, so we do have to do that manually later on.*/
|
||||
tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour);
|
||||
trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
|
||||
DualTrackBits neighbour_track_config = GetRailTrackBitsUniversal(neighbour, NULL);
|
||||
trackconfig[TS_NEIGHBOUR] = neighbour_track_config.primary | neighbour_track_config.secondary;
|
||||
wireconfig[TS_NEIGHBOUR] = MaskWireBits(neighbour, trackconfig[TS_NEIGHBOUR]);
|
||||
if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wireconfig[TS_NEIGHBOUR] = trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
|
||||
|
||||
@@ -382,7 +451,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
if (IsTileType(neighbour, MP_STATION) || IsTileType(neighbour, MP_ROAD)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
|
||||
|
||||
/* Read the foundations if they are present, and adjust the tileh */
|
||||
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
|
||||
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasRailCatenary(GetTileRailTypeByEntryDir(neighbour, i))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
|
||||
if (IsBridgeTile(neighbour)) {
|
||||
foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
|
||||
}
|
||||
@@ -458,8 +527,6 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
/* Don't draw a wire if the station tile does not want any */
|
||||
if (IsRailStationTile(ti->tile) && !CanStationTileHaveWires(ti->tile)) return;
|
||||
|
||||
SpriteID wire_normal = GetWireBase(ti->tile);
|
||||
SpriteID wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, TCX_UPPER_HALFTILE) : wire_normal;
|
||||
Track halftile_track;
|
||||
switch (halftile_corner) {
|
||||
case CORNER_W: halftile_track = TRACK_LEFT; break;
|
||||
@@ -469,10 +536,43 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
default: halftile_track = INVALID_TRACK; break;
|
||||
}
|
||||
|
||||
SpriteID wire_normal = 0;
|
||||
SpriteID wire_halftile = 0;
|
||||
SpriteID wire_normal_secondary = 0;
|
||||
SpriteID wire_halftile_secondary = 0;
|
||||
|
||||
auto get_wire_sprite = [&](Track track, bool halftile) -> SpriteID {
|
||||
if (home_track_config.secondary && HasTrack(home_track_config.secondary, track)) {
|
||||
if (wire_normal_secondary == 0) {
|
||||
wire_normal_secondary = GetWireBase(ti->tile, GetSecondaryRailType(ti->tile));
|
||||
}
|
||||
if (halftile) {
|
||||
if (wire_halftile_secondary == 0) {
|
||||
wire_halftile_secondary = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, GetSecondaryRailType(ti->tile), TCX_UPPER_HALFTILE) : wire_normal_secondary;
|
||||
}
|
||||
return wire_halftile_secondary;
|
||||
} else {
|
||||
return wire_normal_secondary;
|
||||
}
|
||||
} else {
|
||||
if (wire_normal == 0) {
|
||||
wire_normal = GetWireBase(ti->tile, GetRailType(ti->tile));
|
||||
}
|
||||
if (halftile) {
|
||||
if (wire_halftile == 0) {
|
||||
wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, GetRailType(ti->tile), TCX_UPPER_HALFTILE) : wire_normal;
|
||||
}
|
||||
return wire_halftile;
|
||||
} else {
|
||||
return wire_normal;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Drawing of pylons is finished, now draw the wires */
|
||||
Track t;
|
||||
FOR_EACH_SET_TRACK(t, wireconfig[TS_HOME]) {
|
||||
SpriteID wire_base = (t == halftile_track) ? wire_halftile : wire_normal;
|
||||
SpriteID wire_base = get_wire_sprite(t, (t == halftile_track));
|
||||
byte PCPconfig = HasBit(PCPstatus, PCPpositions[t][0]) +
|
||||
(HasBit(PCPstatus, PCPpositions[t][1]) << 1);
|
||||
|
||||
@@ -527,14 +627,14 @@ void DrawRailCatenaryOnBridge(const TileInfo *ti)
|
||||
|
||||
height = GetBridgePixelHeight(end);
|
||||
|
||||
SpriteID wire_base = GetWireBase(end, TCX_ON_BRIDGE);
|
||||
SpriteID wire_base = GetWireBase(end, GetRailType(end), TCX_ON_BRIDGE);
|
||||
|
||||
AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
||||
sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
|
||||
IsTransparencySet(TO_CATENARY)
|
||||
);
|
||||
|
||||
SpriteID pylon_base = GetPylonBase(end, TCX_ON_BRIDGE);
|
||||
SpriteID pylon_base = GetPylonBase(end, GetRailType(end), TCX_ON_BRIDGE);
|
||||
|
||||
/* Finished with wires, draw pylons
|
||||
* every other tile needs a pylon on the northern end */
|
||||
@@ -570,7 +670,7 @@ void DrawRailCatenary(const TileInfo *ti)
|
||||
if (IsRailDepot(ti->tile)) {
|
||||
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
|
||||
|
||||
SpriteID wire_base = GetWireBase(ti->tile);
|
||||
SpriteID wire_base = GetWireBase(ti->tile, GetRailType(ti->tile));
|
||||
|
||||
/* This wire is not visible with the default depot sprites */
|
||||
AddSortableSpriteToDraw(
|
||||
|
Reference in New Issue
Block a user