src/rail_cmd.cpp
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9718 f82a4facea8b
child 9723 eee46cb39750
equal deleted inserted replaced
9721:9a27928bcd5e 9722:ebf0ece7d8f6
    38 #include "newgrf_callbacks.h"
    38 #include "newgrf_callbacks.h"
    39 #include "newgrf_station.h"
    39 #include "newgrf_station.h"
    40 #include "train.h"
    40 #include "train.h"
    41 #include "misc/autoptr.hpp"
    41 #include "misc/autoptr.hpp"
    42 #include "autoslope.h"
    42 #include "autoslope.h"
       
    43 #include "transparency.h"
    43 
    44 
    44 const byte _track_sloped_sprites[14] = {
    45 const byte _track_sloped_sprites[14] = {
    45 	14, 15, 22, 13,
    46 	14, 15, 22, 13,
    46 	 0, 21, 17, 12,
    47 	 0, 21, 17, 12,
    47 	23,  0, 18, 20,
    48 	23,  0, 18, 20,
   213 		/* Get higher track */
   214 		/* Get higher track */
   214 		Corner highest_corner = GetHighestSlopeCorner(tileh);
   215 		Corner highest_corner = GetHighestSlopeCorner(tileh);
   215 		TrackBits higher_track = CornerToTrackBits(highest_corner);
   216 		TrackBits higher_track = CornerToTrackBits(highest_corner);
   216 
   217 
   217 		/* Only higher track? */
   218 		/* Only higher track? */
   218 		if (bits == higher_track) return FOUNDATION_STEEP_HIGHER;
   219 		if (bits == higher_track) return HalftileFoundation(highest_corner);
   219 
   220 
   220 		/* Overlap with higher track? */
   221 		/* Overlap with higher track? */
   221 		if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
   222 		if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
   222 
   223 
   223 		/* either lower track or both higher and lower track */
   224 		/* either lower track or both higher and lower track */
   224 		return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER);
   225 		return ((bits & higher_track) != 0 ? FOUNDATION_STEEP_BOTH : FOUNDATION_STEEP_LOWER);
   225 	} else {
   226 	} else {
   226 		if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
   227 		if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
   227 
   228 
   228 		bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
   229 		bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
   229 
   230 
       
   231 		Corner track_corner;
   230 		switch (bits) {
   232 		switch (bits) {
       
   233 			case TRACK_BIT_LEFT:  track_corner = CORNER_W; break;
       
   234 			case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
       
   235 			case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
       
   236 			case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
       
   237 
       
   238 			case TRACK_BIT_HORZ:
       
   239 				if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N);
       
   240 				if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S);
       
   241 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
       
   242 
       
   243 			case TRACK_BIT_VERT:
       
   244 				if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W);
       
   245 				if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E);
       
   246 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
       
   247 
   231 			case TRACK_BIT_X:
   248 			case TRACK_BIT_X:
   232 				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
   249 				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
   233 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   250 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   234 
   251 
   235 			case TRACK_BIT_Y:
   252 			case TRACK_BIT_Y:
   237 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   254 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   238 
   255 
   239 			default:
   256 			default:
   240 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   257 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   241 		}
   258 		}
       
   259 		/* Single diagonal track */
       
   260 
       
   261 		/* Track must be at least valid on leveled foundation */
       
   262 		if (!valid_on_leveled) return FOUNDATION_INVALID;
       
   263 
       
   264 		/* If slope has three raised corners, build leveled foundation */
       
   265 		if (HasSlopeHighestCorner(ComplementSlope(tileh))) return FOUNDATION_LEVELED;
       
   266 
       
   267 		/* If neighboured corners of track_corner are lowered, build halftile foundation */
       
   268 		if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner);
       
   269 
       
   270 		/* else special anti-zig-zag foundation */
       
   271 		return SpecialRailFoundation(track_corner);
   242 	}
   272 	}
   243 }
   273 }
   244 
   274 
   245 
   275 
   246 /**
   276 /**
   253  * @return Error message or cost for foundation building.
   283  * @return Error message or cost for foundation building.
   254  */
   284  */
   255 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
   285 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
   256 {
   286 {
   257 	/* don't allow building on the lower side of a coast */
   287 	/* don't allow building on the lower side of a coast */
   258 	if (IsTileType(tile, MP_WATER)) {
   288 	if (IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_RAILWAY) && (GetRailGroundType(tile) == RAIL_GROUND_WATER))) {
   259 		if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   289 		if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   260 	}
   290 	}
   261 
   291 
   262 	Foundation f_new = GetRailFoundation(tileh, rail_bits | existing);
   292 	Foundation f_new = GetRailFoundation(tileh, rail_bits | existing);
   263 
   293 
   265 	if ((f_new == FOUNDATION_INVALID) ||
   295 	if ((f_new == FOUNDATION_INVALID) ||
   266 	    ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes))
   296 	    ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes))
   267 	   ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   297 	   ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   268 
   298 
   269 	Foundation f_old = GetRailFoundation(tileh, existing);
   299 	Foundation f_old = GetRailFoundation(tileh, existing);
   270 	return CommandCost(f_new != f_old ? _price.terraform : 0);
   300 	return CommandCost(f_new != f_old ? _price.terraform : (Money)0);
   271 }
   301 }
   272 
   302 
   273 /* Validate functions for rail building */
   303 /* Validate functions for rail building */
   274 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);}
   304 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);}
   275 
   305 
   328 			break;
   358 			break;
   329 
   359 
   330 		case MP_ROAD:
   360 		case MP_ROAD:
   331 #define M(x) (1 << (x))
   361 #define M(x) (1 << (x))
   332 			/* Level crossings may only be built on these slopes */
   362 			/* Level crossings may only be built on these slopes */
   333 			if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
   363 			if (!HasBit(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
   334 				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   364 				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   335 			}
   365 			}
   336 #undef M
   366 #undef M
   337 
   367 
   338 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   368 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   374 				return_cmd_error(STR_1007_ALREADY_BUILT);
   404 				return_cmd_error(STR_1007_ALREADY_BUILT);
   375 			}
   405 			}
   376 			/* FALLTHROUGH */
   406 			/* FALLTHROUGH */
   377 
   407 
   378 		default:
   408 		default:
       
   409 			bool water_ground = IsTileType(tile, MP_WATER) && !IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh);
       
   410 
   379 			ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
   411 			ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
   380 			if (CmdFailed(ret)) return ret;
   412 			if (CmdFailed(ret)) return ret;
   381 			cost.AddCost(ret);
   413 			cost.AddCost(ret);
   382 
   414 
   383 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   415 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   384 			if (CmdFailed(ret)) return ret;
   416 			if (CmdFailed(ret)) return ret;
   385 			cost.AddCost(ret);
   417 			cost.AddCost(ret);
   386 
   418 
   387 			if (flags & DC_EXEC) MakeRailNormal(tile, _current_player, trackbit, railtype);
   419 			if (water_ground) {
       
   420 				cost.AddCost(-_price.clear_water);
       
   421 				cost.AddCost(_price.purchase_land);
       
   422 			}
       
   423 
       
   424 			if (flags & DC_EXEC) {
       
   425 				MakeRailNormal(tile, _current_player, trackbit, railtype);
       
   426 				if (water_ground) SetRailGroundType(tile, RAIL_GROUND_WATER);
       
   427 			}
   388 			break;
   428 			break;
   389 	}
   429 	}
   390 
   430 
   391 	if (flags & DC_EXEC) {
   431 	if (flags & DC_EXEC) {
   392 		MarkTileDirtyByTile(tile);
   432 		MarkTileDirtyByTile(tile);
   448 				cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS));
   488 				cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS));
   449 
   489 
   450 			if (flags & DC_EXEC) {
   490 			if (flags & DC_EXEC) {
   451 				present ^= trackbit;
   491 				present ^= trackbit;
   452 				if (present == 0) {
   492 				if (present == 0) {
   453 					DoClearSquare(tile);
   493 					if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
       
   494 						MakeShore(tile);
       
   495 					} else {
       
   496 						DoClearSquare(tile);
       
   497 					}
   454 				} else {
   498 				} else {
   455 					SetTrackBits(tile, present);
   499 					SetTrackBits(tile, present);
   456 				}
   500 				}
   457 			}
   501 			}
   458 			break;
   502 			break;
   480 
   524 
   481 	return cost;
   525 	return cost;
   482 }
   526 }
   483 
   527 
   484 
   528 
       
   529 /**
       
   530  * Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore.
       
   531  * The function floods the lower halftile, if the tile has a halftile foundation.
       
   532  *
       
   533  * @param t The tile to flood.
       
   534  */
       
   535 void FloodHalftile(TileIndex t)
       
   536 {
       
   537 	if (GetRailGroundType(t) == RAIL_GROUND_WATER) return;
       
   538 
       
   539 	Slope tileh = GetTileSlope(t, NULL);
       
   540 	TrackBits rail_bits = GetTrackBits(t);
       
   541 
       
   542 	if (!IsSteepSlope(tileh) && HasSlopeHighestCorner(tileh)) {
       
   543 		TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh)));
       
   544 
       
   545 		TrackBits to_remove = lower_track & rail_bits;
       
   546 		if (to_remove != 0) {
       
   547 			_current_player = OWNER_WATER;
       
   548 			if (CmdFailed(DoCommand(t, 0, FIND_FIRST_BIT(to_remove), DC_EXEC, CMD_REMOVE_SINGLE_RAIL))) return; // not yet floodable
       
   549 			rail_bits = rail_bits & ~to_remove;
       
   550 			if (rail_bits == 0) {
       
   551 				MakeShore(t);
       
   552 				MarkTileDirtyByTile(t);
       
   553 				return;
       
   554 			}
       
   555 		}
       
   556 
       
   557 		if (IsNonContinuousFoundation(GetRailFoundation(tileh, rail_bits))) {
       
   558 			SetRailGroundType(t, RAIL_GROUND_WATER);
       
   559 			MarkTileDirtyByTile(t);
       
   560 		}
       
   561 	}
       
   562 }
       
   563 
   485 static const TileIndexDiffC _trackdelta[] = {
   564 static const TileIndexDiffC _trackdelta[] = {
   486 	{ -1,  0 }, {  0,  1 }, { -1,  0 }, {  0,  1 }, {  1,  0 }, {  0,  1 },
   565 	{ -1,  0 }, {  0,  1 }, { -1,  0 }, {  0,  1 }, {  1,  0 }, {  0,  1 },
   487 	{  0,  0 },
   566 	{  0,  0 },
   488 	{  0,  0 },
   567 	{  0,  0 },
   489 	{  1,  0 }, {  0, -1 }, {  0, -1 }, {  1,  0 }, {  0, -1 }, { -1,  0 },
   568 	{  1,  0 }, {  0, -1 }, {  0, -1 }, {  1,  0 }, {  0, -1 }, { -1,  0 },
   520 		(trdx <= 0 && dx > 0) ||
   599 		(trdx <= 0 && dx > 0) ||
   521 		(trdx >= 0 && dx < 0) ||
   600 		(trdx >= 0 && dx < 0) ||
   522 		(trdy <= 0 && dy > 0) ||
   601 		(trdy <= 0 && dy > 0) ||
   523 		(trdy >= 0 && dy < 0)
   602 		(trdy >= 0 && dy < 0)
   524 	) {
   603 	) {
   525 		if (!HASBIT(*trackdir, 3)) { // first direction is invalid, try the other
   604 		if (!HasBit(*trackdir, 3)) { // first direction is invalid, try the other
   526 			SetBitT(*trackdir, 3); // reverse the direction
   605 			SetBit(*trackdir, 3); // reverse the direction
   527 			trdx = -trdx;
   606 			trdx = -trdx;
   528 			trdy = -trdy;
   607 			trdy = -trdy;
   529 		} else { // other direction is invalid too, invalid drag
   608 		} else { // other direction is invalid too, invalid drag
   530 			return CMD_ERROR;
   609 			return CMD_ERROR;
   531 		}
   610 		}
   555 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   634 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   556 {
   635 {
   557 	CommandCost ret, total_cost;
   636 	CommandCost ret, total_cost;
   558 	Track track = (Track)GB(p2, 4, 3);
   637 	Track track = (Track)GB(p2, 4, 3);
   559 	Trackdir trackdir;
   638 	Trackdir trackdir;
   560 	byte mode = HASBIT(p2, 7);
   639 	byte mode = HasBit(p2, 7);
   561 	RailType railtype = (RailType)GB(p2, 0, 4);
   640 	RailType railtype = (RailType)GB(p2, 0, 4);
   562 	TileIndex end_tile;
   641 	TileIndex end_tile;
   563 
   642 
   564 	if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
   643 	if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
   565 	if (p1 >= MapSize()) return CMD_ERROR;
   644 	if (p1 >= MapSize()) return CMD_ERROR;
   585 		if (tile == end_tile) break;
   664 		if (tile == end_tile) break;
   586 
   665 
   587 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   666 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   588 
   667 
   589 		/* toggle railbit for the non-diagonal tracks */
   668 		/* toggle railbit for the non-diagonal tracks */
   590 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   669 		if (!IsDiagonalTrackdir(trackdir)) ToggleBit(trackdir, 0);
   591 	}
   670 	}
   592 
   671 
   593 	return (total_cost.GetCost() == 0) ? CMD_ERROR : total_cost;
   672 	return (total_cost.GetCost() == 0) ? CMD_ERROR : total_cost;
   594 }
   673 }
   595 
   674 
   604  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   683  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   605  * @see CmdRailTrackHelper
   684  * @see CmdRailTrackHelper
   606  */
   685  */
   607 CommandCost CmdBuildRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   686 CommandCost CmdBuildRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   608 {
   687 {
   609 	return CmdRailTrackHelper(tile, flags, p1, CLRBIT(p2, 7));
   688 	return CmdRailTrackHelper(tile, flags, p1, ClrBit(p2, 7));
   610 }
   689 }
   611 
   690 
   612 /** Build rail on a stretch of track.
   691 /** Build rail on a stretch of track.
   613  * Stub for the unified rail builder/remover
   692  * Stub for the unified rail builder/remover
   614  * @param tile start tile of drag
   693  * @param tile start tile of drag
   620  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   699  * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
   621  * @see CmdRailTrackHelper
   700  * @see CmdRailTrackHelper
   622  */
   701  */
   623 CommandCost CmdRemoveRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   702 CommandCost CmdRemoveRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   624 {
   703 {
   625 	return CmdRailTrackHelper(tile, flags, p1, SETBIT(p2, 7));
   704 	return CmdRailTrackHelper(tile, flags, p1, SetBit(p2, 7));
   626 }
   705 }
   627 
   706 
   628 /** Build a train depot
   707 /** Build a train depot
   629  * @param tile position of the train depot
   708  * @param tile position of the train depot
   630  * @param flags operation to perform
   709  * @param flags operation to perform
   701  * TODO: p2 should be replaced by two bits for "along" and "against" the track.
   780  * TODO: p2 should be replaced by two bits for "along" and "against" the track.
   702  */
   781  */
   703 CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   782 CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   704 {
   783 {
   705 	Track track = (Track)GB(p1, 0, 3);
   784 	Track track = (Track)GB(p1, 0, 3);
   706 	bool pre_signal = HASBIT(p1, 3);
   785 	bool pre_signal = HasBit(p1, 3);
   707 	SignalVariant sigvar = (pre_signal ^ HASBIT(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
   786 	SignalVariant sigvar = (pre_signal ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
   708 	CommandCost cost;
   787 	CommandCost cost;
   709 
   788 
   710 	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track))
   789 	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track))
   711 		return CMD_ERROR;
   790 		return CMD_ERROR;
   712 
   791 
   721 	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
   800 	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
   722 
   801 
   723 	{
   802 	{
   724 		/* See if this is a valid track combination for signals, (ie, no overlap) */
   803 		/* See if this is a valid track combination for signals, (ie, no overlap) */
   725 		TrackBits trackbits = GetTrackBits(tile);
   804 		TrackBits trackbits = GetTrackBits(tile);
   726 		if (KILL_FIRST_BIT(trackbits) != 0 && /* More than one track present */
   805 		if (KillFirstBit(trackbits) != TRACK_BIT_NONE && /* More than one track present */
   727 				trackbits != TRACK_BIT_HORZ &&
   806 				trackbits != TRACK_BIT_HORZ &&
   728 				trackbits != TRACK_BIT_VERT) {
   807 				trackbits != TRACK_BIT_VERT) {
   729 			return CMD_ERROR;
   808 			return CMD_ERROR;
   730 		}
   809 		}
   731 	}
   810 	}
   813 			if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false;
   892 			if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false;
   814 			signal_ctr++;
   893 			signal_ctr++;
   815 			if (IsDiagonalTrackdir(trackdir)) {
   894 			if (IsDiagonalTrackdir(trackdir)) {
   816 				signal_ctr++;
   895 				signal_ctr++;
   817 				/* Ensure signal_ctr even so X and Y pieces get signals */
   896 				/* Ensure signal_ctr even so X and Y pieces get signals */
   818 				CLRBIT(signal_ctr, 0);
   897 				ClrBit(signal_ctr, 0);
   819 			}
   898 			}
   820 			return true;
   899 			return true;
   821 
   900 
   822 		case MP_ROAD:
   901 		case MP_ROAD:
   823 			if (!IsLevelCrossing(tile)) return false;
   902 			if (!IsLevelCrossing(tile)) return false;
   864 	bool error = true;
   943 	bool error = true;
   865 	TileIndex end_tile;
   944 	TileIndex end_tile;
   866 	TileIndex start_tile = tile;
   945 	TileIndex start_tile = tile;
   867 
   946 
   868 	Track track = (Track)GB(p2, 0, 3);
   947 	Track track = (Track)GB(p2, 0, 3);
   869 	bool mode = HASBIT(p2, 3);
   948 	bool mode = HasBit(p2, 3);
   870 	bool semaphores = HASBIT(p2, 4);
   949 	bool semaphores = HasBit(p2, 4);
   871 	bool remove = HASBIT(p2, 5);
   950 	bool remove = HasBit(p2, 5);
   872 	bool autofill = HASBIT(p2, 6);
   951 	bool autofill = HasBit(p2, 6);
   873 	Trackdir trackdir = TrackToTrackdir(track);
   952 	Trackdir trackdir = TrackToTrackdir(track);
   874 	byte signal_density = GB(p2, 24, 8);
   953 	byte signal_density = GB(p2, 24, 8);
   875 
   954 
   876 	if (p1 >= MapSize()) return CMD_ERROR;
   955 	if (p1 >= MapSize()) return CMD_ERROR;
   877 	end_tile = p1;
   956 	end_tile = p1;
   903 	} else { // no signals exist, drag a two-way signal stretch
   982 	} else { // no signals exist, drag a two-way signal stretch
   904 		signals = SignalOnTrack(track);
   983 		signals = SignalOnTrack(track);
   905 	}
   984 	}
   906 
   985 
   907 	byte signal_dir = 0;
   986 	byte signal_dir = 0;
   908 	if (signals & SignalAlongTrackdir(trackdir))   SETBIT(signal_dir, 0);
   987 	if (signals & SignalAlongTrackdir(trackdir))   SetBit(signal_dir, 0);
   909 	if (signals & SignalAgainstTrackdir(trackdir)) SETBIT(signal_dir, 1);
   988 	if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1);
   910 
   989 
   911 	/* signal_ctr         - amount of tiles already processed
   990 	/* signal_ctr         - amount of tiles already processed
   912 	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
   991 	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
   913 	 **********
   992 	 **********
   914 	 * trackdir   - trackdir to build with autorail
   993 	 * trackdir   - trackdir to build with autorail
   924 			SB(p1, 3, 1, mode);
  1003 			SB(p1, 3, 1, mode);
   925 			SB(p1, 4, 1, semaphores);
  1004 			SB(p1, 4, 1, semaphores);
   926 
  1005 
   927 			/* Pick the correct orientation for the track direction */
  1006 			/* Pick the correct orientation for the track direction */
   928 			signals = 0;
  1007 			signals = 0;
   929 			if (HASBIT(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir);
  1008 			if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir);
   930 			if (HASBIT(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir);
  1009 			if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir);
   931 
  1010 
   932 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
  1011 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
   933 
  1012 
   934 			/* Be user-friendly and try placing signals as much as possible */
  1013 			/* Be user-friendly and try placing signals as much as possible */
   935 			if (CmdSucceeded(ret)) {
  1014 			if (CmdSucceeded(ret)) {
   951 
  1030 
   952 			/* toggle railbit for the non-diagonal tracks (|, -- tracks) */
  1031 			/* toggle railbit for the non-diagonal tracks (|, -- tracks) */
   953 			if (IsDiagonalTrackdir(trackdir)) {
  1032 			if (IsDiagonalTrackdir(trackdir)) {
   954 				signal_ctr++;
  1033 				signal_ctr++;
   955 			} else {
  1034 			} else {
   956 				ToggleBitT(trackdir, 0);
  1035 				ToggleBit(trackdir, 0);
   957 			}
  1036 			}
   958 		}
  1037 		}
   959 	}
  1038 	}
   960 
  1039 
   961 	return error ? CMD_ERROR : total_cost;
  1040 	return error ? CMD_ERROR : total_cost;
  1039  * - p2 = (bit 24-31) - user defined signals_density
  1118  * - p2 = (bit 24-31) - user defined signals_density
  1040  * @see CmdSignalTrackHelper
  1119  * @see CmdSignalTrackHelper
  1041  */
  1120  */
  1042 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1121 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1043 {
  1122 {
  1044 	return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit
  1123 	return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit
  1045 }
  1124 }
  1046 
  1125 
  1047 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
  1126 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
  1048 
  1127 
  1049 void *UpdateTrainPowerProc(Vehicle *v, void *data)
  1128 void *UpdateTrainPowerProc(Vehicle *v, void *data)
  1212 	}
  1291 	}
  1213 
  1292 
  1214 	switch (GetRailTileType(tile)) {
  1293 	switch (GetRailTileType(tile)) {
  1215 		case RAIL_TILE_SIGNALS:
  1294 		case RAIL_TILE_SIGNALS:
  1216 		case RAIL_TILE_NORMAL: {
  1295 		case RAIL_TILE_NORMAL: {
       
  1296 			bool water_ground = (GetRailGroundType(tile) == RAIL_GROUND_WATER);
       
  1297 
  1217 			TrackBits tracks = GetTrackBits(tile);
  1298 			TrackBits tracks = GetTrackBits(tile);
  1218 			while (tracks != TRACK_BIT_NONE) {
  1299 			while (tracks != TRACK_BIT_NONE) {
  1219 				Track track = RemoveFirstTrack(&tracks);
  1300 				Track track = RemoveFirstTrack(&tracks);
  1220 				ret = DoCommand(tile, 0, track, flags, CMD_REMOVE_SINGLE_RAIL);
  1301 				ret = DoCommand(tile, 0, track, flags, CMD_REMOVE_SINGLE_RAIL);
  1221 				if (CmdFailed(ret)) return CMD_ERROR;
  1302 				if (CmdFailed(ret)) return CMD_ERROR;
  1222 				cost.AddCost(ret);
  1303 				cost.AddCost(ret);
  1223 			}
  1304 			}
       
  1305 
       
  1306 			if (water_ground) {
       
  1307 				/* The track was removed, and left a coast tile. Now also clear the water. */
       
  1308 				if (flags & DC_EXEC) DoClearSquare(tile);
       
  1309 				cost.AddCost(_price.clear_water);
       
  1310 			}
       
  1311 
  1224 			return cost;
  1312 			return cost;
  1225 		}
  1313 		}
  1226 
  1314 
  1227 		case RAIL_TILE_DEPOT:
  1315 		case RAIL_TILE_DEPOT:
  1228 			return RemoveTrainDepot(tile, flags);
  1316 			return RemoveTrainDepot(tile, flags);
  1234 			return CMD_ERROR;
  1322 			return CMD_ERROR;
  1235 	}
  1323 	}
  1236 }
  1324 }
  1237 
  1325 
  1238 #include "table/track_land.h"
  1326 #include "table/track_land.h"
       
  1327 
       
  1328 /**
       
  1329  * Get surface height in point (x,y)
       
  1330  * On tiles with halftile foundations move (x,y) to a save point wrt. track
       
  1331  */
       
  1332 static uint GetSaveSlopeZ(uint x, uint y, Track track)
       
  1333 {
       
  1334 	switch (track) {
       
  1335 		case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break;
       
  1336 		case TRACK_LOWER: x |=  0xF; y |=  0xF; break;
       
  1337 		case TRACK_LEFT:  x |=  0xF; y &= ~0xF; break;
       
  1338 		case TRACK_RIGHT: x &= ~0xF; y |=  0xF; break;
       
  1339 		default: break;
       
  1340 	}
       
  1341 	return GetSlopeZ(x, y);
       
  1342 }
  1239 
  1343 
  1240 static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos)
  1344 static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos)
  1241 {
  1345 {
  1242 	bool side = (_opt.road_side != 0) && _patches.signal_side;
  1346 	bool side = (_opt.road_side != 0) && _patches.signal_side;
  1243 	static const Point SignalPositions[2][12] = {
  1347 	static const Point SignalPositions[2][12] = {
  1269 	uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
  1373 	uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
  1270 	uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
  1374 	uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
  1271 
  1375 
  1272 	SpriteID sprite;
  1376 	SpriteID sprite;
  1273 
  1377 
  1274 	/* _signal_base is set by our NewGRF Action 5 loader. If it is 0 then we
  1378 	if (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC) {
  1275 	 * just draw the standard signals, else we get the offset from _signal_base
       
  1276 	 * and draw that sprite. All the signal sprites are loaded sequentially. */
       
  1277 	if (_signal_base == 0 || (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC)) {
       
  1278 		sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition;
  1379 		sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition;
  1279 	} else {
  1380 	} else {
  1280 		sprite = _signal_base + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition;
  1381 		sprite = SPR_SIGNALS_BASE + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition;
  1281 	}
  1382 	}
  1282 
  1383 
  1283 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSlopeZ(x,y));
  1384 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
  1284 }
  1385 }
  1285 
  1386 
  1286 static uint32 _drawtile_track_palette;
  1387 static uint32 _drawtile_track_palette;
  1287 
  1388 
  1288 
  1389 
  1335  */
  1436  */
  1336 static void DrawTrackFence_NS_1(const TileInfo *ti)
  1437 static void DrawTrackFence_NS_1(const TileInfo *ti)
  1337 {
  1438 {
  1338 	int z = ti->z;
  1439 	int z = ti->z;
  1339 	if (ti->tileh & SLOPE_W) z += TILE_HEIGHT;
  1440 	if (ti->tileh & SLOPE_W) z += TILE_HEIGHT;
       
  1441 	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
  1340 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
  1442 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
  1341 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1443 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1342 }
  1444 }
  1343 
  1445 
  1344 /**
  1446 /**
  1346  */
  1448  */
  1347 static void DrawTrackFence_NS_2(const TileInfo *ti)
  1449 static void DrawTrackFence_NS_2(const TileInfo *ti)
  1348 {
  1450 {
  1349 	int z = ti->z;
  1451 	int z = ti->z;
  1350 	if (ti->tileh & SLOPE_E) z += TILE_HEIGHT;
  1452 	if (ti->tileh & SLOPE_E) z += TILE_HEIGHT;
       
  1453 	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
  1351 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
  1454 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_VERT, _drawtile_track_palette,
  1352 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1455 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1353 }
  1456 }
  1354 
  1457 
  1355 /**
  1458 /**
  1357  */
  1460  */
  1358 static void DrawTrackFence_WE_1(const TileInfo *ti)
  1461 static void DrawTrackFence_WE_1(const TileInfo *ti)
  1359 {
  1462 {
  1360 	int z = ti->z;
  1463 	int z = ti->z;
  1361 	if (ti->tileh & SLOPE_N) z += TILE_HEIGHT;
  1464 	if (ti->tileh & SLOPE_N) z += TILE_HEIGHT;
       
  1465 	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
  1362 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
  1466 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
  1363 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1467 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1364 }
  1468 }
  1365 
  1469 
  1366 /**
  1470 /**
  1368  */
  1472  */
  1369 static void DrawTrackFence_WE_2(const TileInfo *ti)
  1473 static void DrawTrackFence_WE_2(const TileInfo *ti)
  1370 {
  1474 {
  1371 	int z = ti->z;
  1475 	int z = ti->z;
  1372 	if (ti->tileh & SLOPE_S) z += TILE_HEIGHT;
  1476 	if (ti->tileh & SLOPE_S) z += TILE_HEIGHT;
       
  1477 	if (IsSteepSlope(ti->tileh)) z += TILE_HEIGHT;
  1373 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
  1478 	AddSortableSpriteToDraw(SPR_TRACK_FENCE_FLAT_HORZ, _drawtile_track_palette,
  1374 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1479 		ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, 4, z);
  1375 }
  1480 }
  1376 
  1481 
  1377 
  1482 
  1386 		case RAIL_GROUND_FENCE_NESW:   DrawTrackFence_NE_SW(ti); break;
  1491 		case RAIL_GROUND_FENCE_NESW:   DrawTrackFence_NE_SW(ti); break;
  1387 		case RAIL_GROUND_FENCE_VERT1:  DrawTrackFence_NS_1(ti);  break;
  1492 		case RAIL_GROUND_FENCE_VERT1:  DrawTrackFence_NS_1(ti);  break;
  1388 		case RAIL_GROUND_FENCE_VERT2:  DrawTrackFence_NS_2(ti);  break;
  1493 		case RAIL_GROUND_FENCE_VERT2:  DrawTrackFence_NS_2(ti);  break;
  1389 		case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti);  break;
  1494 		case RAIL_GROUND_FENCE_HORIZ1: DrawTrackFence_WE_1(ti);  break;
  1390 		case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti);  break;
  1495 		case RAIL_GROUND_FENCE_HORIZ2: DrawTrackFence_WE_2(ti);  break;
       
  1496 		case RAIL_GROUND_WATER:
       
  1497 			switch (GetHalftileSlopeCorner(ti->tileh)) {
       
  1498 				case CORNER_W: DrawTrackFence_NS_1(ti); break;
       
  1499 				case CORNER_S: DrawTrackFence_WE_2(ti); break;
       
  1500 				case CORNER_E: DrawTrackFence_NS_2(ti); break;
       
  1501 				case CORNER_N: DrawTrackFence_WE_1(ti); break;
       
  1502 				default: NOT_REACHED();
       
  1503 			}
       
  1504 			break;
  1391 		default: break;
  1505 		default: break;
  1392 	}
  1506 	}
  1393 }
  1507 }
  1394 
  1508 
  1395 
  1509 
  1399  * @param track TrackBits to draw
  1513  * @param track TrackBits to draw
  1400  */
  1514  */
  1401 static void DrawTrackBits(TileInfo* ti, TrackBits track)
  1515 static void DrawTrackBits(TileInfo* ti, TrackBits track)
  1402 {
  1516 {
  1403 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
  1517 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
       
  1518 	RailGroundType rgt = GetRailGroundType(ti->tile);
       
  1519 	Foundation f = GetRailFoundation(ti->tileh, track);
       
  1520 	Corner halftile_corner = CORNER_INVALID;
       
  1521 
       
  1522 	if (IsNonContinuousFoundation(f)) {
       
  1523 		/* Save halftile corner */
       
  1524 		halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
       
  1525 		/* Draw lower part first */
       
  1526 		track &= ~CornerToTrackBits(halftile_corner);
       
  1527 		f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE);
       
  1528 	}
       
  1529 
       
  1530 	DrawFoundation(ti, f);
       
  1531 	/* DrawFoundation modifies ti */
       
  1532 
  1404 	SpriteID image;
  1533 	SpriteID image;
  1405 	SpriteID pal = PAL_NONE;
  1534 	SpriteID pal = PAL_NONE;
  1406 	bool junction = false;
  1535 	bool junction = false;
  1407 
  1536 
  1408 	/* Select the sprite to use. */
  1537 	/* Select the sprite to use. */
  1409 	(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1538 	if (track == 0) {
  1410 	(image++,                           track == TRACK_BIT_X) ||
  1539 		/* Clear ground (only track on halftile foundation) */
  1411 	(image++,                           track == TRACK_BIT_UPPER) ||
  1540 		if (rgt == RAIL_GROUND_WATER) {
  1412 	(image++,                           track == TRACK_BIT_LOWER) ||
  1541 			image = SPR_FLAT_WATER_TILE;
  1413 	(image++,                           track == TRACK_BIT_RIGHT) ||
  1542 		} else {
  1414 	(image++,                           track == TRACK_BIT_LEFT) ||
  1543 			switch (rgt) {
  1415 	(image++,                           track == TRACK_BIT_CROSS) ||
  1544 				case RAIL_GROUND_BARREN:     image = SPR_FLAT_BARE_LAND;  break;
  1416 
  1545 				case RAIL_GROUND_ICE_DESERT: image = SPR_FLAT_SNOWY_TILE; break;
  1417 	(image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
  1546 				default:                     image = SPR_FLAT_GRASS_TILE; break;
  1418 	(image++,                            track == TRACK_BIT_VERT) ||
  1547 			}
  1419 
  1548 			image += _tileh_to_sprite[ti->tileh];
  1420 	(junction = true, false) ||
  1549 		}
  1421 	(image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
  1550 	} else {
  1422 	(image++,                          (track & TRACK_BIT_3WAY_SW) == 0) ||
  1551 		if (ti->tileh != SLOPE_FLAT) {
  1423 	(image++,                          (track & TRACK_BIT_3WAY_NW) == 0) ||
  1552 			/* track on non-flat ground */
  1424 	(image++,                          (track & TRACK_BIT_3WAY_SE) == 0) ||
  1553 			image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1425 	(image++, true);
  1554 		} else {
  1426 
  1555 			/* track on flat ground */
  1427 	if (ti->tileh != SLOPE_FLAT) {
  1556 			(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1428 		DrawFoundation(ti, GetRailFoundation(ti->tileh, track));
  1557 			(image++,                           track == TRACK_BIT_X) ||
  1429 
  1558 			(image++,                           track == TRACK_BIT_UPPER) ||
  1430 		/* DrawFoundation() modifies it.
  1559 			(image++,                           track == TRACK_BIT_LOWER) ||
  1431 		 * Default sloped sprites.. */
  1560 			(image++,                           track == TRACK_BIT_RIGHT) ||
  1432 		if (ti->tileh != SLOPE_FLAT) image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1561 			(image++,                           track == TRACK_BIT_LEFT) ||
  1433 	}
  1562 			(image++,                           track == TRACK_BIT_CROSS) ||
  1434 
  1563 
  1435 	switch (GetRailGroundType(ti->tile)) {
  1564 			(image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
  1436 		case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
  1565 			(image++,                            track == TRACK_BIT_VERT) ||
  1437 		case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break;
  1566 
  1438 		default: break;
  1567 			(junction = true, false) ||
       
  1568 			(image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
       
  1569 			(image++,                          (track & TRACK_BIT_3WAY_SW) == 0) ||
       
  1570 			(image++,                          (track & TRACK_BIT_3WAY_NW) == 0) ||
       
  1571 			(image++,                          (track & TRACK_BIT_3WAY_SE) == 0) ||
       
  1572 			(image++, true);
       
  1573 		}
       
  1574 
       
  1575 		switch (rgt) {
       
  1576 			case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
       
  1577 			case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset;  break;
       
  1578 			case RAIL_GROUND_WATER:      NOT_REACHED();
       
  1579 			default: break;
       
  1580 		}
  1439 	}
  1581 	}
  1440 
  1582 
  1441 	DrawGroundSprite(image, pal);
  1583 	DrawGroundSprite(image, pal);
  1442 
  1584 
  1443 	/* Draw track pieces individually for junction tiles */
  1585 	/* Draw track pieces individually for junction tiles */
  1447 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1589 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1448 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1590 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1449 		if (track & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
  1591 		if (track & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
  1450 		if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
  1592 		if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
  1451 	}
  1593 	}
       
  1594 
       
  1595 	if (IsValidCorner(halftile_corner)) {
       
  1596 		DrawFoundation(ti, HalftileFoundation(halftile_corner));
       
  1597 
       
  1598 		/* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
       
  1599 		Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
       
  1600 		image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y;
       
  1601 		pal = PAL_NONE;
       
  1602 		switch (rgt) {
       
  1603 			case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
       
  1604 			case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset;  break;
       
  1605 			default: break;
       
  1606 		}
       
  1607 
       
  1608 		static const int INF = 1000; // big number compared to tilesprite size
       
  1609 		static const SubSprite _halftile_sub_sprite[4] = {
       
  1610 			{ -INF    , -INF  , 32 - 33, INF     }, // CORNER_W, clip 33 pixels from right
       
  1611 			{ -INF    ,  0 + 7, INF    , INF     }, // CORNER_S, clip 7 pixels from top
       
  1612 			{ -31 + 33, -INF  , INF    , INF     }, // CORNER_E, clip 33 pixels from left
       
  1613 			{ -INF    , -INF  , INF    , 30 - 23 }  // CORNER_N, clip 23 pixels from bottom
       
  1614 		};
       
  1615 
       
  1616 		DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
       
  1617 	}
  1452 }
  1618 }
  1453 
  1619 
  1454 static void DrawSignals(TileIndex tile, TrackBits rails)
  1620 static void DrawSignals(TileIndex tile, TrackBits rails)
  1455 {
  1621 {
  1456 #define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z)
  1622 #define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z)
  1493 	if (IsPlainRailTile(ti->tile)) {
  1659 	if (IsPlainRailTile(ti->tile)) {
  1494 		TrackBits rails = GetTrackBits(ti->tile);
  1660 		TrackBits rails = GetTrackBits(ti->tile);
  1495 
  1661 
  1496 		DrawTrackBits(ti, rails);
  1662 		DrawTrackBits(ti, rails);
  1497 
  1663 
  1498 		if (HASBIT(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti);
  1664 		if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti);
  1499 
  1665 
  1500 		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
  1666 		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
  1501 
  1667 
  1502 		if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
  1668 		if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
  1503 	} else {
  1669 	} else {
  1533 			if (statspec != NULL) {
  1699 			if (statspec != NULL) {
  1534 				/* emulate station tile - open with building */
  1700 				/* emulate station tile - open with building */
  1535 				const Station* st = ComposeWaypointStation(ti->tile);
  1701 				const Station* st = ComposeWaypointStation(ti->tile);
  1536 				uint gfx = 2;
  1702 				uint gfx = 2;
  1537 
  1703 
  1538 				if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) {
  1704 				if (HasBit(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) {
  1539 					uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  1705 					uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  1540 					if (callback != CALLBACK_FAILED) gfx = callback;
  1706 					if (callback != CALLBACK_FAILED) gfx = callback;
  1541 				}
  1707 				}
  1542 
  1708 
  1543 				if (statspec->renderdata == NULL) {
  1709 				if (statspec->renderdata == NULL) {
  1548 
  1714 
  1549 				if (dts != NULL && dts->seq != NULL) {
  1715 				if (dts != NULL && dts->seq != NULL) {
  1550 					relocation = GetCustomStationRelocation(statspec, st, ti->tile);
  1716 					relocation = GetCustomStationRelocation(statspec, st, ti->tile);
  1551 
  1717 
  1552 					image = dts->ground_sprite;
  1718 					image = dts->ground_sprite;
  1553 					if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
  1719 					if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  1554 						image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
  1720 						image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
  1555 						image += rti->custom_ground_offset;
  1721 						image += rti->custom_ground_offset;
  1556 					} else {
  1722 					} else {
  1557 						image += rti->total_offset;
  1723 						image += rti->total_offset;
  1558 					}
  1724 					}
  1578 			SpriteID pal;
  1744 			SpriteID pal;
  1579 
  1745 
  1580 			/* Unlike stations, our default waypoint has no variation for
  1746 			/* Unlike stations, our default waypoint has no variation for
  1581 			 * different railtype, so don't use the railtype offset if
  1747 			 * different railtype, so don't use the railtype offset if
  1582 			 * no relocation is set */
  1748 			 * no relocation is set */
  1583 			if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
  1749 			if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  1584 				image += rti->total_offset;
  1750 				image += rti->total_offset;
  1585 			} else {
  1751 			} else {
  1586 				image += relocation;
  1752 				image += relocation;
  1587 			}
  1753 			}
  1588 
  1754 
  1589 			if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) {
  1755 			if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
  1590 				pal = _drawtile_track_palette;
  1756 				pal = _drawtile_track_palette;
  1591 			} else {
  1757 			} else {
  1592 				pal = dtss->pal;
  1758 				pal = dtss->pal;
  1593 			}
  1759 			}
  1594 
  1760 
  1596 				AddSortableSpriteToDraw(
  1762 				AddSortableSpriteToDraw(
  1597 					image, pal,
  1763 					image, pal,
  1598 					ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  1764 					ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  1599 					dtss->size_x, dtss->size_y,
  1765 					dtss->size_x, dtss->size_y,
  1600 					dtss->size_z, ti->z + dtss->delta_z,
  1766 					dtss->size_z, ti->z + dtss->delta_z,
  1601 					HASBIT(_transparent_opt, TO_BUILDINGS)
  1767 					IsTransparencySet(TO_BUILDINGS)
  1602 				);
  1768 				);
  1603 			} else {
  1769 			} else {
  1604 				AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
  1770 				AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
  1605 			}
  1771 			}
  1606 		}
  1772 		}
  1616 	DrawSprite(ground, PAL_NONE, x, y);
  1782 	DrawSprite(ground, PAL_NONE, x, y);
  1617 	for (; dtss->image != 0; dtss++) {
  1783 	for (; dtss->image != 0; dtss++) {
  1618 		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
  1784 		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
  1619 		SpriteID image = dtss->image + offset;
  1785 		SpriteID image = dtss->image + offset;
  1620 
  1786 
  1621 		DrawSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y);
  1787 		DrawSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y);
  1622 	}
  1788 	}
  1623 }
  1789 }
  1624 
  1790 
  1625 void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype)
  1791 void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype)
  1626 {
  1792 {
  1931 
  2097 
  1932 static void TileLoop_Track(TileIndex tile)
  2098 static void TileLoop_Track(TileIndex tile)
  1933 {
  2099 {
  1934 	RailGroundType old_ground = GetRailGroundType(tile);
  2100 	RailGroundType old_ground = GetRailGroundType(tile);
  1935 	RailGroundType new_ground;
  2101 	RailGroundType new_ground;
       
  2102 
       
  2103 	if (old_ground == RAIL_GROUND_WATER) {
       
  2104 		TileLoop_Water(tile);
       
  2105 		return;
       
  2106 	}
  1936 
  2107 
  1937 	switch (_opt.landscape) {
  2108 	switch (_opt.landscape) {
  1938 		case LT_ARCTIC:
  2109 		case LT_ARCTIC:
  1939 			if (GetTileZ(tile) > GetSnowLine()) {
  2110 			if (GetTileZ(tile) > GetSnowLine()) {
  1940 				new_ground = RAIL_GROUND_ICE_DESERT;
  2111 				new_ground = RAIL_GROUND_ICE_DESERT;
  2231 
  2402 
  2232 	/* Get the slopes on top of the foundations */
  2403 	/* Get the slopes on top of the foundations */
  2233 	z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old);
  2404 	z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), &tileh_old);
  2234 	z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new);
  2405 	z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), &tileh_new);
  2235 
  2406 
  2236 	Slope track_corner;
  2407 	Corner track_corner;
  2237 	switch (rail_bits) {
  2408 	switch (rail_bits) {
  2238 		case TRACK_BIT_LEFT:  track_corner = SLOPE_W; break;
  2409 		case TRACK_BIT_LEFT:  track_corner = CORNER_W; break;
  2239 		case TRACK_BIT_LOWER: track_corner = SLOPE_S; break;
  2410 		case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
  2240 		case TRACK_BIT_RIGHT: track_corner = SLOPE_E; break;
  2411 		case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
  2241 		case TRACK_BIT_UPPER: track_corner = SLOPE_N; break;
  2412 		case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
  2242 
  2413 
  2243 		/* Surface slope must not be changed */
  2414 		/* Surface slope must not be changed */
  2244 		default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
  2415 		default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
  2245 	}
  2416 	}
  2246 
  2417 
  2247 	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
  2418 	/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
  2248 	if ((tileh_old & track_corner) != 0) z_old += TILE_HEIGHT;
  2419 	z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner);
  2249 	if ((tileh_new & track_corner) != 0) z_new += TILE_HEIGHT;
  2420 	z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner);
  2250 	if (z_old != z_new) return CMD_ERROR;
  2421 	if (z_old != z_new) return CMD_ERROR;
  2251 
  2422 
       
  2423 	CommandCost cost = CommandCost(_price.terraform);
  2252 	/* Make the ground dirty, if surface slope has changed */
  2424 	/* Make the ground dirty, if surface slope has changed */
  2253 	if ((tileh_old != tileh_new) && ((flags & DC_EXEC) != 0)) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2425 	if (tileh_old != tileh_new) {
  2254 
  2426 		if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water);
  2255 	return _price.terraform;
  2427 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
       
  2428 	}
       
  2429 	return  cost;
  2256 }
  2430 }
  2257 
  2431 
  2258 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
  2432 static CommandCost TerraformTile_Track(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
  2259 {
  2433 {
  2260 	uint z_old;
  2434 	uint z_old;
  2261 	Slope tileh_old = GetTileSlope(tile, &z_old);
  2435 	Slope tileh_old = GetTileSlope(tile, &z_old);
  2262 	if (IsPlainRailTile(tile)) {
  2436 	if (IsPlainRailTile(tile)) {
  2263 		TrackBits rail_bits = GetTrackBits(tile);
  2437 		TrackBits rail_bits = GetTrackBits(tile);
       
  2438 		bool was_water = GetRailGroundType(tile) == RAIL_GROUND_WATER;
  2264 
  2439 
  2265 		_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
  2440 		_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
  2266 
  2441 
  2267 		/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
  2442 		/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
  2268 		CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
  2443 		CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
  2269 
  2444 
  2270 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
  2445 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
  2271 		Slope allowed_corner;
  2446 		Corner allowed_corner;
  2272 		switch (rail_bits) {
  2447 		switch (rail_bits) {
  2273 			case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break;
  2448 			case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break;
  2274 			case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
  2449 			case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break;
  2275 			case TRACK_BIT_LEFT:  allowed_corner = SLOPE_E; break;
  2450 			case TRACK_BIT_LEFT:  allowed_corner = CORNER_E; break;
  2276 			case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
  2451 			case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break;
  2277 			default: return autoslope_result;
  2452 			default: return autoslope_result;
  2278 		}
  2453 		}
  2279 
  2454 
  2280 		Slope track_corners = ComplementSlope(allowed_corner);
       
  2281 
       
  2282 		Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
  2455 		Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
  2283 		switch (f_old) {
  2456 
  2284 			case FOUNDATION_NONE:
  2457 		/* Do not allow terraforming if allowed_corner is part of anti-zig-zag foundations */
  2285 				/* Everything is valid, which only changes allowed_corner */
  2458 		if (tileh_old != SLOPE_NS && tileh_old != SLOPE_EW && IsSpecialRailFoundation(f_old)) return autoslope_result;
  2286 
  2459 
  2287 				/* Compute height of track */
  2460 		/* Everything is valid, which only changes allowed_corner */
  2288 				if (tileh_old == track_corners) z_old += TILE_HEIGHT;
  2461 		for (Corner corner = (Corner)0; corner < CORNER_END; corner = (Corner)(corner + 1)) {
  2289 				if (tileh_new == track_corners) {
  2462 			if (allowed_corner == corner) continue;
  2290 					z_new += TILE_HEIGHT;
  2463 			if (z_old + GetSlopeZInCorner(tileh_old, corner) != z_new + GetSlopeZInCorner(tileh_new, corner)) return autoslope_result;
  2291 				} else {
       
  2292 					/* do not build a foundation */
       
  2293 					if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result;
       
  2294 				}
       
  2295 
       
  2296 				/* Track height must remain unchanged */
       
  2297 				if (z_old != z_new) return autoslope_result;
       
  2298 				break;
       
  2299 
       
  2300 			case FOUNDATION_LEVELED:
       
  2301 				/* Is allowed_corner covered by the foundation? */
       
  2302 				if ((tileh_old & allowed_corner) == 0) return autoslope_result;
       
  2303 
       
  2304 				/* allowed_corner may only be raised -> steep slope */
       
  2305 				if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result;
       
  2306 				break;
       
  2307 
       
  2308 			case FOUNDATION_STEEP_LOWER:
       
  2309 				/* Only allow to lower highest corner */
       
  2310 				if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result;
       
  2311 				break;
       
  2312 
       
  2313 			case FOUNDATION_STEEP_HIGHER:
       
  2314 				return autoslope_result;
       
  2315 
       
  2316 			default: NOT_REACHED();
       
  2317 		}
  2464 		}
  2318 
  2465 
  2319 		/* Make the ground dirty */
  2466 		/* Make the ground dirty */
  2320 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2467 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2321 
  2468 
  2322 		/* allow terraforming, no extra costs */
  2469 		/* allow terraforming */
  2323 		return CommandCost();
  2470 		return (was_water ? CommandCost(_price.clear_water) : CommandCost());
  2324 	} else {
  2471 	} else {
  2325 		if (_patches.build_on_slopes && AutoslopeEnabled()) {
  2472 		if (_patches.build_on_slopes && AutoslopeEnabled()) {
  2326 			switch (GetRailTileType(tile)) {
  2473 			switch (GetRailTileType(tile)) {
  2327 				case RAIL_TILE_WAYPOINT: {
  2474 				case RAIL_TILE_WAYPOINT: {
  2328 					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
  2475 					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));