src/rail_cmd.cpp
branchNewGRF_ports
changeset 6878 7d1ff2f621c7
parent 6877 889301acc299
child 10184 fcf5fb2548eb
--- a/src/rail_cmd.cpp	Sun Feb 03 20:34:26 2008 +0000
+++ b/src/rail_cmd.cpp	Mon Mar 10 15:26:39 2008 +0000
@@ -45,6 +45,7 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 #include "table/railtypes.h"
+#include "table/track_land.h"
 
 const byte _track_sloped_sprites[14] = {
 	14, 15, 22, 13,
@@ -356,9 +357,11 @@
 
 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
-			if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
+			if (IsNormalRoad(tile)) {
 				if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
 
+				if (GetDisallowedRoadDirections(tile) != DRD_NONE) return_cmd_error(STR_ERR_CROSSING_ON_ONEWAY_ROAD);
+
 				RoadTypes roadtypes = GetRoadTypes(tile);
 				RoadBits road = GetRoadBits(tile, ROADTYPE_ROAD);
 				RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
@@ -366,7 +369,7 @@
 					default: break;
 					case ROADTYPES_TRAM:
 						/* Tram crossings must always have road. */
-						SetRoadOwner(tile, ROADTYPE_ROAD, _current_player);
+						if (flags & DC_EXEC) SetRoadOwner(tile, ROADTYPE_ROAD, _current_player);
 						roadtypes |= ROADTYPES_ROAD;
 						break;
 
@@ -455,7 +458,7 @@
 			if (!IsLevelCrossing(tile) ||
 					GetCrossingRailBits(tile) != trackbit ||
 					(_current_player != OWNER_WATER && !CheckTileOwnership(tile)) ||
-					!EnsureNoVehicleOnGround(tile)) {
+					(!(flags & DC_BANKRUPT) && !EnsureNoVehicleOnGround(tile))) {
 				return CMD_ERROR;
 			}
 
@@ -910,8 +913,7 @@
 	if (tile == INVALID_TILE) return false;
 
 	/* Check for track bits on the new tile */
-	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0);
-	TrackdirBits trackdirbits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
+	TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
 
 	if (TracksOverlap(TrackdirBitsToTrackBits(trackdirbits))) return false;
 	trackdirbits &= TrackdirReachesTrackdirs(trackdir);
@@ -1312,7 +1314,7 @@
 
 				default: // MP_STATION, MP_ROAD
 					if (flags & DC_EXEC) {
-						Track track = (tt == MP_STATION) ? GetRailStationTrack(tile) : AxisToTrack(OtherAxis(GetCrossingRoadAxis(tile)));
+						Track track = ((tt == MP_STATION) ? GetRailStationTrack(tile) : GetCrossingRailTrack(tile));
 						YapfNotifyTrackLayoutChange(tile, track);
 					}
 
@@ -1398,8 +1400,6 @@
 	}
 }
 
-#include "table/track_land.h"
-
 /**
  * Get surface height in point (x,y)
  * On tiles with halftile foundations move (x,y) to a save point wrt. track
@@ -1433,27 +1433,20 @@
 		}
 	};
 
-	static const SpriteID SignalBase[2][2][4] = {
-		{    /* Signals on left side */
-			{  0x4FB, 0x1323, 0x1333, 0x1343}, /* light signals */
-			{ 0x1353, 0x1363, 0x1373, 0x1383}  /* semaphores    */
-		}, { /* Signals on right side */
-			{  0x4FB, 0x1323, 0x1333, 0x1343}, /* light signals */
-			{ 0x1446, 0x1456, 0x1466, 0x1476}  /* semaphores    */
-		/*         |       |       |       |     */
-		/*    normal,  entry,   exit,  combo     */
-		}
-	};
-
 	uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
 	uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
 
 	SpriteID sprite;
 
-	if (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC) {
-		sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition;
+	SignalType type       = GetSignalType(tile, track);
+	SignalVariant variant = GetSignalVariant(tile, track);
+
+	if (type == SIGTYPE_NORMAL && variant == SIG_ELECTRIC) {
+		/* Normal electric signals are picked from original sprites. */
+		sprite = SPR_ORIGINAL_SIGNALS_BASE + image + condition;
 	} else {
-		sprite = SPR_SIGNALS_BASE + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition;
+		/* All other signals are picked from add on sprites. */
+		sprite = SPR_SIGNALS_BASE + (type - 1) * 16 + variant * 64 + image + condition;
 	}
 
 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
@@ -1698,42 +1691,59 @@
 		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;
+			case RAIL_GROUND_ICE_DESERT:
+			case RAIL_GROUND_HALF_SNOW:  image += rti->snow_offset;  break; // higher part has snow in this case too
 			default: break;
 		}
 		DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
 	}
 }
 
+/** Enums holding the offsets from base signal sprite,
+ * according to the side it is representing.
+ * The addtion of 2 per enum is necessary in order to "jump" over the
+ * green state sprite, all signal sprites being in pair,
+ * starting with the off-red state */
+enum {
+	SIGNAL_TO_SOUTHWEST =  0,
+	SIGNAL_TO_NORTHEAST =  2,
+	SIGNAL_TO_SOUTHEAST =  4,
+	SIGNAL_TO_NORTHWEST =  6,
+	SIGNAL_TO_EAST      =  8,
+	SIGNAL_TO_WEST      = 10,
+	SIGNAL_TO_SOUTH     = 12,
+	SIGNAL_TO_NORTH     = 14,
+};
+
 static void DrawSignals(TileIndex tile, TrackBits rails)
 {
-#define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z)
+#define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y, z)
 
 	if (!(rails & TRACK_BIT_Y)) {
 		if (!(rails & TRACK_BIT_X)) {
 			if (rails & TRACK_BIT_LEFT) {
-				MAYBE_DRAW_SIGNAL(2, 0x509, 0, TRACK_LEFT);
-				MAYBE_DRAW_SIGNAL(3, 0x507, 1, TRACK_LEFT);
+				MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, TRACK_LEFT);
+				MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, TRACK_LEFT);
 			}
 			if (rails & TRACK_BIT_RIGHT) {
-				MAYBE_DRAW_SIGNAL(0, 0x509, 2, TRACK_RIGHT);
-				MAYBE_DRAW_SIGNAL(1, 0x507, 3, TRACK_RIGHT);
+				MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, TRACK_RIGHT);
+				MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, TRACK_RIGHT);
 			}
 			if (rails & TRACK_BIT_UPPER) {
-				MAYBE_DRAW_SIGNAL(3, 0x505, 4, TRACK_UPPER);
-				MAYBE_DRAW_SIGNAL(2, 0x503, 5, TRACK_UPPER);
+				MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, TRACK_UPPER);
+				MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, TRACK_UPPER);
 			}
 			if (rails & TRACK_BIT_LOWER) {
-				MAYBE_DRAW_SIGNAL(1, 0x505, 6, TRACK_LOWER);
-				MAYBE_DRAW_SIGNAL(0, 0x503, 7, TRACK_LOWER);
+				MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, TRACK_LOWER);
+				MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, TRACK_LOWER);
 			}
 		} else {
-			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8, TRACK_X);
-			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9, TRACK_X);
+			MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, TRACK_X);
+			MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, TRACK_X);
 		}
 	} else {
-		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10, TRACK_Y);
-		MAYBE_DRAW_SIGNAL(2, 0x501, 11, TRACK_Y);
+		MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, TRACK_Y);
+		MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, TRACK_Y);
 	}
 }
 
@@ -1767,7 +1777,7 @@
 
 			relocation = rti->total_offset;
 
-			image = dts->ground_sprite;
+			image = dts->ground.sprite;
 			if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
 
 			/* adjust ground tile for desert
@@ -1803,7 +1813,7 @@
 				if (dts != NULL && dts->seq != NULL) {
 					relocation = GetCustomStationRelocation(statspec, st, ti->tile);
 
-					image = dts->ground_sprite;
+					image = dts->ground.sprite;
 					if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
 						image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
 						image += rti->custom_ground_offset;
@@ -1818,7 +1828,7 @@
 				/* There is no custom layout, fall back to the default graphics */
 				dts = &_waypoint_gfx_table[GetWaypointAxis(ti->tile)];
 				relocation = 0;
-				image = dts->ground_sprite + rti->total_offset;
+				image = dts->ground.sprite + rti->total_offset;
 				if (IsSnowRailGround(ti->tile)) image += rti->snow_offset;
 			}
 		}
@@ -1828,7 +1838,7 @@
 		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
 
 		foreach_draw_tile_seq(dtss, dts->seq) {
-			SpriteID image = dtss->image;
+			SpriteID image = dtss->image.sprite;
 			SpriteID pal;
 
 			/* Unlike stations, our default waypoint has no variation for
@@ -1843,7 +1853,7 @@
 			if (!(!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
 				pal = _drawtile_track_palette;
 			} else {
-				pal = dtss->pal;
+				pal = dtss->image.pal;
 			}
 
 			if ((byte)dtss->delta_z != 0x80) {
@@ -1868,9 +1878,9 @@
 	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
 
 	DrawSprite(ground, PAL_NONE, x, y);
-	for (; dtss->image != 0; dtss++) {
+	for (; dtss->image.sprite != 0; dtss++) {
 		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
-		SpriteID image = dtss->image + offset;
+		SpriteID image = dtss->image.sprite + offset;
 
 		DrawSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y);
 	}
@@ -1879,7 +1889,7 @@
 void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype)
 {
 	const DrawTileSprites* dts = &_depot_gfx_table[dir];
-	SpriteID image = dts->ground_sprite;
+	SpriteID image = dts->ground.sprite;
 	uint32 offset = GetRailTypeInfo(railtype)->total_offset;
 
 	if (image != SPR_FLAT_GRASS_TILE) image += offset;
@@ -1891,7 +1901,7 @@
 	uint32 offset = GetRailTypeInfo(railtype)->total_offset;
 	const DrawTileSprites* dts = &_waypoint_gfx_table[AXIS_X];
 
-	DrawTileSequence(x, y, dts->ground_sprite + offset, dts->seq, 0);
+	DrawTileSequence(x, y, dts->ground.sprite + offset, dts->seq, 0);
 }
 
 static uint GetSlopeZ_Track(TileIndex tile, uint x, uint y)
@@ -1934,12 +1944,62 @@
 	}
 
 	switch (_opt.landscape) {
-		case LT_ARCTIC:
-			if (GetTileZ(tile) > GetSnowLine()) {
-				new_ground = RAIL_GROUND_ICE_DESERT;
+		case LT_ARCTIC: {
+			uint z;
+			Slope slope = GetTileSlope(tile, &z);
+			bool half = false;
+
+			/* for non-flat track, use lower part of track
+			 * in other cases, use the highest part with track */
+			if (IsPlainRailTile(tile)) {
+				TrackBits track = GetTrackBits(tile);
+				Foundation f = GetRailFoundation(slope, track);
+
+				switch (f) {
+					case FOUNDATION_NONE:
+						/* no foundation - is the track on the upper side of three corners raised tile? */
+						if (IsSlopeWithThreeCornersRaised(slope)) z += TILE_HEIGHT;
+						break;
+
+					case FOUNDATION_INCLINED_X:
+					case FOUNDATION_INCLINED_Y:
+						/* sloped track - is it on a steep slope? */
+						if (IsSteepSlope(slope)) z += TILE_HEIGHT;
+						break;
+
+					case FOUNDATION_STEEP_LOWER:
+						/* only lower part of steep slope */
+						z += TILE_HEIGHT;
+						break;
+
+					default:
+						/* if it is a steep slope, then there is a track on higher part */
+						if (IsSteepSlope(slope)) z += TILE_HEIGHT;
+						z += TILE_HEIGHT;
+						break;
+				}
+
+				half = IsInsideMM(f, FOUNDATION_STEEP_BOTH, FOUNDATION_HALFTILE_N + 1);
+			} else {
+				/* is the depot on a non-flat tile? */
+				if (slope != SLOPE_FLAT) z += TILE_HEIGHT;
+			}
+
+			/* 'z' is now the lowest part of the highest track bit -
+			 * for sloped track, it is 'z' of lower part
+			 * for two track bits, it is 'z' of higher track bit
+			 * For non-continuous foundations (and STEEP_BOTH), 'half' is set */
+			if (z > GetSnowLine()) {
+				if (half && z - GetSnowLine() == TILE_HEIGHT) {
+					/* track on non-continuous foundation, lower part is not under snow */
+					new_ground = RAIL_GROUND_HALF_SNOW;
+				} else {
+					new_ground = RAIL_GROUND_ICE_DESERT;
+				}
 				goto set_ground;
 			}
 			break;
+			}
 
 		case LT_TROPIC:
 			if (GetTropicZone(tile) == TROPICZONE_DESERT) {
@@ -2040,20 +2100,21 @@
 }
 
 
-static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint sub_mode)
+static TrackStatus GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
 {
 	if (mode != TRANSPORT_RAIL) return 0;
 
+	TrackBits trackbits = TRACK_BIT_NONE;
+	TrackdirBits red_signals = TRACKDIR_BIT_NONE;
+
 	switch (GetRailTileType(tile)) {
 		default: NOT_REACHED();
-		case RAIL_TILE_NORMAL: {
-			TrackBits rails = GetTrackBits(tile);
-			uint32 ret = rails * 0x101;
-			return (rails == TRACK_BIT_CROSS) ? ret | 0x40 : ret;
-		}
+		case RAIL_TILE_NORMAL:
+			trackbits = GetTrackBits(tile);
+			break;
 
 		case RAIL_TILE_SIGNALS: {
-			uint32 ret = GetTrackBits(tile) * 0x101;
+			trackbits = GetTrackBits(tile);
 			byte a = GetPresentSignals(tile);
 			uint b = GetSignalStates(tile);
 
@@ -2066,17 +2127,29 @@
 			if ((a & 0xC) == 0) b |= 0xC;
 			if ((a & 0x3) == 0) b |= 0x3;
 
-			if ((b & 0x8) == 0) ret |= 0x10070000;
-			if ((b & 0x4) == 0) ret |= 0x07100000;
-			if ((b & 0x2) == 0) ret |= 0x20080000;
-			if ((b & 0x1) == 0) ret |= 0x08200000;
+			if ((b & 0x8) == 0) red_signals |= (TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E);
+			if ((b & 0x4) == 0) red_signals |= (TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_UPPER_W);
+			if ((b & 0x2) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_E);
+			if ((b & 0x1) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_W);
 
-			return ret;
+			break;
 		}
 
-		case RAIL_TILE_DEPOT:    return AxisToTrackBits(DiagDirToAxis(GetRailDepotDirection(tile))) * 0x101;
-		case RAIL_TILE_WAYPOINT: return GetRailWaypointBits(tile) * 0x101;
+		case RAIL_TILE_DEPOT: {
+			DiagDirection dir = GetRailDepotDirection(tile);
+
+			if (side != INVALID_DIAGDIR && side != dir) break;
+
+			trackbits = AxisToTrackBits(DiagDirToAxis(dir));
+			break;
+		}
+
+		case RAIL_TILE_WAYPOINT:
+			trackbits = GetRailWaypointBits(tile);
+			break;
 	}
+
+	return CombineTrackStatus(TrackBitsToTrackdirBits(trackbits), red_signals);
 }
 
 static void ClickTile_Track(TileIndex tile)
@@ -2146,7 +2219,7 @@
 	if (new_player != PLAYER_SPECTATOR) {
 		SetTileOwner(tile, new_player);
 	} else {
-		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
+		DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
 	}
 }