summaryrefslogtreecommitdiff
path: root/src/rail_cmd.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-10-20 21:04:14 +0000
committerrubidium <rubidium@openttd.org>2007-10-20 21:04:14 +0000
commitef9e037c2a8857609876fc1f7ebcd35eeaf127fa (patch)
tree00e0a4772269841d27f0e14ac11dc189c51f5042 /src/rail_cmd.cpp
parent0c845bdd277af36e385539b0ab26929274f98831 (diff)
downloadopenttd-ef9e037c2a8857609876fc1f7ebcd35eeaf127fa.tar.xz
(svn r11319) -Add: halftile- and anti-zig-zag-foundations. Patch by frosch.
Diffstat (limited to 'src/rail_cmd.cpp')
-rw-r--r--src/rail_cmd.cpp188
1 files changed, 118 insertions, 70 deletions
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 638d70c63..7c7409e5d 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -215,19 +215,35 @@ Foundation GetRailFoundation(Slope tileh, TrackBits bits)
TrackBits higher_track = CornerToTrackBits(highest_corner);
/* Only higher track? */
- if (bits == higher_track) return FOUNDATION_STEEP_HIGHER;
+ if (bits == higher_track) return HalftileFoundation(highest_corner);
/* Overlap with higher track? */
if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
/* either lower track or both higher and lower track */
- return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER);
+ return ((bits & higher_track) != 0 ? FOUNDATION_STEEP_BOTH : FOUNDATION_STEEP_LOWER);
} else {
if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
+ Corner track_corner;
switch (bits) {
+ case TRACK_BIT_LEFT: track_corner = CORNER_W; break;
+ case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
+ case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
+ case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
+
+ case TRACK_BIT_HORZ:
+ if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N);
+ if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S);
+ return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
+
+ case TRACK_BIT_VERT:
+ if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W);
+ if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E);
+ return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
+
case TRACK_BIT_X:
if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
@@ -239,6 +255,19 @@ Foundation GetRailFoundation(Slope tileh, TrackBits bits)
default:
return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
}
+ /* Single diagonal track */
+
+ /* Track must be at least valid on leveled foundation */
+ if (!valid_on_leveled) return FOUNDATION_INVALID;
+
+ /* If slope has three raised corners, build leveled foundation */
+ if (HasSlopeHighestCorner(ComplementSlope(tileh))) return FOUNDATION_LEVELED;
+
+ /* If neighboured corners of track_corner are lowered, build halftile foundation */
+ if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner);
+
+ /* else special anti-zig-zag foundation */
+ return SpecialRailFoundation(track_corner);
}
}
@@ -1422,41 +1451,64 @@ static void DrawTrackDetails(const TileInfo* ti)
static void DrawTrackBits(TileInfo* ti, TrackBits track)
{
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
+ RailGroundType rgt = GetRailGroundType(ti->tile);
+ Foundation f = GetRailFoundation(ti->tileh, track);
+ Corner halftile_corner = CORNER_INVALID;
+
+ if (IsNonContinuousFoundation(f)) {
+ /* Save halftile corner */
+ halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
+ /* Draw lower part first */
+ track &= ~CornerToTrackBits(halftile_corner);
+ f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE);
+ }
+
+ DrawFoundation(ti, f);
+ /* DrawFoundation modifies ti */
+
SpriteID image;
SpriteID pal = PAL_NONE;
bool junction = false;
/* Select the sprite to use. */
- (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
- (image++, track == TRACK_BIT_X) ||
- (image++, track == TRACK_BIT_UPPER) ||
- (image++, track == TRACK_BIT_LOWER) ||
- (image++, track == TRACK_BIT_RIGHT) ||
- (image++, track == TRACK_BIT_LEFT) ||
- (image++, track == TRACK_BIT_CROSS) ||
-
- (image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
- (image++, track == TRACK_BIT_VERT) ||
-
- (junction = true, false) ||
- (image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
- (image++, (track & TRACK_BIT_3WAY_SW) == 0) ||
- (image++, (track & TRACK_BIT_3WAY_NW) == 0) ||
- (image++, (track & TRACK_BIT_3WAY_SE) == 0) ||
- (image++, true);
-
- if (ti->tileh != SLOPE_FLAT) {
- DrawFoundation(ti, GetRailFoundation(ti->tileh, track));
-
- /* DrawFoundation() modifies it.
- * Default sloped sprites.. */
- if (ti->tileh != SLOPE_FLAT) image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
- }
+ if (track == 0) {
+ /* Clear ground (only track on halftile foundation) */
+ switch (rgt) {
+ case RAIL_GROUND_BARREN: image = SPR_FLAT_BARE_LAND; break;
+ case RAIL_GROUND_ICE_DESERT: image = SPR_FLAT_SNOWY_TILE; break;
+ default: image = SPR_FLAT_GRASS_TILE; break;
+ }
+ image += _tileh_to_sprite[ti->tileh];
+ } else {
+ if (ti->tileh != SLOPE_FLAT) {
+ /* track on non-flat ground */
+ image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
+ } else {
+ /* track on flat ground */
+ (image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
+ (image++, track == TRACK_BIT_X) ||
+ (image++, track == TRACK_BIT_UPPER) ||
+ (image++, track == TRACK_BIT_LOWER) ||
+ (image++, track == TRACK_BIT_RIGHT) ||
+ (image++, track == TRACK_BIT_LEFT) ||
+ (image++, track == TRACK_BIT_CROSS) ||
+
+ (image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
+ (image++, track == TRACK_BIT_VERT) ||
+
+ (junction = true, false) ||
+ (image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
+ (image++, (track & TRACK_BIT_3WAY_SW) == 0) ||
+ (image++, (track & TRACK_BIT_3WAY_NW) == 0) ||
+ (image++, (track & TRACK_BIT_3WAY_SE) == 0) ||
+ (image++, true);
+ }
- switch (GetRailGroundType(ti->tile)) {
- case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break;
- case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break;
- default: break;
+ switch (rgt) {
+ case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break;
+ case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break;
+ default: break;
+ }
}
DrawGroundSprite(image, pal);
@@ -1470,6 +1522,30 @@ static void DrawTrackBits(TileInfo* ti, TrackBits track)
if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
}
+
+ if (IsValidCorner(halftile_corner)) {
+ DrawFoundation(ti, HalftileFoundation(halftile_corner));
+
+ /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
+ Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
+ image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y;
+ pal = PAL_NONE;
+ switch (rgt) {
+ case RAIL_GROUND_BARREN: pal = PALETTE_TO_BARE_LAND; break;
+ case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break;
+ default: break;
+ }
+
+ static const int INF = 1000; // big number compared to tilesprite size
+ static const SubSprite _halftile_sub_sprite[4] = {
+ { -INF , -INF , 32 - 33, INF }, // CORNER_W, clip 33 pixels from right
+ { -INF , 0 + 7, INF , INF }, // CORNER_S, clip 7 pixels from top
+ { -31 + 33, -INF , INF , INF }, // CORNER_E, clip 33 pixels from left
+ { -INF , -INF , INF , 30 - 23 } // CORNER_N, clip 23 pixels from bottom
+ };
+
+ DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
+ }
}
static void DrawSignals(TileIndex tile, TrackBits rails)
@@ -2289,52 +2365,24 @@ static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new,
CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
- Slope allowed_corner;
+ Corner allowed_corner;
switch (rail_bits) {
- case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break;
- case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
- case TRACK_BIT_LEFT: allowed_corner = SLOPE_E; break;
- case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
+ case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break;
+ case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break;
+ case TRACK_BIT_LEFT: allowed_corner = CORNER_E; break;
+ case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break;
default: return autoslope_result;
}
- Slope track_corners = ComplementSlope(allowed_corner);
-
Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
- switch (f_old) {
- case FOUNDATION_NONE:
- /* Everything is valid, which only changes allowed_corner */
-
- /* Compute height of track */
- if (tileh_old == track_corners) z_old += TILE_HEIGHT;
- if (tileh_new == track_corners) {
- z_new += TILE_HEIGHT;
- } else {
- /* do not build a foundation */
- if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result;
- }
-
- /* Track height must remain unchanged */
- if (z_old != z_new) return autoslope_result;
- break;
-
- case FOUNDATION_LEVELED:
- /* Is allowed_corner covered by the foundation? */
- if ((tileh_old & allowed_corner) == 0) return autoslope_result;
-
- /* allowed_corner may only be raised -> steep slope */
- if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result;
- break;
-
- case FOUNDATION_STEEP_LOWER:
- /* Only allow to lower highest corner */
- if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result;
- break;
- case FOUNDATION_STEEP_HIGHER:
- return autoslope_result;
+ /* Do not allow terraforming if allowed_corner is part of anti-zig-zag foundations */
+ if (tileh_old != SLOPE_NS && tileh_old != SLOPE_EW && IsSpecialRailFoundation(f_old)) return autoslope_result;
- default: NOT_REACHED();
+ /* Everything is valid, which only changes allowed_corner */
+ for (Corner corner = (Corner)0; corner < CORNER_END; corner = (Corner)(corner + 1)) {
+ if (allowed_corner == corner) continue;
+ if (z_old + GetSlopeZInCorner(tileh_old, corner) != z_new + GetSlopeZInCorner(tileh_new, corner)) return autoslope_result;
}
/* Make the ground dirty */