src/rail_cmd.cpp
changeset 6916 e87d54a598ea
parent 6902 9da0ee122fd5
child 6923 6913c8a82cc0
equal deleted inserted replaced
6915:99e67df845fd 6916:e87d54a598ea
    77  *               11uuuudd => rail depot
    77  *               11uuuudd => rail depot
    78  */
    78  */
    79 
    79 
    80 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
    80 static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
    81 {
    81 {
    82 	TrackBits current; /* The current track layout */
    82 	TrackBits current; // The current track layout
    83 	TrackBits future; /* The track layout we want to build */
    83 	TrackBits future;  // The track layout we want to build
    84 	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
    84 	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
    85 
    85 
    86 	if (!IsPlainRailTile(tile)) return false;
    86 	if (!IsPlainRailTile(tile)) return false;
    87 
    87 
    88 	/* So, we have a tile with tracks on it (and possibly signals). Let's see
    88 	/* So, we have a tile with tracks on it (and possibly signals). Let's see
   109 }
   109 }
   110 
   110 
   111 
   111 
   112 static const TrackBits _valid_tileh_slopes[][15] = {
   112 static const TrackBits _valid_tileh_slopes[][15] = {
   113 
   113 
   114 // set of normal ones
   114 /* set of normal ones */
   115 {
   115 {
   116 	TRACK_BIT_ALL,
   116 	TRACK_BIT_ALL,
   117 	TRACK_BIT_RIGHT,
   117 	TRACK_BIT_RIGHT,
   118 	TRACK_BIT_UPPER,
   118 	TRACK_BIT_UPPER,
   119 	TRACK_BIT_X,
   119 	TRACK_BIT_X,
   131 	TRACK_BIT_X,
   131 	TRACK_BIT_X,
   132 	TRACK_BIT_UPPER,
   132 	TRACK_BIT_UPPER,
   133 	TRACK_BIT_RIGHT,
   133 	TRACK_BIT_RIGHT,
   134 },
   134 },
   135 
   135 
   136 // allowed rail for an evenly raised platform
   136 /* allowed rail for an evenly raised platform */
   137 {
   137 {
   138 	TRACK_BIT_NONE,
   138 	TRACK_BIT_NONE,
   139 	TRACK_BIT_LEFT,
   139 	TRACK_BIT_LEFT,
   140 	TRACK_BIT_LOWER,
   140 	TRACK_BIT_LOWER,
   141 	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
   141 	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
   197 			if (valid & rail_bits) return _price.terraform;
   197 			if (valid & rail_bits) return _price.terraform;
   198 		}
   198 		}
   199 	} else {
   199 	} else {
   200 		rail_bits |= existing;
   200 		rail_bits |= existing;
   201 
   201 
   202 		// don't allow building on the lower side of a coast
   202 		/* don't allow building on the lower side of a coast */
   203 		if (IsTileType(tile, MP_WATER) &&
   203 		if (IsTileType(tile, MP_WATER) &&
   204 				~_valid_tileh_slopes[1][tileh] & rail_bits) {
   204 				~_valid_tileh_slopes[1][tileh] & rail_bits) {
   205 			return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   205 			return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   206 		}
   206 		}
   207 
   207 
   208 		// no special foundation
   208 		/* no special foundation */
   209 		if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0)
   209 		if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0)
   210 			return 0;
   210 			return 0;
   211 
   211 
   212 		if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up
   212 		if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up
   213 					(rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) &&
   213 					(rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) &&
   257 					!EnsureNoVehicleOnGround(tile)) {
   257 					!EnsureNoVehicleOnGround(tile)) {
   258 				return CMD_ERROR;
   258 				return CMD_ERROR;
   259 			}
   259 			}
   260 			if (!IsTileOwner(tile, _current_player) ||
   260 			if (!IsTileOwner(tile, _current_player) ||
   261 					!IsCompatibleRail(GetRailType(tile), railtype)) {
   261 					!IsCompatibleRail(GetRailType(tile), railtype)) {
   262 				// Get detailed error message
   262 				/* Get detailed error message */
   263 				return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   263 				return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   264 			}
   264 			}
   265 
   265 
   266 			ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
   266 			ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
   267 			if (CmdFailed(ret)) return ret;
   267 			if (CmdFailed(ret)) return ret;
   432 	int ey = TileY(end);
   432 	int ey = TileY(end);
   433 	int dx, dy, trdx, trdy;
   433 	int dx, dy, trdx, trdy;
   434 
   434 
   435 	if (!ValParamTrackOrientation(TrackdirToTrack(*trackdir))) return CMD_ERROR;
   435 	if (!ValParamTrackOrientation(TrackdirToTrack(*trackdir))) return CMD_ERROR;
   436 
   436 
   437 	// calculate delta x,y from start to end tile
   437 	/* calculate delta x,y from start to end tile */
   438 	dx = ex - x;
   438 	dx = ex - x;
   439 	dy = ey - y;
   439 	dy = ey - y;
   440 
   440 
   441 	// calculate delta x,y for the first direction
   441 	/* calculate delta x,y for the first direction */
   442 	trdx = _trackdelta[*trackdir].x;
   442 	trdx = _trackdelta[*trackdir].x;
   443 	trdy = _trackdelta[*trackdir].y;
   443 	trdy = _trackdelta[*trackdir].y;
   444 
   444 
   445 	if (!IsDiagonalTrackdir(*trackdir)) {
   445 	if (!IsDiagonalTrackdir(*trackdir)) {
   446 		trdx += _trackdelta[*trackdir ^ 1].x;
   446 		trdx += _trackdelta[*trackdir ^ 1].x;
   447 		trdy += _trackdelta[*trackdir ^ 1].y;
   447 		trdy += _trackdelta[*trackdir ^ 1].y;
   448 	}
   448 	}
   449 
   449 
   450 	// validate the direction
   450 	/* validate the direction */
   451 	while (
   451 	while (
   452 		(trdx <= 0 && dx > 0) ||
   452 		(trdx <= 0 && dx > 0) ||
   453 		(trdx >= 0 && dx < 0) ||
   453 		(trdx >= 0 && dx < 0) ||
   454 		(trdy <= 0 && dy > 0) ||
   454 		(trdy <= 0 && dy > 0) ||
   455 		(trdy >= 0 && dy < 0)
   455 		(trdy >= 0 && dy < 0)
   461 		} else { // other direction is invalid too, invalid drag
   461 		} else { // other direction is invalid too, invalid drag
   462 			return CMD_ERROR;
   462 			return CMD_ERROR;
   463 		}
   463 		}
   464 	}
   464 	}
   465 
   465 
   466 	// (for diagonal tracks, this is already made sure of by above test), but:
   466 	/* (for diagonal tracks, this is already made sure of by above test), but:
   467 	// for non-diagonal tracks, check if the start and end tile are on 1 line
   467 	 * for non-diagonal tracks, check if the start and end tile are on 1 line */
   468 	if (!IsDiagonalTrackdir(*trackdir)) {
   468 	if (!IsDiagonalTrackdir(*trackdir)) {
   469 		trdx = _trackdelta[*trackdir].x;
   469 		trdx = _trackdelta[*trackdir].x;
   470 		trdy = _trackdelta[*trackdir].y;
   470 		trdy = _trackdelta[*trackdir].y;
   471 		if (abs(dx) != abs(dy) && abs(dx) + abs(trdy) != abs(dy) + abs(trdx))
   471 		if (abs(dx) != abs(dy) && abs(dx) + abs(trdy) != abs(dy) + abs(trdx))
   472 			return CMD_ERROR;
   472 			return CMD_ERROR;
   515 
   515 
   516 		if (tile == end_tile) break;
   516 		if (tile == end_tile) break;
   517 
   517 
   518 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   518 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   519 
   519 
   520 		// toggle railbit for the non-diagonal tracks
   520 		/* toggle railbit for the non-diagonal tracks */
   521 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   521 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   522 	}
   522 	}
   523 
   523 
   524 	return (total_cost == 0) ? CMD_ERROR : total_cost;
   524 	return (total_cost == 0) ? CMD_ERROR : total_cost;
   525 }
   525 }
   647 	}
   647 	}
   648 
   648 
   649 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   649 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   650 
   650 
   651 	if (!HasSignalOnTrack(tile, track)) {
   651 	if (!HasSignalOnTrack(tile, track)) {
   652 		// build new signals
   652 		/* build new signals */
   653 		cost = _price.build_signals;
   653 		cost = _price.build_signals;
   654 	} else {
   654 	} else {
   655 		if (p2 != 0 && sigvar != GetSignalVariant(tile)) {
   655 		if (p2 != 0 && sigvar != GetSignalVariant(tile)) {
   656 			// convert signals <-> semaphores
   656 			/* convert signals <-> semaphores */
   657 			cost = _price.build_signals + _price.remove_signals;
   657 			cost = _price.build_signals + _price.remove_signals;
   658 		} else {
   658 		} else {
   659 			// it is free to change orientation/pre-exit-combo signals
   659 			// it is free to change orientation/pre-exit-combo signals
   660 			cost = 0;
   660 			cost = 0;
   661 		}
   661 		}
   662 	}
   662 	}
   663 
   663 
   664 	if (flags & DC_EXEC) {
   664 	if (flags & DC_EXEC) {
   665 		if (!HasSignals(tile)) {
   665 		if (!HasSignals(tile)) {
   666 			// there are no signals at all on this tile yet
   666 			/* there are no signals at all on this tile yet */
   667 			SetHasSignals(tile, true);
   667 			SetHasSignals(tile, true);
   668 			_m[tile].m2 |= 0xF0;              // all signals are on
   668 			_m[tile].m2 |= 0xF0;              // all signals are on
   669 			_m[tile].m3 &= ~0xF0;          // no signals built by default
   669 			_m[tile].m3 &= ~0xF0;             // no signals built by default
   670 			SetSignalType(tile, SIGTYPE_NORMAL);
   670 			SetSignalType(tile, SIGTYPE_NORMAL);
   671 			SetSignalVariant(tile, sigvar);
   671 			SetSignalVariant(tile, sigvar);
   672 		}
   672 		}
   673 
   673 
   674 		if (p2 == 0) {
   674 		if (p2 == 0) {
   675 			if (!HasSignalOnTrack(tile, track)) {
   675 			if (!HasSignalOnTrack(tile, track)) {
   676 				// build new signals
   676 				/* build new signals */
   677 				_m[tile].m3 |= SignalOnTrack(track);
   677 				_m[tile].m3 |= SignalOnTrack(track);
   678 			} else {
   678 			} else {
   679 				if (pre_signal) {
   679 				if (pre_signal) {
   680 					// cycle between normal -> pre -> exit -> combo -> ...
   680 					/* cycle between normal -> pre -> exit -> combo -> ... */
   681 					SignalType type = GetSignalType(tile);
   681 					SignalType type = GetSignalType(tile);
   682 
   682 
   683 					SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
   683 					SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
   684 				} else {
   684 				} else {
   685 					CycleSignalSide(tile, track);
   685 					CycleSignalSide(tile, track);
   744 	// copy the signal-style of the first rail-piece if existing
   744 	// copy the signal-style of the first rail-piece if existing
   745 	if (HasSignals(tile)) {
   745 	if (HasSignals(tile)) {
   746 		signals = _m[tile].m3 & SignalOnTrack(track);
   746 		signals = _m[tile].m3 & SignalOnTrack(track);
   747 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
   747 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
   748 
   748 
   749 		// copy signal/semaphores style (independent of CTRL)
   749 		/* copy signal/semaphores style (independent of CTRL) */
   750 		semaphores = GetSignalVariant(tile) != SIG_ELECTRIC;
   750 		semaphores = GetSignalVariant(tile) != SIG_ELECTRIC;
   751 	} else { // no signals exist, drag a two-way signal stretch
   751 	} else { // no signals exist, drag a two-way signal stretch
   752 		signals = SignalOnTrack(track);
   752 		signals = SignalOnTrack(track);
   753 	}
   753 	}
   754 
   754 
   760 	 * signals    - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
   760 	 * signals    - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
   761 	 *              and convert all others to semaphore/signal
   761 	 *              and convert all others to semaphore/signal
   762 	 * remove     - 1 remove signals, 0 build signals */
   762 	 * remove     - 1 remove signals, 0 build signals */
   763 	signal_ctr = total_cost = 0;
   763 	signal_ctr = total_cost = 0;
   764 	for (;;) {
   764 	for (;;) {
   765 		// only build/remove signals with the specified density
   765 		/* only build/remove signals with the specified density */
   766 		if (signal_ctr % signal_density == 0) {
   766 		if (signal_ctr % signal_density == 0) {
   767 			uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
   767 			uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
   768 			SB(p1, 3, 1, mode);
   768 			SB(p1, 3, 1, mode);
   769 			SB(p1, 4, 1, semaphores);
   769 			SB(p1, 4, 1, semaphores);
   770 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
   770 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
   779 		if (tile == end_tile) break;
   779 		if (tile == end_tile) break;
   780 
   780 
   781 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   781 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   782 		signal_ctr++;
   782 		signal_ctr++;
   783 
   783 
   784 		// toggle railbit for the non-diagonal tracks (|, -- tracks)
   784 		/* toggle railbit for the non-diagonal tracks (|, -- tracks) */
   785 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   785 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   786 	}
   786 	}
   787 
   787 
   788 	return error ? CMD_ERROR : total_cost;
   788 	return error ? CMD_ERROR : total_cost;
   789 }
   789 }
   867 
   867 
   868 	if (GetRailType(tile) == totype) return CMD_ERROR;
   868 	if (GetRailType(tile) == totype) return CMD_ERROR;
   869 
   869 
   870 	if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR;
   870 	if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR;
   871 
   871 
   872 	// 'hidden' elrails can't be downgraded to normal rail when elrails are disabled
   872 	/* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */
   873 	if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR;
   873 	if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR;
   874 
   874 
   875 	// change type.
   875 	/* change type. */
   876 	if (exec) {
   876 	if (exec) {
   877 		SetRailType(tile, totype);
   877 		SetRailType(tile, totype);
   878 		MarkTileDirtyByTile(tile);
   878 		MarkTileDirtyByTile(tile);
   879 
   879 
   880 		// notify YAPF about the track layout change
   880 		/* notify YAPF about the track layout change */
   881 		TrackBits tracks = GetTrackBits(tile);
   881 		TrackBits tracks = GetTrackBits(tile);
   882 		while (tracks != TRACK_BIT_NONE) {
   882 		while (tracks != TRACK_BIT_NONE) {
   883 			YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
   883 			YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
   884 		}
   884 		}
   885 
   885 
   921 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   921 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   922 
   922 
   923 	if (!ValParamRailtype(p2)) return CMD_ERROR;
   923 	if (!ValParamRailtype(p2)) return CMD_ERROR;
   924 	if (p1 >= MapSize()) return CMD_ERROR;
   924 	if (p1 >= MapSize()) return CMD_ERROR;
   925 
   925 
   926 	// make sure sx,sy are smaller than ex,ey
   926 	/* make sure sx,sy are smaller than ex,ey */
   927 	ex = TileX(tile);
   927 	ex = TileX(tile);
   928 	ey = TileY(tile);
   928 	ey = TileY(tile);
   929 	sx = TileX(p1);
   929 	sx = TileX(p1);
   930 	sy = TileY(p1);
   930 	sy = TileY(p1);
   931 	if (ex < sx) Swap(ex, sx);
   931 	if (ex < sx) Swap(ex, sx);
  1186 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
  1186 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
  1187 	SpriteID image;
  1187 	SpriteID image;
  1188 	SpriteID pal = PAL_NONE;
  1188 	SpriteID pal = PAL_NONE;
  1189 	bool junction = false;
  1189 	bool junction = false;
  1190 
  1190 
  1191 	// Select the sprite to use.
  1191 	/* Select the sprite to use. */
  1192 	(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1192 	(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1193 	(image++,                           track == TRACK_BIT_X) ||
  1193 	(image++,                           track == TRACK_BIT_X) ||
  1194 	(image++,                           track == TRACK_BIT_UPPER) ||
  1194 	(image++,                           track == TRACK_BIT_UPPER) ||
  1195 	(image++,                           track == TRACK_BIT_LOWER) ||
  1195 	(image++,                           track == TRACK_BIT_LOWER) ||
  1196 	(image++,                           track == TRACK_BIT_RIGHT) ||
  1196 	(image++,                           track == TRACK_BIT_RIGHT) ||
  1210 	if (ti->tileh != SLOPE_FLAT) {
  1210 	if (ti->tileh != SLOPE_FLAT) {
  1211 		uint foundation = GetRailFoundation(ti->tileh, track);
  1211 		uint foundation = GetRailFoundation(ti->tileh, track);
  1212 
  1212 
  1213 		if (foundation != 0) DrawFoundation(ti, foundation);
  1213 		if (foundation != 0) DrawFoundation(ti, foundation);
  1214 
  1214 
  1215 		// DrawFoundation() modifies ti.
  1215 		/* DrawFoundation() modifies it.
  1216 		// Default sloped sprites..
  1216 		 * Default sloped sprites.. */
  1217 		if (ti->tileh != SLOPE_FLAT)
  1217 		if (ti->tileh != SLOPE_FLAT)
  1218 			image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1218 			image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1219 	}
  1219 	}
  1220 
  1220 
  1221 	switch (GetRailGroundType(ti->tile)) {
  1221 	switch (GetRailGroundType(ti->tile)) {
  1224 		default: break;
  1224 		default: break;
  1225 	}
  1225 	}
  1226 
  1226 
  1227 	DrawGroundSprite(image, pal);
  1227 	DrawGroundSprite(image, pal);
  1228 
  1228 
  1229 	// Draw track pieces individually for junction tiles
  1229 	/* Draw track pieces individually for junction tiles */
  1230 	if (junction) {
  1230 	if (junction) {
  1231 		if (track & TRACK_BIT_X)     DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE);
  1231 		if (track & TRACK_BIT_X)     DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE);
  1232 		if (track & TRACK_BIT_Y)     DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
  1232 		if (track & TRACK_BIT_Y)     DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
  1233 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1233 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1234 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1234 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1286 
  1286 
  1287 		if (_display_opt & DO_FULL_DETAIL) DrawTrackDetails(ti);
  1287 		if (_display_opt & DO_FULL_DETAIL) DrawTrackDetails(ti);
  1288 
  1288 
  1289 		if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
  1289 		if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
  1290 	} else {
  1290 	} else {
  1291 		// draw depot/waypoint
  1291 		/* draw depot/waypoint */
  1292 		const DrawTileSprites* dts;
  1292 		const DrawTileSprites* dts;
  1293 		const DrawTileSeqStruct* dtss;
  1293 		const DrawTileSeqStruct* dtss;
  1294 		uint32 relocation;
  1294 		uint32 relocation;
  1295 
  1295 
  1296 		if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
  1296 		if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
  1301 			relocation = rti->total_offset;
  1301 			relocation = rti->total_offset;
  1302 
  1302 
  1303 			image = dts->ground_sprite;
  1303 			image = dts->ground_sprite;
  1304 			if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
  1304 			if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
  1305 
  1305 
  1306 			// adjust ground tile for desert
  1306 			/* adjust ground tile for desert
  1307 			// don't adjust for snow, because snow in depots looks weird
  1307 			 * don't adjust for snow, because snow in depots looks weird */
  1308 			if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) {
  1308 			if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) {
  1309 				if (image != SPR_FLAT_GRASS_TILE) {
  1309 				if (image != SPR_FLAT_GRASS_TILE) {
  1310 					image += rti->snow_offset; // tile with tracks
  1310 					image += rti->snow_offset; // tile with tracks
  1311 				} else {
  1311 				} else {
  1312 					image = SPR_FLAT_SNOWY_TILE; // flat ground
  1312 					image = SPR_FLAT_SNOWY_TILE; // flat ground
  1313 				}
  1313 				}
  1314 			}
  1314 			}
  1315 		} else {
  1315 		} else {
  1316 			// look for customization
  1316 			/* look for customization */
  1317 			byte stat_id = GetWaypointByTile(ti->tile)->stat_id;
  1317 			byte stat_id = GetWaypointByTile(ti->tile)->stat_id;
  1318 			const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, stat_id);
  1318 			const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, stat_id);
  1319 
  1319 
  1320 			if (statspec != NULL) {
  1320 			if (statspec != NULL) {
  1321 				// emulate station tile - open with building
  1321 				/* emulate station tile - open with building */
  1322 				const Station* st = ComposeWaypointStation(ti->tile);
  1322 				const Station* st = ComposeWaypointStation(ti->tile);
  1323 				uint gfx = 2;
  1323 				uint gfx = 2;
  1324 
  1324 
  1325 				if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) {
  1325 				if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) {
  1326 					uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  1326 					uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  1346 				} else {
  1346 				} else {
  1347 					goto default_waypoint;
  1347 					goto default_waypoint;
  1348 				}
  1348 				}
  1349 			} else {
  1349 			} else {
  1350 default_waypoint:
  1350 default_waypoint:
  1351 				// There is no custom layout, fall back to the default graphics
  1351 				/* There is no custom layout, fall back to the default graphics */
  1352 				dts = &_waypoint_gfx_table[GetWaypointAxis(ti->tile)];
  1352 				dts = &_waypoint_gfx_table[GetWaypointAxis(ti->tile)];
  1353 				relocation = 0;
  1353 				relocation = 0;
  1354 				image = dts->ground_sprite + rti->total_offset;
  1354 				image = dts->ground_sprite + rti->total_offset;
  1355 				if (IsSnowRailGround(ti->tile)) image += rti->snow_offset;
  1355 				if (IsSnowRailGround(ti->tile)) image += rti->snow_offset;
  1356 			}
  1356 			}
  1433 	int cur;
  1433 	int cur;
  1434 	int cur_stack;
  1434 	int cur_stack;
  1435 	bool stop;
  1435 	bool stop;
  1436 	bool has_presignal;
  1436 	bool has_presignal;
  1437 
  1437 
  1438 	// presignal info
  1438 	/* presignal info */
  1439 	int presignal_exits;
  1439 	int presignal_exits;
  1440 	int presignal_exits_free;
  1440 	int presignal_exits_free;
  1441 
  1441 
  1442 	// these are used to keep track of the signals that change.
  1442 	/* these are used to keep track of the signals that change. */
  1443 	TrackdirByte bit[NUM_SSD_ENTRY];
  1443 	TrackdirByte bit[NUM_SSD_ENTRY];
  1444 	TileIndex tile[NUM_SSD_ENTRY];
  1444 	TileIndex tile[NUM_SSD_ENTRY];
  1445 
  1445 
  1446 	// these are used to keep track of the stack that modifies presignals recursively
  1446 	/* these are used to keep track of the stack that modifies presignals recursively */
  1447 	TileIndex next_tile[NUM_SSD_STACK];
  1447 	TileIndex next_tile[NUM_SSD_STACK];
  1448 	DiagDirectionByte next_dir[NUM_SSD_STACK];
  1448 	DiagDirectionByte next_dir[NUM_SSD_STACK];
  1449 
  1449 
  1450 };
  1450 };
  1451 
  1451 
  1453 {
  1453 {
  1454 	SetSignalsData* ssd = (SetSignalsData*)data;
  1454 	SetSignalsData* ssd = (SetSignalsData*)data;
  1455 
  1455 
  1456 	if (!IsTileType(tile, MP_RAILWAY)) return false;
  1456 	if (!IsTileType(tile, MP_RAILWAY)) return false;
  1457 
  1457 
  1458 	// the tile has signals?
  1458 	/* the tile has signals? */
  1459 	if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) {
  1459 	if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) {
  1460 		if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
  1460 		if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
  1461 			// yes, add the signal to the list of signals
  1461 			/* yes, add the signal to the list of signals */
  1462 			if (ssd->cur != NUM_SSD_ENTRY) {
  1462 			if (ssd->cur != NUM_SSD_ENTRY) {
  1463 				ssd->tile[ssd->cur] = tile; // remember the tile index
  1463 				ssd->tile[ssd->cur] = tile; // remember the tile index
  1464 				ssd->bit[ssd->cur] = trackdir; // and the controlling bit number
  1464 				ssd->bit[ssd->cur] = trackdir; // and the controlling bit number
  1465 				ssd->cur++;
  1465 				ssd->cur++;
  1466 			}
  1466 			}
  1467 
  1467 
  1468 			// remember if this block has a presignal.
  1468 			/* remember if this block has a presignal. */
  1469 			ssd->has_presignal |= IsPresignalEntry(tile);
  1469 			ssd->has_presignal |= IsPresignalEntry(tile);
  1470 		}
  1470 		}
  1471 
  1471 
  1472 		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) {
  1472 		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) {
  1473 			// this is an exit signal that points out from the segment
  1473 			/* this is an exit signal that points out from the segment */
  1474 			ssd->presignal_exits++;
  1474 			ssd->presignal_exits++;
  1475 			if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED)
  1475 			if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED)
  1476 				ssd->presignal_exits_free++;
  1476 				ssd->presignal_exits_free++;
  1477 		}
  1477 		}
  1478 
  1478 
  1526 			direction = GetBridgeRampDirection(tile);
  1526 			direction = GetBridgeRampDirection(tile);
  1527 		}
  1527 		}
  1528 
  1528 
  1529 		dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible)
  1529 		dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible)
  1530 
  1530 
  1531 		// check for a vehicle with that trackdir on the start tile of the tunnel
  1531 		/* check for a vehicle with that trackdir on the start tile of the tunnel */
  1532 		if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true;
  1532 		if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true;
  1533 
  1533 
  1534 		// check for a vehicle with that trackdir on the end tile of the tunnel
  1534 		/* check for a vehicle with that trackdir on the end tile of the tunnel */
  1535 		if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
  1535 		if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
  1536 
  1536 
  1537 		// now check all tiles from start to end for a warping vehicle
  1537 		/* now check all tiles from start to end for a warping vehicle
  1538 		// NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile?
  1538 		 * NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile? */
  1539 		dest.track = 0x40;   //Vehicle inside a tunnel or on a bridge
  1539 		dest.track = 0x40;   //Vehicle inside a tunnel or on a bridge
  1540 		for (; tile != end; tile += TileOffsByDiagDir(direction)) {
  1540 		for (; tile != end; tile += TileOffsByDiagDir(direction)) {
  1541 			if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL)
  1541 			if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL)
  1542 				return true;
  1542 				return true;
  1543 		}
  1543 		}
  1544 
  1544 
  1545 		// no vehicle found
  1545 		/* no vehicle found */
  1546 		return false;
  1546 		return false;
  1547 	}
  1547 	}
  1548 
  1548 
  1549 	return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL;
  1549 	return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL;
  1550 }
  1550 }
  1595 
  1595 
  1596 static void ChangeSignalStates(SetSignalsData *ssd)
  1596 static void ChangeSignalStates(SetSignalsData *ssd)
  1597 {
  1597 {
  1598 	int i;
  1598 	int i;
  1599 
  1599 
  1600 	// thinking about presignals...
  1600 	/* thinking about presignals...
  1601 	// the presignal is green if,
  1601 	 * the presignal is green if,
  1602 	//   if no train is in the segment AND
  1602 	 *   if no train is in the segment AND
  1603 	//   there is at least one green exit signal OR
  1603 	 *   there is at least one green exit signal OR
  1604 	//   there are no exit signals in the segment
  1604 	 *   there are no exit signals in the segment */
  1605 
  1605 
  1606 	// then mark the signals in the segment accordingly
  1606 	/* then mark the signals in the segment accordingly */
  1607 	for (i = 0; i != ssd->cur; i++) {
  1607 	for (i = 0; i != ssd->cur; i++) {
  1608 		TileIndex tile = ssd->tile[i];
  1608 		TileIndex tile = ssd->tile[i];
  1609 		byte bit = SignalAgainstTrackdir(ssd->bit[i]);
  1609 		byte bit = SignalAgainstTrackdir(ssd->bit[i]);
  1610 		uint16 m2 = _m[tile].m2;
  1610 		uint16 m2 = _m[tile].m2;
  1611 
  1611 
  1612 		// presignals don't turn green if there is at least one presignal exit and none are free
  1612 		/* presignals don't turn green if there is at least one presignal exit and none are free */
  1613 		if (IsPresignalEntry(tile)) {
  1613 		if (IsPresignalEntry(tile)) {
  1614 			int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free;
  1614 			int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free;
  1615 
  1615 
  1616 			// subtract for dual combo signals so they don't count themselves
  1616 			/* subtract for dual combo signals so they don't count themselves */
  1617 			if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
  1617 			if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
  1618 				ex--;
  1618 				ex--;
  1619 				if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--;
  1619 				if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--;
  1620 			}
  1620 			}
  1621 
  1621 
  1622 			// if we have exits and none are free, make red.
  1622 			/* if we have exits and none are free, make red. */
  1623 			if (ex && !exfree) goto make_red;
  1623 			if (ex && !exfree) goto make_red;
  1624 		}
  1624 		}
  1625 
  1625 
  1626 		// check if the signal is unaffected.
  1626 		/* check if the signal is unaffected. */
  1627 		if (ssd->stop) {
  1627 		if (ssd->stop) {
  1628 make_red:
  1628 make_red:
  1629 			// turn red
  1629 			/* turn red */
  1630 			if ((bit & m2) == 0) continue;
  1630 			if ((bit & m2) == 0) continue;
  1631 		} else {
  1631 		} else {
  1632 			// turn green
  1632 			/* turn green */
  1633 			if ((bit & m2) != 0) continue;
  1633 			if ((bit & m2) != 0) continue;
  1634 		}
  1634 		}
  1635 
  1635 
  1636 		/* Update signals on the other side of this exit-combo signal; it changed. */
  1636 		/* Update signals on the other side of this exit-combo signal; it changed. */
  1637 		if (IsPresignalExit(tile)) {
  1637 		if (IsPresignalExit(tile)) {
  1642 			} else {
  1642 			} else {
  1643 				DEBUG(misc, 0, "NUM_SSD_STACK too small"); /// @todo WTF is this???
  1643 				DEBUG(misc, 0, "NUM_SSD_STACK too small"); /// @todo WTF is this???
  1644 			}
  1644 			}
  1645 		}
  1645 		}
  1646 
  1646 
  1647 		// it changed, so toggle it
  1647 		/* it changed, so toggle it */
  1648 		_m[tile].m2 = m2 ^ bit;
  1648 		_m[tile].m2 = m2 ^ bit;
  1649 		MarkTileDirtyByTile(tile);
  1649 		MarkTileDirtyByTile(tile);
  1650 	}
  1650 	}
  1651 }
  1651 }
  1652 
  1652 
  1657 	int result = -1;
  1657 	int result = -1;
  1658 
  1658 
  1659 	ssd.cur_stack = 0;
  1659 	ssd.cur_stack = 0;
  1660 
  1660 
  1661 	for (;;) {
  1661 	for (;;) {
  1662 		// go through one segment and update all signals pointing into that segment.
  1662 		/* go through one segment and update all signals pointing into that segment. */
  1663 		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
  1663 		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
  1664 		ssd.has_presignal = false;
  1664 		ssd.has_presignal = false;
  1665 
  1665 
  1666 		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
  1666 		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
  1667 		ChangeSignalStates(&ssd);
  1667 		ChangeSignalStates(&ssd);
  1668 
  1668 
  1669 		// remember the result only for the first iteration.
  1669 		/* remember the result only for the first iteration. */
  1670 		if (result < 0) {
  1670 		if (result < 0) {
  1671 			// stay in depot while segment is occupied or while all presignal exits are blocked
  1671 			/* stay in depot while segment is occupied or while all presignal exits are blocked */
  1672 			result = ssd.stop || (ssd.presignal_exits > 0 && ssd.presignal_exits_free == 0);
  1672 			result = ssd.stop || (ssd.presignal_exits > 0 && ssd.presignal_exits_free == 0);
  1673 		}
  1673 		}
  1674 
  1674 
  1675 		// if any exit signals were changed, we need to keep going to modify the stuff behind those.
  1675 		/* if any exit signals were changed, we need to keep going to modify the stuff behind those. */
  1676 		if (ssd.cur_stack == 0) break;
  1676 		if (ssd.cur_stack == 0) break;
  1677 
  1677 
  1678 		// one or more exit signals were changed, so we need to update another segment too.
  1678 		/* one or more exit signals were changed, so we need to update another segment too. */
  1679 		tile = ssd.next_tile[--ssd.cur_stack];
  1679 		tile = ssd.next_tile[--ssd.cur_stack];
  1680 		direction = ssd.next_dir[ssd.cur_stack];
  1680 		direction = ssd.next_dir[ssd.cur_stack];
  1681 	}
  1681 	}
  1682 
  1682 
  1683 	return result != 0;
  1683 	return result != 0;
  1766 
  1766 
  1767 	if (!IsPlainRailTile(tile)) return;
  1767 	if (!IsPlainRailTile(tile)) return;
  1768 
  1768 
  1769 	new_ground = RAIL_GROUND_GRASS;
  1769 	new_ground = RAIL_GROUND_GRASS;
  1770 
  1770 
  1771 	if (old_ground != RAIL_GROUND_BARREN) { /* wait until bottom is green */
  1771 	if (old_ground != RAIL_GROUND_BARREN) { // wait until bottom is green
  1772 		/* determine direction of fence */
  1772 		/* determine direction of fence */
  1773 		TrackBits rail = GetTrackBits(tile);
  1773 		TrackBits rail = GetTrackBits(tile);
  1774 
  1774 
  1775 		switch (rail) {
  1775 		switch (rail) {
  1776 			case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
  1776 			case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
  1960 	byte fract_coord;
  1960 	byte fract_coord;
  1961 	byte fract_coord_leave;
  1961 	byte fract_coord_leave;
  1962 	DiagDirection dir;
  1962 	DiagDirection dir;
  1963 	int length;
  1963 	int length;
  1964 
  1964 
  1965 	// this routine applies only to trains in depot tiles
  1965 	/* this routine applies only to trains in depot tiles */
  1966 	if (v->type != VEH_TRAIN || !IsTileDepotType(tile, TRANSPORT_RAIL)) return VETSB_CONTINUE;
  1966 	if (v->type != VEH_TRAIN || !IsTileDepotType(tile, TRANSPORT_RAIL)) return VETSB_CONTINUE;
  1967 
  1967 
  1968 	/* depot direction */
  1968 	/* depot direction */
  1969 	dir = GetRailDepotDirection(tile);
  1969 	dir = GetRailDepotDirection(tile);
  1970 
  1970