(svn r11319) -Add: halftile- and anti-zig-zag-foundations. Patch by frosch.

This commit is contained in:
rubidium 2007-10-20 21:04:14 +00:00
parent 0c845bdd27
commit ef9e037c2a
4 changed files with 273 additions and 88 deletions

View File

@ -76,6 +76,16 @@ uint ApplyFoundationToSlope(Foundation f, Slope *s)
return TILE_HEIGHT;
}
if (f != FOUNDATION_STEEP_BOTH && IsNonContinuousFoundation(f)) {
*s = HalftileSlope(*s, GetHalftileFoundationCorner(f));
return 0;
}
if (IsSpecialRailFoundation(f)) {
*s = SlopeWithThreeCornersRaised(OppositeCorner(GetRailFoundationCorner(f)));
return 0;
}
uint dz = IsSteepSlope(*s) ? TILE_HEIGHT : 0;
Corner highest_corner = GetHighestSlopeCorner(*s);
@ -92,8 +102,8 @@ uint ApplyFoundationToSlope(Foundation f, Slope *s)
*s = SlopeWithOneCornerRaised(highest_corner);
break;
case FOUNDATION_STEEP_HIGHER:
*s = SlopeWithThreeCornersRaised(OppositeCorner(highest_corner));
case FOUNDATION_STEEP_BOTH:
*s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
break;
default: NOT_REACHED();
@ -228,6 +238,24 @@ uint GetSlopeZ(int x, int y)
return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
}
/**
* Determine the Z height of a corner relative to TileZ.
*
* @pre The slope must not be a halftile slope.
*
* @param tileh The slope.
* @param corner The corner.
* @return Z position of corner relative to TileZ.
*/
int GetSlopeZInCorner(Slope tileh, Corner corner)
{
assert(!IsHalftileSlope(tileh));
static const int _corner_slopes[4][2] = {
{ SLOPE_W, SLOPE_STEEP_W }, { SLOPE_S, SLOPE_STEEP_S }, { SLOPE_E, SLOPE_STEEP_E }, { SLOPE_N, SLOPE_STEEP_N }
};
return ((tileh & _corner_slopes[corner][0]) != 0 ? TILE_HEIGHT : 0) + (tileh == _corner_slopes[corner][1] ? TILE_HEIGHT : 0);
}
/**
* Determine the Z height of the corners of a specific tile edge
*
@ -308,6 +336,9 @@ void DrawFoundation(TileInfo *ti, Foundation f)
{
if (!IsFoundation(f)) return;
/* Two part foundations must be drawn separately */
assert(f != FOUNDATION_STEEP_BOTH);
uint sprite_block = 0;
uint z;
Slope slope = GetFoundationSlope(ti->tile, &z);
@ -324,13 +355,15 @@ void DrawFoundation(TileInfo *ti, Foundation f)
/* Use the original slope sprites if NW and NE borders should be visible */
SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * SPR_TRKFOUND_BLOCK_SIZE));
SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SPR_SLOPES_INCLINED_OFFSET + sprite_block * SPR_TRKFOUND_BLOCK_SIZE;
//SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_HALFTILE_BLOCK_SIZE;
SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_HALFTILE_BLOCK_SIZE;
if (IsSteepSlope(ti->tileh)) {
/* Lower part of foundation */
AddSortableSpriteToDraw(
leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z
);
if (!IsNonContinuousFoundation(f)) {
/* Lower part of foundation */
AddSortableSpriteToDraw(
leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z
);
}
Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
ti->z += ApplyFoundationToSlope(f, &ti->tileh);
@ -341,24 +374,42 @@ void DrawFoundation(TileInfo *ti, Foundation f)
AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y, 16, 16, 1, ti->z);
OffsetGroundSprite(31, 9);
} else if (f >= FOUNDATION_STEEP_HIGHER) {
/* three corners raised:
* Draw inclined foundations for both axes, that results in the needed image.
*/
SpriteID upper = inclined_base + highest_corner * 2;
AddSortableSpriteToDraw(upper, PAL_NONE, ti->x, ti->y, 16, 16, 1, ti->z);
AddChildSpriteScreen(upper + 1, PAL_NONE, 31, 9);
OffsetGroundSprite(31, 9);
} else {
} else if (f == FOUNDATION_STEEP_LOWER) {
/* one corner raised */
OffsetGroundSprite(31, 1);
} else {
/* halftile foundation */
int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? 8 : 0);
int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? 8 : 0);
AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z + TILE_HEIGHT);
OffsetGroundSprite(31, 9);
}
} else {
if (IsLeveledFoundation(f)) {
/* leveled foundation */
AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
OffsetGroundSprite(31, 1);
} else if (IsNonContinuousFoundation(f)) {
/* halftile foundation */
Corner halftile_corner = GetHalftileFoundationCorner(f);
int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? 8 : 0);
int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? 8 : 0);
AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z);
OffsetGroundSprite(31, 9);
} else if (IsSpecialRailFoundation(f)) {
/* anti-zig-zag foundation */
SpriteID spr;
if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
/* half of leveled foundation under track corner */
spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
} else {
/* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
}
AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
OffsetGroundSprite(31, 9);
} else {
/* inclined foundation */
byte inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);

View File

@ -26,6 +26,7 @@ bool IsValidTile(TileIndex tile);
uint GetPartialZ(int x, int y, Slope corners);
uint GetSlopeZ(int x, int y);
void GetSlopeZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2);
int GetSlopeZInCorner(Slope tileh, Corner corner);
static inline Point RemapCoords(int x, int y, int z)
{

View File

@ -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) ||
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) ||
(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);
(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;
}
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;
}
/* 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;
/* 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;
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 */

View File

@ -16,7 +16,8 @@ enum Corner {
CORNER_S = 1,
CORNER_E = 2,
CORNER_N = 3,
CORNER_END
CORNER_END,
CORNER_INVALID = 0xFF
};
/**
@ -234,8 +235,20 @@ enum Foundation {
FOUNDATION_LEVELED, ///< The tile is leveled up to a flat slope.
FOUNDATION_INCLINED_X, ///< The tile has an along X-axis inclined foundation.
FOUNDATION_INCLINED_Y, ///< The tile has an along Y-axis inclined foundation.
FOUNDATION_STEEP_LOWER, ///< The tile has a steep slope. The lowerst corner is raised by a foundation to allow building railroad on the lower halftile.
FOUNDATION_STEEP_HIGHER, ///< The tile has a steep slope. Three corners are raised by a foundation to allow building railroad on the higher halftile.
FOUNDATION_STEEP_LOWER, ///< The tile has a steep slope. The lowest corner is raised by a foundation to allow building railroad on the lower halftile.
/* Halftile foundations */
FOUNDATION_STEEP_BOTH, ///< The tile has a steep slope. The lowest corner is raised by a foundation and the upper halftile is leveled.
FOUNDATION_HALFTILE_W, ///< Level west halftile non-continuously.
FOUNDATION_HALFTILE_S, ///< Level south halftile non-continuously.
FOUNDATION_HALFTILE_E, ///< Level east halftile non-continuously.
FOUNDATION_HALFTILE_N, ///< Level north halftile non-continuously.
/* Special anti-zig-zag foundations for single horizontal/vertical track */
FOUNDATION_RAIL_W, ///< Foundation for TRACK_BIT_LEFT, but not a leveled foundation.
FOUNDATION_RAIL_S, ///< Foundation for TRACK_BIT_LOWER, but not a leveled foundation.
FOUNDATION_RAIL_E, ///< Foundation for TRACK_BIT_RIGHT, but not a leveled foundation.
FOUNDATION_RAIL_N, ///< Foundation for TRACK_BIT_UPPER, but not a leveled foundation.
FOUNDATION_INVALID = 0xFF ///< Used inside "rail_cmd.cpp" to indicate invalid slope/track combination.
};
@ -273,6 +286,54 @@ static inline bool IsInclinedFoundation(Foundation f)
return (f == FOUNDATION_INCLINED_X) || (f == FOUNDATION_INCLINED_Y);
}
/**
* Tests if a foundation is a non-continuous foundation, i.e. halftile-foundation or FOUNDATION_STEEP_BOTH.
*
* @param f The #Foundation.
* @return true iff f is a non-continuous foundation
*/
static inline bool IsNonContinuousFoundation(Foundation f)
{
return IS_INT_INSIDE(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1);
}
/**
* Returns the halftile corner of a halftile-foundation
*
* @pre f != FOUNDATION_STEEP_BOTH
*
* @param f The #Foundation.
* @return The #Corner with track.
*/
static inline Corner GetHalftileFoundationCorner(Foundation f)
{
assert(IS_INT_INSIDE(f, FOUNDATION_HALFTILE_W, FOUNDATION_HALFTILE_N + 1));
return (Corner)(f - FOUNDATION_HALFTILE_W);
}
/**
* Tests if a foundation is a special rail foundation for single horizontal/vertical track.
*
* @param f The #Foundation.
* @return true iff f is a special rail foundation for single horizontal/vertical track.
*/
static inline bool IsSpecialRailFoundation(Foundation f)
{
return IS_INT_INSIDE(f, FOUNDATION_RAIL_W, FOUNDATION_RAIL_N + 1);
}
/**
* Returns the track corner of a special rail foundation
*
* @param f The #Foundation.
* @return The #Corner with track.
*/
static inline Corner GetRailFoundationCorner(Foundation f)
{
assert(IsSpecialRailFoundation(f));
return (Corner)(f - FOUNDATION_RAIL_W);
}
/**
* Returns the foundation needed to flatten a slope.
* The returned foundation is either FOUNDATION_NONE if the tile was already flat, or FOUNDATION_LEVELED.
@ -298,4 +359,28 @@ static inline Foundation InclinedFoundation(Axis axis)
return (axis == AXIS_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y);
}
/**
* Returns the halftile foundation for single horizontal/vertical track.
*
* @param corner The #Corner with the track.
* @return The wanted #Foundation.
*/
static inline Foundation HalftileFoundation(Corner corner)
{
assert(IsValidCorner(corner));
return (Foundation)(FOUNDATION_HALFTILE_W + corner);
}
/**
* Returns the special rail foundation for single horizontal/vertical track.
*
* @param corner The #Corner with the track.
* @return The wanted #Foundation.
*/
static inline Foundation SpecialRailFoundation(Corner corner)
{
assert(IsValidCorner(corner));
return (Foundation)(FOUNDATION_RAIL_W + corner);
}
#endif /* SLOPE_H */