Changeset - r3792:deb3c0493c60
[Not reviewed]
master
0 15 0
rubidium - 18 years ago 2006-05-09 08:17:33
rubidium@openttd.org
(svn r4788) - Codechange: RAILTYPE_{NORMAL,ELECTRIC,...} and RAIL_TYPE_{NORMAL,SIGNAL,...} have nearly the same name, rename RAIL_TYPE_* to RAIL_TILE_* of extra clarity
15 files changed with 55 insertions and 55 deletions:
0 comments (0 inline, 0 general)
ai/default/default.c
Show inline comments
 
@@ -2139,97 +2139,97 @@ static void AiBuildRailConstruct(Player 
 
		for (i = 0; i != 2; i++) {
 
			AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0);
 
		}
 
	}
 
}
 

	
 
static bool AiRemoveTileAndGoForward(Player *p)
 
{
 
	byte b;
 
	int bit;
 
	const byte *ptr;
 
	TileIndex tile = p->ai.cur_tile_a;
 
	TileIndex tilenew;
 

	
 
	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
		if (IsTunnel(tile)) {
 
			// Clear the tunnel and continue at the other side of it.
 
			if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
 
				return false;
 
			p->ai.cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDir(p->ai.cur_dir_a));
 
			return true;
 
		}
 

	
 
		if (IsBridgeRamp(tile)) {
 
			// Check if the bridge points in the right direction.
 
			// This is not really needed the first place AiRemoveTileAndGoForward is called.
 
			if (DiagDirToAxis(GetBridgeRampDirection(tile)) != (p->ai.cur_dir_a & 1U)) return false;
 

	
 
			tile = GetOtherBridgeEnd(tile);
 

	
 
			tilenew = TILE_MASK(tile - TileOffsByDir(p->ai.cur_dir_a));
 
			// And clear the bridge.
 
			if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
 
				return false;
 
			p->ai.cur_tile_a = tilenew;
 
			return true;
 
		}
 
	}
 

	
 
	// Find the railtype at the position. Quit if no rail there.
 
	b = GetRailTrackStatus(tile) & _dir_table_3[p->ai.cur_dir_a];
 
	if (b == 0) return false;
 

	
 
	// Convert into a bit position that CMD_REMOVE_SINGLE_RAIL expects.
 
	bit = FindFirstBit(b);
 

	
 
	// Then remove and signals if there are any.
 
	if (IsTileType(tile, MP_RAILWAY) &&
 
			GetRailTileType(tile) == RAIL_TYPE_SIGNALS) {
 
			GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
 
		DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_SIGNALS);
 
	}
 

	
 
	// And also remove the rail.
 
	if (CmdFailed(DoCommand(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL)))
 
		return false;
 

	
 
	// Find the direction at the other edge of the rail.
 
	ptr = _ai_table_15[p->ai.cur_dir_a ^ 2];
 
	while (ptr[0] != bit) ptr += 2;
 
	p->ai.cur_dir_a = ptr[1] ^ 2;
 

	
 
	// And then also switch tile.
 
	p->ai.cur_tile_a = TILE_MASK(p->ai.cur_tile_a - TileOffsByDir(p->ai.cur_dir_a));
 

	
 
	return true;
 
}
 

	
 

	
 
static void AiBuildRailDestruct(Player *p)
 
{
 
	// Decrease timeout.
 
	if (!--p->ai.state_counter) {
 
		p->ai.state_mode = 2;
 
		p->ai.state_counter = 0;
 
	}
 

	
 
	// Don't do anything if the destination is already reached.
 
	if (p->ai.cur_tile_a == p->ai.start_tile_a) return;
 

	
 
	AiRemoveTileAndGoForward(p);
 
}
 

	
 

	
 
static void AiBuildRail(Player *p)
 
{
 
	if (p->ai.state_mode < 1) {
 
		// Construct mode, build new rail.
 
		AiBuildRailConstruct(p);
 
	} else if (p->ai.state_mode == 1) {
 
		// Destruct mode, destroy the rail currently built.
 
		AiBuildRailDestruct(p);
 
	} else if (p->ai.state_mode == 2) {
 
		uint i;
 

	
 
		// Terraform some and then try building again.
 
		for (i = 0; i != 4; i++)
 
			AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0);
elrail.c
Show inline comments
 
@@ -31,99 +31,99 @@ other tile.
 

	
 
Now on each edge there are two PCPs: One from each adjacent tile. Both PCPs
 
are merged using an OR operation (i. e. if one tile needs a PCP at the postion
 
in question, both tiles get it).
 

	
 
<h4>Position Points</h4>
 
A Pylon Position Point (PPP) is a position where a pylon is located on the
 
ground.  Each PCP owns 8 in (45 degree steps) PPPs that are located around
 
it. PPPs are represented using the Direction enum. Each track bit has PPPs
 
that are impossible (because the pylon would be situated on the track) and
 
some that are preferred (because the pylon would be rectangular to the track).
 

	
 
<img src="../../elrail_tile.png">
 
<img src="../../elrail_track.png">
 

	
 
  */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "station_map.h"
 
#include "tile.h"
 
#include "viewport.h"
 
#include "functions.h" /* We should REALLY get rid of this goddamn file, as it is butt-ugly */
 
#include "variables.h" /* ... same here */
 
#include "rail.h"
 
#include "debug.h"
 
#include "tunnel_map.h"
 
#include "road_map.h"
 
#include "bridge_map.h"
 
#include "bridge.h"
 
#include "rail_map.h"
 
#include "table/sprites.h"
 
#include "table/elrail_data.h"
 

	
 
static inline TLG GetTLG(TileIndex t)
 
{
 
	return (HASBIT(TileX(t), 0) << 1) + HASBIT(TileY(t), 0);
 
}
 

	
 
/** Finds which Rail Bits are present on a given tile. For bridge tiles,
 
  * returns track bits under the bridge
 
  */
 
static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
 
{
 
	switch (GetTileType(t)) {
 
		case MP_RAILWAY:
 
			if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
 
			switch (GetRailTileType(t)) {
 
				case RAIL_TYPE_NORMAL: case RAIL_TYPE_SIGNALS:
 
				case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
 
					return GetTrackBits(t);
 
				case RAIL_TYPE_DEPOT_WAYPOINT:
 
				case RAIL_TILE_DEPOT_WAYPOINT:
 
					if (GetRailTileSubtype(t) == RAIL_SUBTYPE_WAYPOINT) return GetRailWaypointBits(t);
 
				default:
 
					return 0;
 
			}
 
			break;
 
		case MP_TUNNELBRIDGE:
 
			if (IsTunnel(t)) {
 
				if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
 
				if (override != NULL) *override = 1 << GetTunnelDirection(t);
 
				return DiagDirToAxis(GetTunnelDirection(t)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y;
 
			} else {
 
				if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
 
				if (IsBridgeMiddle(t)) {
 
					if (IsTransportUnderBridge(t) &&
 
						GetTransportTypeUnderBridge(t) == TRANSPORT_RAIL) {
 
						return GetRailBitsUnderBridge(t);
 
					} else {
 
						return 0;
 
					}
 
				} else {
 
					if (override != NULL && DistanceMax(t, GetOtherBridgeEnd(t)) > 1) *override = 1 << GetBridgeRampDirection(t);
 

	
 
					return DiagDirToAxis(GetBridgeRampDirection(t)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y;
 
				}
 
			}
 
		case MP_STREET:
 
			if (GetRoadType(t) != ROAD_CROSSING) return 0;
 
			if (GetRailTypeCrossing(t) != RAILTYPE_ELECTRIC) return 0;
 
			return GetCrossingRailBits(t);
 
		case MP_STATION:
 
			if (!IsRailwayStation(t)) return 0;
 
			if (GetRailType(t) != RAILTYPE_ELECTRIC) return 0;
 
			if (!IsStationTileElectrifiable(t)) return 0;
 
			return TrackToTrackBits(GetRailStationTrack(t));
 
		default:
 
			return 0;
 
	}
 
}
 

	
 
/** Corrects the tileh for certain tile types. Returns an effective tileh for the track on the tile.
 
  * @param tile The tile to analyse
 
  * @param *tileh the tileh
 
  */
 
static void AdjustTileh(TileIndex tile, Slope* tileh)
 
{
 
	if (IsTunnelTile(tile)) *tileh = SLOPE_FLAT;
 
	if (IsBridgeTile(tile) && IsBridgeRamp(tile)) {
 
		if (*tileh != SLOPE_FLAT) {
 
@@ -301,66 +301,66 @@ static void DrawCatenaryOnBridge(const T
 
	TileIndex end = GetSouthernBridgeEnd(ti->tile);
 
	TileIndex start = GetOtherBridgeEnd(end);
 

	
 
	uint length = GetBridgeLength(start, end);
 
	uint num = DistanceMax(ti->tile, start);
 

	
 
	const SortableSpriteStruct *sss;
 
	Axis axis = GetBridgeAxis(ti->tile);
 
	TLG tlg = GetTLG(ti->tile);
 

	
 
	CatenarySprite offset = axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH;
 

	
 
	if ((length % 2) && num == length) {
 
		/* Draw the "short" wire on the southern end of the bridge
 
		 * only needed if the length of the bridge is odd */
 
		sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
 
	} else {
 
		/* Draw "long" wires on all other tiles of the bridge (one pylon every two tiles) */
 
		sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
 
	}
 

	
 
	AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
 
			sss->x_size, sss->y_size, sss->z_size, GetBridgeHeight(ti->tile) + sss->z_offset + 8);
 

	
 
	/* Finished with wires, draw pylons */
 
	/* every other tile needs a pylon on the northern end */
 
	if (num % 2) {
 
		if (axis == AXIS_X) {
 
			AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
 
		} else {
 
			AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
 
		}
 
	}
 

	
 
	/* need a pylon on the southern end of the bridge */
 
	if (DistanceMax(ti->tile, start) == length) {
 
		if (axis == AXIS_X) {
 
			AddSortableSpriteToDraw( pylons_bridge[0 + HASBIT(tlg, 0)], ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
 
		} else {
 
			AddSortableSpriteToDraw( pylons_bridge[2 + HASBIT(tlg, 1)], ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, GetBridgeHeight(ti->tile) + TILE_HEIGHT);
 
		}
 
	}
 
}
 

	
 
void DrawCatenary(const TileInfo *ti)
 
{
 
	switch (GetTileType(ti->tile)) {
 
		case MP_RAILWAY:
 
			if (GetRailTileType(ti->tile) == RAIL_TYPE_DEPOT_WAYPOINT && GetRailTileSubtype(ti->tile) == RAIL_SUBTYPE_DEPOT) {
 
			if (GetRailTileType(ti->tile) == RAIL_TILE_DEPOT_WAYPOINT && GetRailTileSubtype(ti->tile) == RAIL_SUBTYPE_DEPOT) {
 
				const SortableSpriteStruct *sss = &CatenarySpriteData[WIRE_DEPOT_SW + ReverseDiagDir(GetRailDepotDirection(ti->tile))];
 
				AddSortableSpriteToDraw( sss->image, ti->x + sss->x_offset, ti->y + sss->y_offset,
 
					sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x, ti->y) + sss->z_offset);
 
				return;
 
			}
 
			/* Fall through */
 
		case MP_TUNNELBRIDGE:
 
			if (IsBridgeTile(ti->tile) && IsBridgeMiddle(ti->tile) && GetRailTypeOnBridge(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenaryOnBridge(ti);
 
			/* Fall further */
 
		case MP_STREET: case MP_STATION:
 
			DrawCatenaryRailway(ti);
 
			break;
 
		default:
 
			break;
 
	}
 
}
 

	
newgrf_station.c
Show inline comments
 
@@ -208,97 +208,97 @@ uint32 GetPlatformInfo(Axis axis, byte t
 
	/* Limit our sizes to 4 bits */
 
	platforms = min(15, platforms);
 
	length    = min(15, length);
 
	x = min(15, x);
 
	y = min(15, y);
 
	if (centred) {
 
		x -= platforms / 2;
 
		y -= length / 2;
 
		SB(retval,  0, 4, y & 0xF);
 
		SB(retval,  4, 4, x & 0xF);
 
	} else {
 
		SB(retval,  0, 4, y);
 
		SB(retval,  4, 4, length - y - 1);
 
		SB(retval,  8, 4, x);
 
		SB(retval, 12, 4, platforms - x - 1);
 
	}
 
	SB(retval, 16, 4, length);
 
	SB(retval, 20, 4, platforms);
 
	SB(retval, 24, 4, tile);
 

	
 
	return retval;
 
}
 

	
 

	
 
/* Find the end of a railway station, from the tile, in the direction of delta.
 
 * If check_type is set, we stop if the custom station type changes.
 
 * If check_axis is set, we stop if the station direction changes.
 
 */
 
static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
 
{
 
	bool waypoint;
 
	byte orig_type = 0;
 
	Axis orig_axis = AXIS_X;
 

	
 
	waypoint = IsTileType(tile, MP_RAILWAY);
 

	
 
	if (waypoint) {
 
		if (check_axis) orig_axis = GetWaypointAxis(tile);
 
	} else {
 
		if (check_type) orig_type = GetCustomStationSpecIndex(tile);
 
		if (check_axis) orig_axis = GetRailStationAxis(tile);
 
	}
 

	
 
	while (true) {
 
		TileIndex new_tile = TILE_ADD(tile, delta);
 

	
 
		if (waypoint) {
 
			if (!IsTileType(new_tile, MP_RAILWAY)) break;
 
			if (GetRailTileType(new_tile) != RAIL_TYPE_DEPOT_WAYPOINT) break;
 
			if (GetRailTileType(new_tile) != RAIL_TILE_DEPOT_WAYPOINT) break;
 
			if (GetRailTileSubtype(new_tile) != RAIL_SUBTYPE_WAYPOINT) break;
 
			if (check_axis && GetWaypointAxis(new_tile) != orig_axis) break;
 
		} else {
 
			if (!IsRailwayStationTile(new_tile)) break;
 
			if (check_type && GetCustomStationSpecIndex(new_tile) != orig_type) break;
 
			if (check_axis && GetRailStationAxis(new_tile) != orig_axis) break;
 
		}
 

	
 
		tile = new_tile;
 
	}
 
	return tile;
 
}
 

	
 

	
 
static uint32 GetPlatformInfoHelper(TileIndex tile, bool check_type, bool check_axis, bool centred)
 
{
 
	int tx = TileX(tile);
 
	int ty = TileY(tile);
 
	int sx = TileX(FindRailStationEnd(tile, TileDiffXY(-1,  0), check_type, check_axis));
 
	int sy = TileY(FindRailStationEnd(tile, TileDiffXY( 0, -1), check_type, check_axis));
 
	int ex = TileX(FindRailStationEnd(tile, TileDiffXY( 1,  0), check_type, check_axis)) + 1;
 
	int ey = TileY(FindRailStationEnd(tile, TileDiffXY( 0,  1), check_type, check_axis)) + 1;
 
	Axis axis = IsTileType(tile, MP_RAILWAY) ? GetWaypointAxis(tile) : GetRailStationAxis(tile);
 

	
 
	tx -= sx; ex -= sx;
 
	ty -= sy; ey -= sy;
 

	
 
	return GetPlatformInfo(axis, IsTileType(tile, MP_RAILWAY) ? 2 : GetStationGfx(tile), ex, ey, tx, ty, centred);
 
}
 

	
 

	
 
/* Station Resolver Functions */
 
static uint32 StationGetRandomBits(const ResolverObject *object)
 
{
 
	const Station *st = object->u.station.st;
 
	const TileIndex tile = object->u.station.tile;
 
	return (st == NULL ? 0 : st->random_bits) | (tile == INVALID_TILE ? 0 : GetStationTileRandomBits(tile) << 16);
 
}
 

	
 

	
 
static uint32 StationGetTriggers(const ResolverObject *object)
 
{
 
	const Station *st = object->u.station.st;
 
	return st == NULL ? 0 : st->waiting_triggers;
 
}
 

	
 

	
 
static void StationSetTriggers(const ResolverObject *object, int triggers)
npf.c
Show inline comments
 
@@ -580,97 +580,97 @@ static void NPFFollowTrack(AyStar* aysta
 
	/* check correct rail type (mono, maglev, etc) */
 
	if (type == TRANSPORT_RAIL) {
 
		RailType dst_type = GetTileRailType(dst_tile, src_trackdir);
 
		if (!HASBIT(aystar->user_data[NPF_RAILTYPES], dst_type))
 
			return;
 
	}
 

	
 
	/* Check the owner of the tile */
 
	if (!VehicleMayEnterTile(aystar->user_data[NPF_OWNER], dst_tile, TrackdirToExitdir(src_trackdir))) {
 
		return;
 
	}
 

	
 
	/* Determine available tracks */
 
	if (type != TRANSPORT_WATER && (IsRoadStopTile(dst_tile) || IsTileDepotType(dst_tile, type))){
 
		/* Road stations and road and train depots return 0 on GTTS, so we have to do this by hand... */
 
		DiagDirection exitdir;
 
		if (IsRoadStopTile(dst_tile)) {
 
			exitdir = GetRoadStopDir(dst_tile);
 
		} else { /* Road or train depot */
 
			exitdir = GetDepotDirection(dst_tile, type);
 
		}
 
		/* Find the trackdirs that are available for a depot or station with this
 
		 * orientation. They are only "inwards", since we are reaching this tile
 
		 * from some other tile. This prevents vehicles driving into depots from
 
		 * the back */
 
		ts = TrackdirToTrackdirBits(DiagdirToDiagTrackdir(ReverseDiagDir(exitdir)));
 
	} else {
 
		ts = GetTileTrackStatus(dst_tile, type);
 
	}
 
	trackdirbits = ts & TRACKDIR_BIT_MASK; /* Filter out signal status and the unused bits */
 

	
 
	DEBUG(npf, 4)("Next node: (%d, %d) [%d], possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirbits);
 
	/* Select only trackdirs we can reach from our current trackdir */
 
	trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
 
	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */
 
		trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
 

	
 
	DEBUG(npf,6)("After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
 

	
 
	i = 0;
 
	/* Enumerate possible track */
 
	while (trackdirbits != 0) {
 
		Trackdir dst_trackdir;
 
		dst_trackdir =  FindFirstBit2x64(trackdirbits);
 
		trackdirbits = KillFirstBit2x64(trackdirbits);
 
		DEBUG(npf, 5)("Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits);
 

	
 
		/* Check for oneway signal against us */
 
		if (IsTileType(dst_tile, MP_RAILWAY) && GetRailTileType(dst_tile) == RAIL_TYPE_SIGNALS) {
 
		if (IsTileType(dst_tile, MP_RAILWAY) && GetRailTileType(dst_tile) == RAIL_TILE_SIGNALS) {
 
			if (HasSignalOnTrackdir(dst_tile, ReverseTrackdir(dst_trackdir)) && !HasSignalOnTrackdir(dst_tile, dst_trackdir))
 
				// if one way signal not pointing towards us, stop going in this direction.
 
				break;
 
		}
 
		{
 
			/* We've found ourselves a neighbour :-) */
 
			AyStarNode* neighbour = &aystar->neighbours[i];
 
			neighbour->tile = dst_tile;
 
			neighbour->direction = dst_trackdir;
 
			/* Save user data */
 
			neighbour->user_data[NPF_NODE_FLAGS] = current->path.node.user_data[NPF_NODE_FLAGS];
 
			NPFFillTrackdirChoice(neighbour, current);
 
		}
 
		i++;
 
	}
 
	aystar->num_neighbours = i;
 
}
 

	
 
/*
 
 * Plan a route to the specified target (which is checked by target_proc),
 
 * from start1 and if not NULL, from start2 as well. The type of transport we
 
 * are checking is in type. reverse_penalty is applied to all routes that
 
 * originate from the second start node.
 
 * When we are looking for one specific target (optionally multiple tiles), we
 
 * should use a good heuristic to perform aystar search. When we search for
 
 * multiple targets that are spread around, we should perform a breadth first
 
 * search by specifiying CalcZero as our heuristic.
 
 */
 
static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
 
{
 
	int r;
 
	NPFFoundTargetData result;
 

	
 
	/* Initialize procs */
 
	_npf_aystar.CalculateH = heuristic_proc;
 
	_npf_aystar.EndNodeCheck = target_proc;
 
	_npf_aystar.FoundEndNode = NPFSaveTargetData;
 
	_npf_aystar.GetNeighbours = NPFFollowTrack;
 
	if (type == TRANSPORT_RAIL)
 
		_npf_aystar.CalculateG = NPFRailPathCost;
 
	else if (type == TRANSPORT_ROAD)
 
		_npf_aystar.CalculateG = NPFRoadPathCost;
 
	else if (type == TRANSPORT_WATER)
 
		_npf_aystar.CalculateG = NPFWaterPathCost;
 
	else
 
		assert(0);
 

	
 
	/* Initialize Start Node(s) */
oldloader.c
Show inline comments
 
@@ -1478,97 +1478,97 @@ static const OldChunks main_chunk[] = {
 

	
 
	OCL_NULL( 1 ),               // Custom vehicle types yes/no, no longer used
 
	OCL_VAR (  OC_UINT8,    1, &_opt.snow_line ),
 

	
 
	OCL_NULL( 32 ),              // new_industry_randtable, no longer used (because of new design)
 
	OCL_NULL( 36 ),              // cargo-stuff, calculated in InitializeLandscapeVariables
 

	
 
	OCL_ASSERT( 0x77179 ),
 

	
 
	OCL_CHUNK( 1, LoadOldMapPart2 ),
 

	
 
	OCL_ASSERT( 0x97179 ),
 

	
 
	/* Below any (if available) extra chunks from TTDPatch can follow */
 

	
 
	OCL_END()
 
};
 

	
 
static bool LoadOldMain(LoadgameState *ls)
 
{
 
	int i;
 

	
 
	/* The first 49 is the name of the game + checksum, skip it */
 
	fseek(ls->file, HEADER_SIZE, SEEK_SET);
 

	
 
	DEBUG(oldloader, 4)("[OldLoader] Going to read main chunk..");
 
	/* Load the biggest chunk */
 
	if (!LoadChunk(ls, NULL, main_chunk)) {
 
		DEBUG(oldloader, 0)("[OldLoader] Loading failed!");
 
		return false;
 
	}
 
	DEBUG(oldloader, 4)("[OldLoader] Done. Converting stuff..");
 

	
 
	/* Fix some general stuff */
 
	_opt.landscape = _opt.landscape & 0xF;
 

	
 
	/* Remap some pointers */
 
	_cur_town_ctr      = REMAP_TOWN_IDX(_old_cur_town_ctr);
 

	
 
	/* _old_map3 is changed in _map3_lo and _map3_hi */
 
	for (i = 0; i < OLD_MAP_SIZE; i++) {
 
		_m[i].m3 = _old_map3[i * 2];
 
		_m[i].m4 = _old_map3[i * 2 + 1];
 
	}
 

	
 
	for (i = 0; i < OLD_MAP_SIZE; i ++) {
 
		if (IsTileType(i, MP_RAILWAY)) {
 
			/* We save presignals different from TTDPatch, convert them */
 
			if (GetRailTileType(i) == RAIL_TYPE_SIGNALS) {
 
			if (GetRailTileType(i) == RAIL_TILE_SIGNALS) {
 
				/* This byte is always zero in TTD for this type of tile */
 
				if (_m[i].m4) /* Convert the presignals to our own format */
 
					_m[i].m4 = (_m[i].m4 >> 1) & 7;
 
			}
 
			/* TTDPatch stores PBS things in L6 and all elsewhere; so we'll just
 
			* clear it for ourselves and let OTTD's rebuild PBS itself */
 
			_m[i].m4 &= 0xF; /* Only keep the lower four bits; upper four is PBS */
 
		}
 
	}
 

	
 
	/* Fix the game to be compatible with OpenTTD */
 
	FixOldTowns();
 
	FixOldStations();
 
	FixOldVehicles();
 

	
 
	AddTypeToEngines();
 

	
 
	/* We have a new difficulty setting */
 
	_opt.diff.town_council_tolerance = clamp(_opt.diff_level, 0, 2);
 

	
 
	DEBUG(oldloader, 4)("[OldLoader] Done!");
 
	DEBUG(oldloader, 1)("[OldLoader] TTD(Patch) savegame successfully converted");
 

	
 
	return true;
 
}
 

	
 
bool LoadOldSaveGame(const char *file)
 
{
 
	LoadgameState ls;
 

	
 
	DEBUG(oldloader, 4)("[OldLoader] Trying to load an TTD(Patch) savegame");
 

	
 
	InitLoading(&ls);
 

	
 
	/* Open file */
 
	ls.file = fopen(file, "rb");
 

	
 
	if (ls.file == NULL) {
 
		DEBUG(oldloader, 0)("[OldLoader] Could not open file %s", file);
 
		return false;
 
	}
 

	
 
	/* Load the main chunk */
 
	if (!LoadOldMain(&ls)) return false;
 

	
 
	fclose(ls.file);
 

	
 
	_pause = 2;
order_gui.c
Show inline comments
 
@@ -155,97 +155,97 @@ static void DrawOrdersWindow(Window *w)
 
					}
 

	
 
					if (order->flags & OF_FULL_LOAD) s++; /* service at */
 

	
 
					SetDParam(1, s);
 
					break;
 
				}
 

	
 
				case OT_GOTO_WAYPOINT:
 
					SetDParam(1, (order->flags & OF_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
 
					SetDParam(2, order->station);
 
					break;
 
			}
 

	
 
			color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
 
			SetDParam(0, i + 1);
 
			if (order->type != OT_DUMMY) {
 
				DrawString(2, y, str, color);
 
			} else {
 
				SetDParam(1, STR_INVALID_ORDER);
 
				SetDParam(2, order->station);
 
				DrawString(2, y, str, color);
 
			}
 
			y += 10;
 
		}
 

	
 
		i++;
 
		order = order->next;
 
	}
 

	
 
	if (i - w->vscroll.pos < w->vscroll.cap) {
 
		str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
 
		color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
 
		DrawString(2, y, str, color);
 
	}
 
}
 

	
 
static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
 
{
 
	Order order;
 
	order.next  = NULL;
 
	order.index = 0;
 

	
 
	// check depot first
 
	if (_patches.gotodepot) {
 
		switch (GetTileType(tile)) {
 
		case MP_RAILWAY:
 
			if (v->type == VEH_Train && IsTileOwner(tile, _local_player)) {
 
				if (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT &&
 
				if (GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT &&
 
						GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT) {
 
					order.type = OT_GOTO_DEPOT;
 
					order.flags = OF_PART_OF_ORDERS;
 
					order.station = GetDepotByTile(tile)->index;
 
					return order;
 
				}
 
			}
 
			break;
 

	
 
		case MP_STREET:
 
			if (GetRoadType(tile) == ROAD_DEPOT && v->type == VEH_Road && IsTileOwner(tile, _local_player)) {
 
				order.type = OT_GOTO_DEPOT;
 
				order.flags = OF_PART_OF_ORDERS;
 
				order.station = GetDepotByTile(tile)->index;
 
				return order;
 
			}
 
			break;
 

	
 
		case MP_STATION:
 
			if (v->type != VEH_Aircraft) break;
 
			if (IsHangar(tile) && IsTileOwner(tile, _local_player)) {
 
				order.type = OT_GOTO_DEPOT;
 
				order.flags = OF_PART_OF_ORDERS;
 
				order.station = GetStationIndex(tile);
 
				return order;
 
			}
 
			break;
 

	
 
		case MP_WATER:
 
			if (v->type != VEH_Ship) break;
 
			if (IsTileDepotType(tile, TRANSPORT_WATER) &&
 
					IsTileOwner(tile, _local_player)) {
 
				TileIndex tile2 = GetOtherShipDepotTile(tile);
 

	
 
				order.type = OT_GOTO_DEPOT;
 
				order.flags = OF_PART_OF_ORDERS;
 
				order.station = GetDepotByTile(tile < tile2 ? tile : tile2)->index;
 
				return order;
 
			}
 

	
 
			default:
 
				break;
 
		}
 
	}
 

	
 
	// check waypoint
 
	if (IsTileType(tile, MP_RAILWAY) &&
 
			v->type == VEH_Train &&
rail.h
Show inline comments
 
@@ -292,112 +292,112 @@ extern const TrackdirBits _exitdir_reach
 
/**
 
 * Returns all trackdirs that can be reached when entering a tile from a given
 
 * (diagonal) direction. This will obviously include 90 degree turns, since no
 
 * information is available about the exact angle of entering */
 
static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir) { return _exitdir_reaches_trackdirs[diagdir]; }
 

	
 
/**
 
 * Returns all tracks that can be reached when entering a tile from a given
 
 * (diagonal) direction. This will obviously include 90 degree turns, since no
 
 * information is available about the exact angle of entering */
 
static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); }
 

	
 
/**
 
 * Maps a trackdir to the trackdirs that can be reached from it (ie, when
 
 * entering the next tile. This will include 90 degree turns!
 
 */
 
static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; }
 
/* Note that there is no direct table for this function (there used to be),
 
 * but it uses two simpeler tables to achieve the result */
 

	
 

	
 
/**
 
 * Maps a trackdir to all trackdirs that make 90 deg turns with it.
 
 */
 
static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir) {
 
	extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END];
 
	return _track_crosses_trackdirs[TrackdirToTrack(trackdir)];
 
}
 

	
 

	
 
/* Checks if a given Track is diagonal */
 
static inline bool IsDiagonalTrack(Track track) { return (track == TRACK_X) || (track == TRACK_Y); }
 

	
 
/* Checks if a given Trackdir is diagonal. */
 
static inline bool IsDiagonalTrackdir(Trackdir trackdir) { return IsDiagonalTrack(TrackdirToTrack(trackdir)); }
 

	
 
/*
 
 * Functions quering signals on tiles.
 
 */
 

	
 
/**
 
 * Checks for the presence of signals (either way) on the given track on the
 
 * given rail tile.
 
 */
 
static inline bool HasSignalOnTrack(TileIndex tile, Track track)
 
{
 
	assert(IsValidTrack(track));
 
	return
 
		GetRailTileType(tile) == RAIL_TYPE_SIGNALS &&
 
		GetRailTileType(tile) == RAIL_TILE_SIGNALS &&
 
		(_m[tile].m3 & SignalOnTrack(track)) != 0;
 
}
 

	
 
/**
 
 * Checks for the presence of signals along the given trackdir on the given
 
 * rail tile.
 
 *
 
 * Along meaning if you are currently driving on the given trackdir, this is
 
 * the signal that is facing us (for which we stop when it's red).
 
 */
 
static inline bool HasSignalOnTrackdir(TileIndex tile, Trackdir trackdir)
 
{
 
	assert (IsValidTrackdir(trackdir));
 
	return
 
		GetRailTileType(tile) == RAIL_TYPE_SIGNALS &&
 
		GetRailTileType(tile) == RAIL_TILE_SIGNALS &&
 
		_m[tile].m3 & SignalAlongTrackdir(trackdir);
 
}
 

	
 
/**
 
 * Gets the state of the signal along the given trackdir.
 
 *
 
 * Along meaning if you are currently driving on the given trackdir, this is
 
 * the signal that is facing us (for which we stop when it's red).
 
 */
 
static inline SignalState GetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir)
 
{
 
	assert(IsValidTrackdir(trackdir));
 
	assert(HasSignalOnTrack(tile, TrackdirToTrack(trackdir)));
 
	return _m[tile].m2 & SignalAlongTrackdir(trackdir) ?
 
		SIGNAL_STATE_GREEN : SIGNAL_STATE_RED;
 
}
 

	
 

	
 
/**
 
 * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
 
 * Note that there is no check if the given trackdir is actually present on
 
 * the tile!
 
 * The given trackdir is used when there are (could be) multiple rail types on
 
 * one tile.
 
 */
 
RailType GetTileRailType(TileIndex tile, Trackdir trackdir);
 

	
 

	
 
/**
 
 * Returns a pointer to the Railtype information for a given railtype
 
 * @param railtype the rail type which the information is requested for
 
 * @return The pointer to the RailtypeInfo
 
 */
 
static inline const RailtypeInfo *GetRailTypeInfo(RailType railtype)
 
{
 
	assert(railtype < RAILTYPE_END);
 
	return &_railtypes[railtype];
 
}
 

	
 
/**
 
 * Checks if an engine of the given RailType can drive on a tile with a given
 
 * RailType. This would normally just be an equality check, but for electric
 
 * rails (which also support non-electric engines).
 
 * @return Whether the engine can drive on this tile.
 
 * @param  enginetype The RailType of the engine we are considering.
 
 * @param  tiletype   The RailType of the tile we are considering.
 
 */
 
static inline bool IsCompatibleRail(RailType enginetype, RailType tiletype)
rail_cmd.c
Show inline comments
 
@@ -32,113 +32,113 @@
 

	
 
const byte _track_sloped_sprites[14] = {
 
	14, 15, 22, 13,
 
	 0, 21, 17, 12,
 
	23,  0, 18, 20,
 
	19, 16
 
};
 

	
 
void ShowTrainDepotWindow(TileIndex tile);
 

	
 
/*         4
 
 *     ---------
 
 *    |\       /|
 
 *    | \    1/ |
 
 *    |  \   /  |
 
 *    |   \ /   |
 
 *  16|    \    |32
 
 *    |   / \2  |
 
 *    |  /   \  |
 
 *    | /     \ |
 
 *    |/       \|
 
 *     ---------
 
 *         8
 
 */
 

	
 

	
 

	
 
/* MAP2 byte:    abcd???? => Signal On? Same coding as map3lo
 
 * MAP3LO byte:  abcd???? => Signal Exists?
 
 *				 a and b are for diagonals, upper and left,
 
 *				 one for each direction. (ie a == NE->SW, b ==
 
 *				 SW->NE, or v.v., I don't know. b and c are
 
 *				 similar for lower and right.
 
 * MAP2 byte:    ????abcd => Type of ground.
 
 * MAP3LO byte:  ????abcd => Type of rail.
 
 * MAP5:         00abcdef => rail
 
 *               01abcdef => rail w/ signals
 
 *               10uuuuuu => unused
 
 *               11uuuudd => rail depot
 
 */
 

	
 
static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
 
{
 
	RailTileType type = GetRailTileType(tile);
 
	TrackBits current; /* The current track layout */
 
	TrackBits future; /* The track layout we want to build */
 
	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
 

	
 
	if (type != RAIL_TYPE_NORMAL && type != RAIL_TYPE_SIGNALS)
 
	if (type != RAIL_TILE_NORMAL && type != RAIL_TILE_SIGNALS)
 
		return false; /* Cannot build anything on depots and checkpoints */
 

	
 
	/* So, we have a tile with tracks on it (and possibly signals). Let's see
 
	 * what tracks first */
 
	current = GetTrackBits(tile);
 
	future = current | to_build;
 

	
 
	/* Are we really building something new? */
 
	if (current == future) {
 
		/* Nothing new is being built */
 
		_error_message = STR_1007_ALREADY_BUILT;
 
		return false;
 
	}
 

	
 
	/* Let's see if we may build this */
 
	if ((flags & DC_NO_RAIL_OVERLAP) || type == RAIL_TYPE_SIGNALS) {
 
	if ((flags & DC_NO_RAIL_OVERLAP) || type == RAIL_TILE_SIGNALS) {
 
		/* If we are not allowed to overlap (flag is on for ai players or we have
 
		 * signals on the tile), check that */
 
		return future == TRACK_BIT_HORZ || future == TRACK_BIT_VERT;
 
	} else {
 
		/* Normally, we may overlap and any combination is valid */
 
		return true;
 
	}
 
}
 

	
 

	
 
const TrackBits _valid_tileh_slopes[2][15] = {
 

	
 
// set of normal ones
 
{
 
	TRACK_BIT_ALL,
 
	TRACK_BIT_RIGHT,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_X,
 

	
 
	TRACK_BIT_LEFT,
 
	0,
 
	TRACK_BIT_Y,
 
	TRACK_BIT_LOWER,
 

	
 
	TRACK_BIT_LOWER,
 
	TRACK_BIT_Y,
 
	0,
 
	TRACK_BIT_LEFT,
 

	
 
	TRACK_BIT_X,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_RIGHT,
 
},
 

	
 
// allowed rail for an evenly raised platform
 
{
 
	0,
 
	TRACK_BIT_LEFT,
 
	TRACK_BIT_LOWER,
 
	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
 

	
 
	TRACK_BIT_RIGHT,
 
	TRACK_BIT_ALL,
 
	TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,
 
	TRACK_BIT_ALL,
 

	
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_LEFT,
 
@@ -216,97 +216,97 @@ static inline bool ValParamTrackOrientat
 
 * @param tile tile  to build on
 
 * @param p1 railtype of being built piece (normal, mono, maglev)
 
 * @param p2 rail track to build
 
 */
 
int32 CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Slope tileh;
 
	Track track = (Track)p2;
 
	TrackBits trackbit;
 
	int32 cost = 0;
 
	int32 ret;
 

	
 
	if (!ValParamRailtype(p1) || !ValParamTrackOrientation(track)) return CMD_ERROR;
 

	
 
	tileh = GetTileSlope(tile, NULL);
 
	trackbit = TrackToTrackBits(track);
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	switch (GetTileType(tile)) {
 
		case MP_TUNNELBRIDGE:
 
			if (!IsBridge(tile) ||
 
					!IsBridgeMiddle(tile) ||
 
					(GetBridgeAxis(tile) == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) != trackbit) {
 
				// Get detailed error message
 
				return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			}
 

	
 
			if (IsClearUnderBridge(tile)) {
 
				ret = CheckRailSlope(tileh, trackbit, 0, tile);
 
				if (CmdFailed(ret)) return ret;
 
				cost += ret;
 

	
 
				if (flags & DC_EXEC) SetRailUnderBridge(tile, _current_player, p1);
 
			} else if (IsTransportUnderBridge(tile) &&
 
					GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
 
				return_cmd_error(STR_1007_ALREADY_BUILT);
 
			} else {
 
				// Get detailed error message
 
				return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			}
 
			break;
 

	
 
		case MP_RAILWAY:
 
			if (!CheckTrackCombination(tile, trackbit, flags) ||
 
					!EnsureNoVehicle(tile)) {
 
				return CMD_ERROR;
 
			}
 
			if (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT ||
 
			if (GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT ||
 
					!IsTileOwner(tile, _current_player) ||
 
					GetRailType(tile) != p1) {
 
				// Get detailed error message
 
				return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			}
 

	
 
			ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
 
			if (CmdFailed(ret)) return ret;
 
			cost += ret;
 

	
 
			if (flags & DC_EXEC) {
 
				SetRailGroundType(tile, RAIL_GROUND_BARREN);
 
				_m[tile].m5 |= trackbit;
 
			}
 
			break;
 

	
 
		case MP_STREET:
 
#define M(x) (1 << (x))
 
			/* Level crossings may only be built on these slopes */
 
			if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 
#undef M
 

	
 
			if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
			if (GetRoadType(tile) == ROAD_NORMAL && (
 
						(track == TRACK_X && GetRoadBits(tile) == ROAD_Y) ||
 
						(track == TRACK_Y && GetRoadBits(tile) == ROAD_X)
 
					)) {
 
				if (flags & DC_EXEC) {
 
					MakeRoadCrossing(tile, GetTileOwner(tile), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), p1, GetTownIndex(tile));
 
				}
 
				break;
 
			}
 

	
 
			if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) {
 
				return_cmd_error(STR_1007_ALREADY_BUILT);
 
			}
 
			/* FALLTHROUGH */
 

	
 
		default:
 
			ret = CheckRailSlope(tileh, trackbit, 0, tile);
 
			if (CmdFailed(ret)) return ret;
 
			cost += ret;
 

	
 
			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			if (CmdFailed(ret)) return ret;
 
@@ -621,256 +621,256 @@ int32 CmdBuildSingleSignal(TileIndex til
 
	SignalVariant sigvar;
 
	bool pre_signal;
 
	Track track = (Track)(p1 & 0x7);
 
	int32 cost;
 

	
 
	// Same bit, used in different contexts
 
	sigvar = HASBIT(p1, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC;
 
	pre_signal = HASBIT(p1, 3);
 

	
 
	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	/* Protect against invalid signal copying */
 
	if (p2 != 0 && (p2 & SignalOnTrack(track)) == 0) return CMD_ERROR;
 

	
 
	/* You can only build signals on plain rail tiles, and the selected track must exist */
 
	if (!IsPlainRailTile(tile) || !HasTrack(tile, track)) return CMD_ERROR;
 

	
 
	if (!CheckTileOwnership(tile)) return CMD_ERROR;
 

	
 
	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
 

	
 
	{
 
 		/* See if this is a valid track combination for signals, (ie, no overlap) */
 
 		TrackBits trackbits = GetTrackBits(tile);
 
		if (KILL_FIRST_BIT(trackbits) != 0 && /* More than one track present */
 
				trackbits != TRACK_BIT_HORZ &&
 
				trackbits != TRACK_BIT_VERT
 
		)
 
			return CMD_ERROR;
 
	}
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	if (!HasSignalOnTrack(tile, track)) {
 
		// build new signals
 
		cost = _price.build_signals;
 
	} else {
 
		if (p2 != 0 && sigvar != GetSignalVariant(tile)) {
 
			// convert signals <-> semaphores
 
			cost = _price.build_signals + _price.remove_signals;
 
		} else {
 
			// it is free to change orientation/pre-exit-combo signals
 
			cost = 0;
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		if (GetRailTileType(tile) != RAIL_TYPE_SIGNALS) {
 
		if (GetRailTileType(tile) != RAIL_TILE_SIGNALS) {
 
			// there are no signals at all on this tile yet
 
			_m[tile].m5 |= RAIL_TYPE_SIGNALS; // change into signals
 
			_m[tile].m5 |= RAIL_TILE_SIGNALS; // change into signals
 
			_m[tile].m2 |= 0xF0;              // all signals are on
 
			_m[tile].m3 &= ~0xF0;          // no signals built by default
 
			SetSignalType(tile, SIGTYPE_NORMAL);
 
			SetSignalVariant(tile, sigvar);
 
		}
 

	
 
		if (p2 == 0) {
 
			if (!HasSignalOnTrack(tile, track)) {
 
				// build new signals
 
				_m[tile].m3 |= SignalOnTrack(track);
 
			} else {
 
				if (pre_signal) {
 
					// cycle between normal -> pre -> exit -> combo -> ...
 
					SignalType type = GetSignalType(tile);
 

	
 
					SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : type + 1);
 
				} else {
 
					CycleSignalSide(tile, track);
 
				}
 
			}
 
		} else {
 
			/* If CmdBuildManySignals is called with copying signals, just copy the
 
			 * direction of the first signal given as parameter by CmdBuildManySignals */
 
			_m[tile].m3 &= ~SignalOnTrack(track);
 
			_m[tile].m3 |= p2 & SignalOnTrack(track);
 
			SetSignalVariant(tile, sigvar);
 
		}
 

	
 
		MarkTileDirtyByTile(tile);
 
		SetSignalsOnBothDir(tile, track);
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**	Build many signals by dragging; AutoSignals
 
 * @param tile start tile of drag
 
 * @param p1  end tile of drag
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit  0)    - 0 = build, 1 = remove signals
 
 * - p2 = (bit  3)    - 0 = signals, 1 = semaphores
 
 * - p2 = (bit  4- 6) - track-orientation, valid values: 0-5 (Track enum)
 
 * - p2 = (bit 24-31) - user defined signals_density
 
 */
 
static int32 CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	int32 ret, total_cost, signal_ctr;
 
	byte signals;
 
	bool error = true;
 
	TileIndex end_tile;
 

	
 
	int mode = p2 & 0x1;
 
	Track track = GB(p2, 4, 3);
 
	Trackdir trackdir = TrackToTrackdir(track);
 
	byte semaphores = (HASBIT(p2, 3)) ? 8 : 0;
 
	byte signal_density = (p2 >> 24);
 

	
 
	if (p1 >= MapSize()) return CMD_ERROR;
 
	end_tile = p1;
 
	if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
 

	
 
	if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* for vertical/horizontal tracks, double the given signals density
 
	* since the original amount will be too dense (shorter tracks) */
 
	if (!IsDiagonalTrack(track))
 
		signal_density *= 2;
 

	
 
	if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
 

	
 
	track = TrackdirToTrack(trackdir); /* trackdir might have changed, keep track in sync */
 

	
 
	// copy the signal-style of the first rail-piece if existing
 
	if (GetRailTileType(tile) == RAIL_TYPE_SIGNALS && GetTrackBits(tile) != 0) { /* XXX: GetTrackBits check useless? */
 
	if (GetRailTileType(tile) == RAIL_TILE_SIGNALS && GetTrackBits(tile) != 0) { /* XXX: GetTrackBits check useless? */
 
		signals = _m[tile].m3 & SignalOnTrack(track);
 
		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
 

	
 
		// copy signal/semaphores style (independent of CTRL)
 
		semaphores = (GetSignalVariant(tile) == SIG_ELECTRIC ? 0 : 8);
 
	} else // no signals exist, drag a two-way signal stretch
 
		signals = SignalOnTrack(track);
 

	
 
	/* signal_ctr         - amount of tiles already processed
 
	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
 
	 **********
 
	 * trackdir   - trackdir to build with autorail
 
	 * semaphores - semaphores or signals
 
	 * signals    - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
 
	                and convert all others to semaphore/signal
 
	 * mode       - 1 remove signals, 0 build signals */
 
	signal_ctr = total_cost = 0;
 
	for (;;) {
 
		// only build/remove signals with the specified density
 
		if ((signal_ctr % signal_density) == 0 ) {
 
			ret = DoCommand(tile, TrackdirToTrack(trackdir) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
 

	
 
			/* Abort placement for any other error than NOT_SUITABLE_TRACK
 
			 * This includes vehicles on track, competitor's tracks, etc. */
 
			if (CmdFailed(ret)) {
 
				if (_error_message != STR_1005_NO_SUITABLE_RAILROAD_TRACK && mode != 1) return CMD_ERROR;
 
				_error_message = INVALID_STRING_ID;
 
			} else {
 
				error = false;
 
				total_cost += ret;
 
			}
 
		}
 

	
 
		if (tile == end_tile) break;
 

	
 
		tile += ToTileIndexDiff(_trackdelta[trackdir]);
 
		signal_ctr++;
 

	
 
		// toggle railbit for the non-diagonal tracks (|, -- tracks)
 
		if (!IsDiagonalTrackdir(trackdir)) trackdir ^= 1;
 
	}
 

	
 
	return error ? CMD_ERROR : total_cost;
 
}
 

	
 
/** Build signals on a stretch of track.
 
 * Stub for the unified signal builder/remover
 
 * @see CmdSignalTrackHelper
 
 */
 
int32 CmdBuildSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	return CmdSignalTrackHelper(tile, flags, p1, p2);
 
}
 

	
 
/** Remove signals
 
 * @param tile coordinates where signal is being deleted from
 
 * @param p1 track to remove signal from (Track enum)
 
 */
 
int32 CmdRemoveSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Track track = (Track)(p1 & 0x7);
 

	
 
	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	if (!HasSignalOnTrack(tile, track)) // no signals on track?
 
		return CMD_ERROR;
 

	
 
	/* Only water can remove signals from anyone */
 
	if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* Do it? */
 
	if (flags & DC_EXEC) {
 
		_m[tile].m3 &= ~SignalOnTrack(track);
 

	
 
		/* removed last signal from tile? */
 
		if (GB(_m[tile].m3, 4, 4) == 0) {
 
			SB(_m[tile].m2, 4, 4, 0);
 
			SB(_m[tile].m5, 6, 2, RAIL_TYPE_NORMAL >> 6); // XXX >> because the constant is meant for direct application, not use with SB
 
			SB(_m[tile].m5, 6, 2, RAIL_TILE_NORMAL >> 6); // XXX >> because the constant is meant for direct application, not use with SB
 
			SetSignalVariant(tile, SIG_ELECTRIC); // remove any possible semaphores
 
		}
 

	
 
		SetSignalsOnBothDir(tile, track);
 

	
 
		MarkTileDirtyByTile(tile);
 
	}
 

	
 
	return _price.remove_signals;
 
}
 

	
 
/** Remove signals on a stretch of track.
 
 * Stub for the unified signal builder/remover
 
 * @see CmdSignalTrackHelper
 
 */
 
int32 CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 0));
 
}
 

	
 
typedef int32 DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
 

	
 
static int32 DoConvertRail(TileIndex tile, RailType totype, bool exec)
 
{
 
	if (!CheckTileOwnership(tile)) return CMD_ERROR;
 

	
 
	if (!EnsureNoVehicle(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR;
 

	
 
	// tile is already of requested type?
 
	if (GetRailType(tile) == totype) return CMD_ERROR;
 

	
 
	// change type.
 
	if (exec) {
 
		SetRailType(tile, totype);
 
		MarkTileDirtyByTile(tile);
 
	}
 

	
 
	return _price.build_rail / 2;
 
}
 

	
 
extern int32 DoConvertStationRail(TileIndex tile, RailType totype, bool exec);
 
extern int32 DoConvertStreetRail(TileIndex tile, RailType totype, bool exec);
 
extern int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec);
 

	
 
/** Convert one rail type to the other. You can convert normal rail to
 
 * monorail/maglev easily or vice-versa.
 
 * @param tile end tile of rail conversion drag
 
 * @param p1 start tile of drag
 
@@ -912,143 +912,143 @@ int32 CmdConvertRail(TileIndex tile, uin
 
				default: continue;
 
			}
 

	
 
			ret = proc(tile, p2, false);
 
			if (CmdFailed(ret)) continue;
 
			cost += ret;
 

	
 
			if (flags & DC_EXEC) {
 
				money -= ret;
 
				if (money < 0) {
 
					_additional_cash_required = ret;
 
					return cost - ret;
 
				}
 
				proc(tile, p2, true);
 
			}
 
		}
 
	}
 

	
 
	return (cost == 0) ? CMD_ERROR : cost;
 
}
 

	
 
static int32 RemoveTrainDepot(TileIndex tile, uint32 flags)
 
{
 
	if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
 
		return CMD_ERROR;
 

	
 
	if (!EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DiagDirection dir = GetRailDepotDirection(tile);
 

	
 
		DoDeleteDepot(tile);
 
		UpdateSignalsOnSegment(tile, dir);
 
	}
 

	
 
	return _price.remove_train_depot;
 
}
 

	
 
static int32 ClearTile_Track(TileIndex tile, byte flags)
 
{
 
	int32 cost;
 
	int32 ret;
 
	byte m5;
 

	
 
	m5 = _m[tile].m5;
 

	
 
	if (flags & DC_AUTO) {
 
		if (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT) {
 
		if (GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT) {
 
			return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
 
		}
 

	
 
		if (!IsTileOwner(tile, _current_player))
 
			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
 

	
 
		return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
 
	}
 

	
 
	cost = 0;
 

	
 
	switch (GetRailTileType(tile)) {
 
		/* XXX: Why the fuck do we remove these thow signals first? */
 
		case RAIL_TYPE_SIGNALS:
 
		case RAIL_TILE_SIGNALS:
 
			if (HasSignalOnTrack(tile, TRACK_X)) {
 
				ret = DoCommand(tile, TRACK_X, 0, flags, CMD_REMOVE_SIGNALS);
 
				if (CmdFailed(ret)) return CMD_ERROR;
 
				cost += ret;
 
			}
 
			if (HasSignalOnTrack(tile, TRACK_LOWER)) {
 
				ret = DoCommand(tile, TRACK_LOWER, 0, flags, CMD_REMOVE_SIGNALS);
 
				if (CmdFailed(ret)) return CMD_ERROR;
 
				cost += ret;
 
			}
 

	
 
			m5 &= TRACK_BIT_MASK;
 
			if (!(flags & DC_EXEC)) {
 
				for (; m5 != 0; m5 >>= 1) if (m5 & 1) cost += _price.remove_rail;
 
				return cost;
 
			}
 
			/* FALLTHROUGH */
 

	
 
		case RAIL_TYPE_NORMAL: {
 
		case RAIL_TILE_NORMAL: {
 
			uint i;
 

	
 
			for (i = 0; m5 != 0; i++, m5 >>= 1) {
 
				if (m5 & 1) {
 
					ret = DoCommand(tile, 0, i, flags, CMD_REMOVE_SINGLE_RAIL);
 
					if (CmdFailed(ret)) return CMD_ERROR;
 
					cost += ret;
 
				}
 
			}
 
			return cost;
 
		}
 

	
 
		case RAIL_TYPE_DEPOT_WAYPOINT:
 
		case RAIL_TILE_DEPOT_WAYPOINT:
 
			if (GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT) {
 
				return RemoveTrainDepot(tile, flags);
 
			} else {
 
				return RemoveTrainWaypoint(tile, flags, false);
 
			}
 

	
 
		default:
 
			return CMD_ERROR;
 
	}
 
}
 

	
 
#include "table/track_land.h"
 

	
 
static void DrawSingleSignal(TileIndex tile, byte condition, uint image, uint pos)
 
{
 
	bool side = _opt.road_side & _patches.signal_side;
 
	static const Point SignalPositions[2][12] = {
 
		{      /* Signals on the left side */
 
		/*  LEFT      LEFT      RIGHT     RIGHT     UPPER     UPPER */
 
			{ 8,  5}, {14,  1}, { 1, 14}, { 9, 11}, { 1,  0}, { 3, 10},
 
		/*  LOWER     LOWER     X         X         Y         Y     */
 
			{11,  4}, {14, 14}, {11,  3}, { 4, 13}, { 3,  4}, {11, 13}
 
		}, {   /* Signals on the right side */
 
		/*  LEFT      LEFT      RIGHT     RIGHT     UPPER     UPPER */
 
			{14,  1}, {12, 10}, { 4,  6}, { 1, 14}, {10,  4}, { 0,  1},
 
		/*  LOWER     LOWER     X         X         Y         Y     */
 
			{14, 14}, { 5, 12}, {11, 13}, { 4,  3}, {13,  4}, { 3, 11}
 
		}
 
	};
 

	
 
	static const SpriteID SignalBase[2][2][4] = {
 
		{    /* Signals on left side */
 
			{  0x4FB, 0x1323, 0x1333, 0x1343}, /* light signals */
 
			{ 0x1353, 0x1363, 0x1373, 0x1383}  /* semaphores    */
 
		}, { /* Signals on right side */
 
			{  0x4FB, 0x1323, 0x1333, 0x1343}, /* light signals */
 
			{ 0x1446, 0x1456, 0x1466, 0x1476}  /* semaphores    */
 
		/*         |       |       |       |     */
 
		/*    normal,  entry,   exit,  combo     */
 
		}
 
	};
 

	
 
	uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
 
	uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
 

	
 
	SpriteID sprite;
 

	
 
	/* _signal_base is set by our NewGRF Action 5 loader. If it is 0 then we
 
@@ -1253,105 +1253,105 @@ static void DrawTrackBits(TileInfo* ti, 
 
		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s);
 
		if (track & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w);
 
		if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e);
 
	}
 

	
 
	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
 

	
 
}
 

	
 
static void DrawSignals(TileIndex tile, TrackBits rails)
 
{
 
#define MAYBE_DRAW_SIGNAL(x,y,z) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, GetSingleSignalState(tile, x), y - 0x4FB, z)
 

	
 
	if (!(rails & TRACK_BIT_Y)) {
 
		if (!(rails & TRACK_BIT_X)) {
 
			if (rails & TRACK_BIT_LEFT) {
 
				MAYBE_DRAW_SIGNAL(2, 0x509, 0);
 
				MAYBE_DRAW_SIGNAL(3, 0x507, 1);
 
			}
 
			if (rails & TRACK_BIT_RIGHT) {
 
				MAYBE_DRAW_SIGNAL(0, 0x509, 2);
 
				MAYBE_DRAW_SIGNAL(1, 0x507, 3);
 
			}
 
			if (rails & TRACK_BIT_UPPER) {
 
				MAYBE_DRAW_SIGNAL(3, 0x505, 4);
 
				MAYBE_DRAW_SIGNAL(2, 0x503, 5);
 
			}
 
			if (rails & TRACK_BIT_LOWER) {
 
				MAYBE_DRAW_SIGNAL(1, 0x505, 6);
 
				MAYBE_DRAW_SIGNAL(0, 0x503, 7);
 
			}
 
		} else {
 
			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8);
 
			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9);
 
		}
 
	} else {
 
		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10);
 
		MAYBE_DRAW_SIGNAL(2, 0x501, 11);
 
	}
 
}
 

	
 
static void DrawTile_Track(TileInfo *ti)
 
{
 
	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
	PalSpriteID image;
 

	
 
	_drawtile_track_palette = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile)));
 

	
 
	if (GetRailTileType(ti->tile) != RAIL_TYPE_DEPOT_WAYPOINT) {
 
	if (GetRailTileType(ti->tile) != RAIL_TILE_DEPOT_WAYPOINT) {
 
		TrackBits rails = GetTrackBits(ti->tile);
 

	
 
		DrawTrackBits(ti, rails, false);
 

	
 
		if (_display_opt & DO_FULL_DETAIL) _detailed_track_proc[GetRailGroundType(ti->tile)](ti);
 

	
 
		/* draw signals also? */
 
		if (GetRailTileType(ti->tile) == RAIL_TYPE_SIGNALS) DrawSignals(ti->tile, rails);
 
		if (GetRailTileType(ti->tile) == RAIL_TILE_SIGNALS) DrawSignals(ti->tile, rails);
 

	
 
	} else {
 
		/* draw depots / waypoints */
 
		const DrawTrackSeqStruct *drss;
 
		bool is_depot = GetRailTileSubtype(ti->tile) == RAIL_SUBTYPE_DEPOT;
 

	
 
		if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
 

	
 
		if (IsRailWaypoint(ti->tile) && IsCustomWaypoint(ti->tile)) {
 
			// look for customization
 
			byte stat_id = GetWaypointByTile(ti->tile)->stat_id;
 
			const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, stat_id);
 

	
 
			if (statspec != NULL) {
 
				DrawTileSeqStruct const *seq;
 
				// emulate station tile - open with building
 
				uint tile = 2;
 
				const DrawTileSprites *cust;
 
				Station *st = ComposeWaypointStation(ti->tile);
 

	
 
				uint32 relocation = GetCustomStationRelocation(statspec, st, ti->tile);
 

	
 
				if (HASBIT(statspec->callbackmask, CBM_CUSTOM_LAYOUT)) {
 
					uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
 
					if (callback != CALLBACK_FAILED) tile = callback;
 
				}
 

	
 
				if (statspec->renderdata == NULL) {
 
					cust = GetStationTileLayout(tile);
 
				} else {
 
					cust = &statspec->renderdata[(tile < statspec->tiles ? tile : 0) + GetWaypointAxis(ti->tile)];
 
				}
 

	
 
				/* If there is no sprite layout, we fall back to the default waypoint graphics. */
 
				if (cust != NULL && cust->seq != NULL) {
 
					image = cust->ground_sprite;
 
					if (HASBIT(image, 31)) {
 
						CLRBIT(image, 31);
 
						image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
 
						image += rti->custom_ground_offset;
 
					} else {
 
						image += rti->total_offset;
 
					}
 

	
 
					DrawGroundSprite(image);
 

	
 
					if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
 

	
 
@@ -1672,326 +1672,326 @@ make_red:
 
bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction)
 
{
 
	SetSignalsData ssd;
 
	int result = -1;
 

	
 
	ssd.cur_stack = 0;
 

	
 
	for (;;) {
 
		// go through one segment and update all signals pointing into that segment.
 
		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
 
		ssd.has_presignal = false;
 

	
 
		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
 
		ChangeSignalStates(&ssd);
 

	
 
		// remember the result only for the first iteration.
 
		if (result < 0) result = ssd.stop;
 

	
 
		// if any exit signals were changed, we need to keep going to modify the stuff behind those.
 
		if (ssd.cur_stack == 0) break;
 

	
 
		// one or more exit signals were changed, so we need to update another segment too.
 
		tile = ssd.next_tile[--ssd.cur_stack];
 
		direction = ssd.next_dir[ssd.cur_stack];
 
	}
 

	
 
	return result != 0;
 
}
 

	
 
void SetSignalsOnBothDir(TileIndex tile, byte track)
 
{
 
	static const DiagDirection _search_dir_1[] = {
 
		DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE
 
	};
 
	static const DiagDirection _search_dir_2[] = {
 
		DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
 
	};
 

	
 
	UpdateSignalsOnSegment(tile, _search_dir_1[track]);
 
	UpdateSignalsOnSegment(tile, _search_dir_2[track]);
 
}
 

	
 
static uint GetSlopeZ_Track(const TileInfo* ti)
 
{
 
	Slope tileh = ti->tileh;
 
	uint z = ti->z;
 

	
 
	if (tileh == SLOPE_FLAT) return z;
 
	if (GetRailTileType(ti->tile) == RAIL_TYPE_DEPOT_WAYPOINT) {
 
	if (GetRailTileType(ti->tile) == RAIL_TILE_DEPOT_WAYPOINT) {
 
		return z + TILE_HEIGHT;
 
	} else {
 
		uint f = GetRailFoundation(ti->tileh, GetTrackBits(ti->tile));
 

	
 
		if (f != 0) {
 
			if (f < 15) return z + TILE_HEIGHT; // leveled foundation
 
			tileh = _inclined_tileh[f - 15]; // inclined foundation
 
		}
 
		return z + GetPartialZ(ti->x & 0xF, ti->y & 0xF, tileh);
 
	}
 
}
 

	
 
static Slope GetSlopeTileh_Track(TileIndex tile, Slope tileh)
 
{
 
	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
 
	if (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT) {
 
	if (GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT) {
 
		return SLOPE_FLAT;
 
	} else {
 
		uint f = GetRailFoundation(tileh, GetTrackBits(tile));
 

	
 
		if (f == 0) return tileh;
 
		if (f < 15) return SLOPE_FLAT; // leveled foundation
 
		return _inclined_tileh[f - 15]; // inclined foundation
 
	}
 
}
 

	
 
static void GetAcceptedCargo_Track(TileIndex tile, AcceptedCargo ac)
 
{
 
	/* not used */
 
}
 

	
 
static void AnimateTile_Track(TileIndex tile)
 
{
 
	/* not used */
 
}
 

	
 
static void TileLoop_Track(TileIndex tile)
 
{
 
	RailGroundType old_ground = GetRailGroundType(tile);
 
	RailGroundType new_ground = old_ground;
 
	bool quick_return = false;
 

	
 
	switch (_opt.landscape) {
 
		case LT_HILLY:
 
			if (GetTileZ(tile) > _opt.snow_line) {
 
				new_ground = RAIL_GROUND_ICE_DESERT;
 
				quick_return = true;
 
			}
 
			break;
 

	
 
		case LT_DESERT:
 
			if (GetTropicZone(tile) == TROPICZONE_DESERT) {
 
				new_ground = RAIL_GROUND_ICE_DESERT;
 
				quick_return = true;
 
			}
 
			break;
 
	}
 

	
 
	if (new_ground != old_ground) {
 
		SetRailGroundType(tile, new_ground);
 
		MarkTileDirtyByTile(tile);
 
	}
 

	
 
	if (quick_return) return;
 

	
 
	// Don't continue tile loop for depots
 
	if (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT) return;
 
	if (GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT) return;
 

	
 
	new_ground = RAIL_GROUND_GRASS;
 

	
 
	if (old_ground != RAIL_GROUND_BARREN) { /* wait until bottom is green */
 
		/* determine direction of fence */
 
		TrackBits rail = GetTrackBits(tile);
 

	
 
		switch (rail) {
 
			case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
 
			case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
 
			case TRACK_BIT_LEFT:  new_ground = RAIL_GROUND_FENCE_VERT1;  break;
 
			case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2;  break;
 

	
 
			default: {
 
				PlayerID owner = GetTileOwner(tile);
 

	
 
				if (rail == (TRACK_BIT_LOWER | TRACK_BIT_RIGHT) || (
 
							(rail & TRACK_BIT_3WAY_NW) == 0 &&
 
							(rail & TRACK_BIT_X)
 
						)) {
 
					TileIndex n = tile + TileDiffXY(0, -1);
 
					TrackBits nrail = GetTrackBits(n);
 

	
 
					if (!IsTileType(n, MP_RAILWAY) ||
 
							!IsTileOwner(n, owner) ||
 
							nrail == TRACK_BIT_UPPER ||
 
							nrail == TRACK_BIT_LEFT) {
 
						new_ground = RAIL_GROUND_FENCE_NW;
 
					}
 
				}
 

	
 
				if (rail == (TRACK_BIT_UPPER | TRACK_BIT_LEFT) || (
 
							(rail & TRACK_BIT_3WAY_SE) == 0 &&
 
							(rail & TRACK_BIT_X)
 
						)) {
 
					TileIndex n = tile + TileDiffXY(0, 1);
 
					TrackBits nrail = GetTrackBits(n);
 

	
 
					if (!IsTileType(n, MP_RAILWAY) ||
 
							!IsTileOwner(n, owner) ||
 
							nrail == TRACK_BIT_LOWER ||
 
							nrail == TRACK_BIT_RIGHT) {
 
						new_ground = (new_ground == RAIL_GROUND_FENCE_NW) ?
 
							RAIL_GROUND_FENCE_SENW : RAIL_GROUND_FENCE_SE;
 
					}
 
				}
 

	
 
				if (rail == (TRACK_BIT_LOWER | TRACK_BIT_LEFT) || (
 
							(rail & TRACK_BIT_3WAY_NE) == 0 &&
 
							(rail & TRACK_BIT_Y)
 
						)) {
 
					TileIndex n = tile + TileDiffXY(-1, 0);
 
					TrackBits nrail = GetTrackBits(n);
 

	
 
					if (!IsTileType(n, MP_RAILWAY) ||
 
							!IsTileOwner(n, owner) ||
 
							nrail == TRACK_BIT_UPPER ||
 
							nrail == TRACK_BIT_RIGHT) {
 
						new_ground = RAIL_GROUND_FENCE_NE;
 
					}
 
				}
 

	
 
				if (rail == (TRACK_BIT_UPPER | TRACK_BIT_RIGHT) || (
 
							(rail & TRACK_BIT_3WAY_SW) == 0 &&
 
							(rail & TRACK_BIT_Y)
 
						)) {
 
					TileIndex n = tile + TileDiffXY(1, 0);
 
					TrackBits nrail = GetTrackBits(n);
 

	
 
					if (!IsTileType(n, MP_RAILWAY) ||
 
							!IsTileOwner(n, owner) ||
 
							nrail == TRACK_BIT_LOWER ||
 
							nrail == TRACK_BIT_LEFT) {
 
						new_ground = (new_ground == RAIL_GROUND_FENCE_NE) ?
 
							RAIL_GROUND_FENCE_NESW : RAIL_GROUND_FENCE_SW;
 
					}
 
				}
 
				break;
 
			}
 
		}
 
	}
 

	
 
	if (old_ground != new_ground) {
 
		SetRailGroundType(tile, new_ground);
 
		MarkTileDirtyByTile(tile);
 
	}
 
}
 

	
 

	
 
static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode)
 
{
 
	byte a;
 
	uint16 b;
 

	
 
	if (mode != TRANSPORT_RAIL) return 0;
 

	
 
	if (GetRailTileType(tile) != RAIL_TYPE_DEPOT_WAYPOINT) {
 
	if (GetRailTileType(tile) != RAIL_TILE_DEPOT_WAYPOINT) {
 
		TrackBits rails = GetTrackBits(tile);
 
		uint32 ret = rails * 0x101;
 

	
 
		if (GetRailTileType(tile) != RAIL_TYPE_SIGNALS) {
 
		if (GetRailTileType(tile) != RAIL_TILE_SIGNALS) {
 
			if (rails == TRACK_BIT_CROSS) ret |= 0x40;
 
		} else {
 
			/* has_signals */
 

	
 
			a = _m[tile].m3;
 
			b = _m[tile].m2;
 

	
 
			b &= a;
 

	
 
			/* When signals are not present (in neither
 
			 * direction), we pretend them to be green. (So if
 
			 * signals are only one way, the other way will
 
			 * implicitely become `red' */
 
			if ((a & 0xC0) == 0) b |= 0xC0;
 
			if ((a & 0x30) == 0) b |= 0x30;
 

	
 
			if ((b & 0x80) == 0) ret |= 0x10070000;
 
			if ((b & 0x40) == 0) ret |= 0x07100000;
 
			if ((b & 0x20) == 0) ret |= 0x20080000;
 
			if ((b & 0x10) == 0) ret |= 0x08200000;
 
		}
 
		return ret;
 
	} else {
 
		if (GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT) {
 
			return (DiagDirToAxis(GetRailDepotDirection(tile)) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y) * 0x101;
 
		} else {
 
			return GetRailWaypointBits(tile) * 0x101;
 
		}
 
	}
 
}
 

	
 
static void ClickTile_Track(TileIndex tile)
 
{
 
	if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
 
		ShowTrainDepotWindow(tile);
 
	} else if (IsRailWaypoint(tile)) {
 
		ShowRenameWaypointWindow(GetWaypointByTile(tile));
 
	}
 
}
 

	
 
static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
 
{
 
	td->owner = GetTileOwner(tile);
 
	switch (GetRailTileType(tile)) {
 
		case RAIL_TYPE_NORMAL:
 
		case RAIL_TILE_NORMAL:
 
			td->str = STR_1021_RAILROAD_TRACK;
 
			break;
 

	
 
		case RAIL_TYPE_SIGNALS: {
 
		case RAIL_TILE_SIGNALS: {
 
			const StringID signal_type[] = {
 
				STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS,
 
				STR_RAILROAD_TRACK_WITH_PRESIGNALS,
 
				STR_RAILROAD_TRACK_WITH_EXITSIGNALS,
 
				STR_RAILROAD_TRACK_WITH_COMBOSIGNALS
 
			};
 

	
 
			td->str = signal_type[GetSignalType(tile)];
 
			break;
 
		}
 

	
 
		case RAIL_TYPE_DEPOT_WAYPOINT:
 
		case RAIL_TILE_DEPOT_WAYPOINT:
 
		default:
 
			td->str = (GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT) ?
 
				STR_1023_RAILROAD_TRAIN_DEPOT : STR_LANDINFO_WAYPOINT;
 
			break;
 
	}
 
}
 

	
 
static void ChangeTileOwner_Track(TileIndex tile, PlayerID old_player, PlayerID new_player)
 
{
 
	if (!IsTileOwner(tile, old_player)) return;
 

	
 
	if (new_player != OWNER_SPECTATOR) {
 
		SetTileOwner(tile, new_player);
 
	}	else {
 
		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
	}
 
}
 

	
 
static const byte _fractcoords_behind[4] = { 0x8F, 0x8, 0x80, 0xF8 };
 
static const byte _fractcoords_enter[4] = { 0x8A, 0x48, 0x84, 0xA8 };
 
static const byte _deltacoord_leaveoffset[8] = {
 
	-1,  0,  1,  0, /* x */
 
	 0,  1,  0, -1  /* y */
 
};
 

	
 
static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
 
{
 
	byte fract_coord;
 
	byte fract_coord_leave;
 
	DiagDirection dir;
 
	int length;
 

	
 
	// this routine applies only to trains in depot tiles
 
	if (v->type != VEH_Train || !IsTileDepotType(tile, TRANSPORT_RAIL)) return 0;
 

	
 
	/* depot direction */
 
	dir = GetRailDepotDirection(tile);
 

	
 
	/* calculate the point where the following wagon should be activated */
 
	/* this depends on the length of the current vehicle */
 
	length = v->u.rail.cached_veh_length;
 

	
 
	fract_coord_leave =
 
		((_fractcoords_enter[dir] & 0x0F) +				// x
 
			(length + 1) * _deltacoord_leaveoffset[dir]) +
 
		(((_fractcoords_enter[dir] >> 4) +				// y
 
			((length + 1) * _deltacoord_leaveoffset[dir+4])) << 4);
 

	
rail_gui.c
Show inline comments
 
@@ -45,97 +45,97 @@ static struct {
 
static void HandleStationPlacement(TileIndex start, TileIndex end);
 
static void ShowBuildTrainDepotPicker(void);
 
static void ShowBuildWaypointPicker(void);
 
static void ShowStationBuilder(void);
 

	
 
void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	if (success) SndPlayTileFx(SND_20_SPLAT_2, tile);
 
}
 

	
 
static void GenericPlaceRail(TileIndex tile, int cmd)
 
{
 
	DoCommandP(tile, _cur_railtype, cmd, CcPlaySound1E,
 
		_remove_button_clicked ?
 
		CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) | CMD_AUTO | CMD_NO_WATER :
 
		CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) | CMD_AUTO | CMD_NO_WATER
 
	);
 
}
 

	
 
static void PlaceRail_N(TileIndex tile)
 
{
 
	int cmd = _tile_fract_coords.x > _tile_fract_coords.y ? 4 : 5;
 
	GenericPlaceRail(tile, cmd);
 
}
 

	
 
static void PlaceRail_NE(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_FIX_Y);
 
}
 

	
 
static void PlaceRail_E(TileIndex tile)
 
{
 
	int cmd = _tile_fract_coords.x + _tile_fract_coords.y <= 15 ? 2 : 3;
 
	GenericPlaceRail(tile, cmd);
 
}
 

	
 
static void PlaceRail_NW(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_FIX_X);
 
}
 

	
 
static void PlaceRail_AutoRail(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_RAILDIRS);
 
}
 

	
 
static void PlaceExtraDepotRail(TileIndex tile, uint16 extra)
 
{
 
	if (GetRailTileType(tile) != RAIL_TYPE_NORMAL) return;
 
	if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return;
 
	if ((GetTrackBits(tile) & GB(extra, 8, 8)) == 0) return;
 

	
 
	DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_AUTO | CMD_NO_WATER);
 
}
 

	
 
static const uint16 _place_depot_extra[12] = {
 
	0x604,		0x2102,		0x1202,		0x505,
 
	0x2400,		0x2801,		0x1800,		0x1401,
 
	0x2203,		0x904,		0x0A05,		0x1103,
 
};
 

	
 

	
 
void CcRailDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	if (success) {
 
		DiagDirection dir = p2;
 

	
 
		SndPlayTileFx(SND_20_SPLAT_2, tile);
 
		ResetObjectToPlace();
 

	
 
		tile += TileOffsByDir(dir);
 

	
 
		if (IsTileType(tile, MP_RAILWAY)) {
 
			PlaceExtraDepotRail(tile, _place_depot_extra[dir]);
 
			PlaceExtraDepotRail(tile, _place_depot_extra[dir + 4]);
 
			PlaceExtraDepotRail(tile, _place_depot_extra[dir + 8]);
 
		}
 
	}
 
}
 

	
 
static void PlaceRail_Depot(TileIndex tile)
 
{
 
	DoCommandP(tile, _cur_railtype, _build_depot_direction, CcRailDepot,
 
		CMD_BUILD_TRAIN_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_100E_CAN_T_BUILD_TRAIN_DEPOT));
 
}
 

	
 
static void PlaceRail_Waypoint(TileIndex tile)
 
{
 
	if (!_remove_button_clicked) {
 
		DoCommandP(tile, _cur_waypoint_type, 0, CcPlaySound1E, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT));
 
	} else {
 
		DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_WAYPOINT));
 
	}
 
}
 

	
 
void CcStation(bool success, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	if (success) {
rail_map.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef RAIL_MAP_H
 
#define RAIL_MAP_H
 

	
 
#include "direction.h"
 
#include "tile.h"
 

	
 

	
 
typedef enum RailTileType {
 
	RAIL_TYPE_NORMAL         = 0x0,
 
	RAIL_TYPE_SIGNALS        = 0x40,
 
	RAIL_TYPE_UNUSED         = 0x80, /* XXX: Maybe this could become waypoints? */
 
	RAIL_TYPE_DEPOT_WAYPOINT = 0xC0, /* Is really depots and waypoints... */
 
	RAIL_TILE_NORMAL         = 0x0,
 
	RAIL_TILE_SIGNALS        = 0x40,
 
	RAIL_TILE_UNUSED         = 0x80, /* XXX: Maybe this could become waypoints? */
 
	RAIL_TILE_DEPOT_WAYPOINT = 0xC0, /* Is really depots and waypoints... */
 
	RAIL_TILE_TYPE_MASK      = 0xC0
 
} RailTileType;
 

	
 
static inline RailTileType GetRailTileType(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_RAILWAY));
 
	return _m[t].m5 & RAIL_TILE_TYPE_MASK;
 
}
 

	
 
/**
 
 * Returns whether this is plain rails, with or without signals. Iow, if this
 
 * tiles RailTileType is RAIL_TYPE_NORMAL or RAIL_TYPE_SIGNALS.
 
 * tiles RailTileType is RAIL_TILE_NORMAL or RAIL_TILE_SIGNALS.
 
 */
 
static inline bool IsPlainRailTile(TileIndex tile)
 
{
 
	RailTileType rtt = GetRailTileType(tile);
 
	return rtt == RAIL_TYPE_NORMAL || rtt == RAIL_TYPE_SIGNALS;
 
	return rtt == RAIL_TILE_NORMAL || rtt == RAIL_TILE_SIGNALS;
 
}
 

	
 
/**
 
 * Checks if a rail tile has signals.
 
 */
 
static inline bool HasSignals(TileIndex tile)
 
{
 
	return GetRailTileType(tile) == RAIL_TYPE_SIGNALS;
 
	return GetRailTileType(tile) == RAIL_TILE_SIGNALS;
 
}
 

	
 

	
 
/** These specify the subtype when the main rail type is
 
 * RAIL_TYPE_DEPOT_WAYPOINT */
 
 * RAIL_TILE_DEPOT_WAYPOINT */
 
typedef enum RailTileSubtypes {
 
	RAIL_SUBTYPE_DEPOT    = 0x00,
 
	RAIL_SUBTYPE_WAYPOINT = 0x04,
 
	RAIL_SUBTYPE_MASK     = 0x3C
 
} RailTileSubtype;
 

	
 
/**
 
 * Returns the RailTileSubtype of a given rail tile with type
 
 * RAIL_TYPE_DEPOT_WAYPOINT
 
 * RAIL_TILE_DEPOT_WAYPOINT
 
 */
 
static inline RailTileSubtype GetRailTileSubtype(TileIndex tile)
 
{
 
	assert(GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT);
 
	assert(GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT);
 
	return (RailTileSubtype)(_m[tile].m5 & RAIL_SUBTYPE_MASK);
 
}
 

	
 

	
 
typedef enum RailTypes {
 
	RAILTYPE_RAIL     = 0,
 
	RAILTYPE_ELECTRIC = 1,
 
	RAILTYPE_MONO     = 2,
 
	RAILTYPE_MAGLEV   = 3,
 
	RAILTYPE_END,
 
	INVALID_RAILTYPE = 0xFF
 
} RailType;
 

	
 
typedef byte RailTypeMask;
 

	
 
static inline RailType GetRailType(TileIndex t)
 
{
 
	return (RailType)GB(_m[t].m3, 0, 4);
 
}
 

	
 
// TODO remove this by moving to the same bits as GetRailType()
 
static inline RailType GetRailTypeCrossing(TileIndex t)
 
{
 
	return (RailType)GB(_m[t].m4, 0, 4);
 
}
 

	
 
static inline RailType GetRailTypeOnBridge(TileIndex t)
 
{
 
	return (RailType)GB(_m[t].m3, 4, 4);
 
}
 

	
 
static inline void SetRailType(TileIndex t, RailType r)
 
{
 
	SB(_m[t].m3, 0, 4, r);
 
}
 

	
 
// TODO remove this by moving to the same bits as SetRailType()
 
static inline void SetRailTypeCrossing(TileIndex t, RailType r)
 
{
 
	SB(_m[t].m4, 0, 4, r);
 
}
 

	
 
static inline void SetRailTypeOnBridge(TileIndex t, RailType r)
 
{
 
	SB(_m[t].m3, 4, 4, r);
 
}
 

	
 

	
 
@@ -156,192 +156,192 @@ static inline bool HasTrack(TileIndex ti
 
}
 

	
 

	
 
static inline DiagDirection GetRailDepotDirection(TileIndex t)
 
{
 
	return (DiagDirection)GB(_m[t].m5, 0, 2);
 
}
 

	
 
static inline Track GetRailWaypointTrack(TileIndex t)
 
{
 
	return HASBIT(_m[t].m5, 0) ? TRACK_Y : TRACK_X;
 
}
 

	
 
static inline TrackBits GetRailWaypointBits(TileIndex t)
 
{
 
	return _m[t].m5 & 1 ? TRACK_BIT_Y : TRACK_BIT_X;
 
}
 

	
 
static inline void SetCustomWaypointSprite(TileIndex t)
 
{
 
	SETBIT(_m[t].m3, 4);
 
}
 

	
 
static inline void ClearCustomWaypointSprite(TileIndex t)
 
{
 
	CLRBIT(_m[t].m3, 4);
 
}
 

	
 
static inline bool IsCustomWaypoint(TileIndex t)
 
{
 
	return HASBIT(_m[t].m3, 4);
 
}
 

	
 
static inline Axis GetWaypointAxis(TileIndex t)
 
{
 
	return HASBIT(_m[t].m5, 0) ? AXIS_Y : AXIS_X;
 
}
 

	
 

	
 
typedef enum SignalType {
 
	SIGTYPE_NORMAL  = 0, // normal signal
 
	SIGTYPE_ENTRY   = 1, // presignal block entry
 
	SIGTYPE_EXIT    = 2, // presignal block exit
 
	SIGTYPE_COMBO   = 3  // presignal inter-block
 
} SignalType;
 

	
 
static inline SignalType GetSignalType(TileIndex t)
 
{
 
	assert(GetRailTileType(t) == RAIL_TYPE_SIGNALS);
 
	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
 
	return (SignalType)GB(_m[t].m4, 0, 2);
 
}
 

	
 
static inline void SetSignalType(TileIndex t, SignalType s)
 
{
 
	assert(GetRailTileType(t) == RAIL_TYPE_SIGNALS);
 
	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
 
	SB(_m[t].m4, 0, 2, s);
 
}
 

	
 
static inline bool IsPresignalEntry(TileIndex t)
 
{
 
	return GetSignalType(t) == SIGTYPE_ENTRY || GetSignalType(t) == SIGTYPE_COMBO;
 
}
 

	
 
static inline bool IsPresignalExit(TileIndex t)
 
{
 
	return GetSignalType(t) == SIGTYPE_EXIT || GetSignalType(t) == SIGTYPE_COMBO;
 
}
 

	
 
static inline void CycleSignalSide(TileIndex t, Track track)
 
{
 
	byte sig;
 
	byte pos = 6;
 
	if (track == TRACK_LOWER || track == TRACK_RIGHT) pos = 4;
 

	
 
	sig = GB(_m[t].m3, pos, 2);
 
	if (--sig == 0) sig = 3;
 
	SB(_m[t].m3, pos, 2, sig);
 
}
 

	
 

	
 
typedef enum SignalVariant {
 
	SIG_ELECTRIC  = 0,
 
	SIG_SEMAPHORE = 1
 
} SignalVariant;
 

	
 
static inline SignalVariant GetSignalVariant(TileIndex t)
 
{
 
	return (SignalVariant)GB(_m[t].m4, 2, 1);
 
}
 

	
 
static inline void SetSignalVariant(TileIndex t, SignalVariant v)
 
{
 
	SB(_m[t].m4, 2, 1, v);
 
}
 

	
 
static inline bool IsSignalPresent(TileIndex t, byte signalbit)
 
{
 
	return HASBIT(_m[t].m3, signalbit + 4);
 
}
 

	
 
/** These are states in which a signal can be. Currently these are only two, so
 
 * simple boolean logic will do. But do try to compare to this enum instead of
 
 * normal boolean evaluation, since that will make future additions easier.
 
 */
 
typedef enum SignalStates {
 
	SIGNAL_STATE_RED = 0,
 
	SIGNAL_STATE_GREEN = 1,
 
} SignalState;
 

	
 
static inline SignalState GetSingleSignalState(TileIndex t, byte signalbit)
 
{
 
	return HASBIT(_m[t].m2, signalbit + 4);
 
}
 

	
 

	
 
typedef enum RailGroundType {
 
	RAIL_MAP2LO_GROUND_MASK = 0xF,
 
	RAIL_GROUND_BARREN = 0,
 
	RAIL_GROUND_GRASS = 1,
 
	RAIL_GROUND_FENCE_NW = 2,
 
	RAIL_GROUND_FENCE_SE = 3,
 
	RAIL_GROUND_FENCE_SENW = 4,
 
	RAIL_GROUND_FENCE_NE = 5,
 
	RAIL_GROUND_FENCE_SW = 6,
 
	RAIL_GROUND_FENCE_NESW = 7,
 
	RAIL_GROUND_FENCE_VERT1 = 8,
 
	RAIL_GROUND_FENCE_VERT2 = 9,
 
	RAIL_GROUND_FENCE_HORIZ1 = 10,
 
	RAIL_GROUND_FENCE_HORIZ2 = 11,
 
	RAIL_GROUND_ICE_DESERT = 12,
 
} RailGroundType;
 

	
 
static inline void SetRailGroundType(TileIndex t, RailGroundType rgt)
 
{
 
	if (GetRailTileType(t) == RAIL_TYPE_DEPOT_WAYPOINT) {
 
	if (GetRailTileType(t) == RAIL_TILE_DEPOT_WAYPOINT) {
 
		SB(_m[t].m4, 0, 4, rgt);
 
		return;
 
	}
 
	SB(_m[t].m2, 0, 4, rgt);
 
}
 

	
 
static inline RailGroundType GetRailGroundType(TileIndex t)
 
{
 
	/* TODO Unify this */
 
	if (GetRailTileType(t) == RAIL_TYPE_DEPOT_WAYPOINT) return GB(_m[t].m4, 0, 4);
 
	if (GetRailTileType(t) == RAIL_TILE_DEPOT_WAYPOINT) return GB(_m[t].m4, 0, 4);
 
	return GB(_m[t].m2, 0, 4);
 
}
 

	
 
static inline bool IsBarrenRailGround(TileIndex t)
 
{
 
	return GetRailGroundType(t) == RAIL_GROUND_BARREN;
 
}
 

	
 
static inline bool IsSnowRailGround(TileIndex t)
 
{
 
	return GetRailGroundType(t) == RAIL_GROUND_ICE_DESERT;
 
}
 

	
 

	
 
static inline void MakeRailNormal(TileIndex t, Owner o, TrackBits b, RailType r)
 
{
 
	SetTileType(t, MP_RAILWAY);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = r;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = RAIL_TYPE_NORMAL | b;
 
	_m[t].m5 = RAIL_TILE_NORMAL | b;
 
}
 

	
 

	
 
static inline void MakeRailDepot(TileIndex t, Owner o, DiagDirection d, RailType r)
 
{
 
	SetTileType(t, MP_RAILWAY);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = r;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = RAIL_TYPE_DEPOT_WAYPOINT | RAIL_SUBTYPE_DEPOT | d;
 
	_m[t].m5 = RAIL_TILE_DEPOT_WAYPOINT | RAIL_SUBTYPE_DEPOT | d;
 
}
 

	
 

	
 
static inline void MakeRailWaypoint(TileIndex t, Owner o, Axis a, RailType r, uint index)
 
{
 
	SetTileType(t, MP_RAILWAY);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = index;
 
	_m[t].m3 = r;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = RAIL_TYPE_DEPOT_WAYPOINT | RAIL_SUBTYPE_WAYPOINT | a;
 
	_m[t].m5 = RAIL_TILE_DEPOT_WAYPOINT | RAIL_SUBTYPE_WAYPOINT | a;
 
}
 

	
 
#endif
road_cmd.c
Show inline comments
 
@@ -278,97 +278,97 @@ int32 CmdBuildRoad(TileIndex tile, uint3
 
	Slope tileh;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
 
	 * if a non-player is building the road */
 
	if ((p1 >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR;
 
	pieces = p1;
 

	
 
	tileh = GetTileSlope(tile, NULL);
 

	
 
	switch (GetTileType(tile)) {
 
		case MP_STREET:
 
			switch (GetRoadType(tile)) {
 
				case ROAD_NORMAL:
 
					existing = GetRoadBits(tile);
 
					if ((existing & pieces) == pieces) {
 
						return_cmd_error(STR_1007_ALREADY_BUILT);
 
					}
 
					if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 
					break;
 

	
 
				case ROAD_CROSSING:
 
					if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct?
 
						return_cmd_error(STR_1007_ALREADY_BUILT);
 
					}
 
					goto do_clear;
 

	
 
				default:
 
				case ROAD_DEPOT:
 
					goto do_clear;
 
			}
 
			break;
 

	
 
		case MP_RAILWAY: {
 
			Axis roaddir;
 

	
 
			if (IsSteepSlope(tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 

	
 
#define M(x) (1 << (x))
 
			/* Level crossings may only be built on these slopes */
 
			if (!HASBIT(M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT), tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 
#undef M
 

	
 
			if (GetRailTileType(tile) != RAIL_TYPE_NORMAL) goto do_clear;
 
			if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear;
 
			switch (GetTrackBits(tile)) {
 
				case TRACK_BIT_X:
 
					if (pieces & ROAD_X) goto do_clear;
 
					roaddir = AXIS_Y;
 
					break;
 

	
 
				case TRACK_BIT_Y:
 
					if (pieces & ROAD_Y) goto do_clear;
 
					roaddir = AXIS_X;
 
					break;
 

	
 
				default: goto do_clear;
 
			}
 

	
 
			if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
			if (flags & DC_EXEC) {
 
				MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2);
 
				MarkTileDirtyByTile(tile);
 
			}
 
			return _price.build_road * 2;
 
		}
 

	
 
		case MP_TUNNELBRIDGE:
 
			/* check for flat land */
 
			if (IsSteepSlope(tileh)) {
 
				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
			}
 

	
 
			if (!IsBridge(tile) || !IsBridgeMiddle(tile)) goto do_clear;
 

	
 
			/* only allow roads pertendicular to bridge */
 
			if ((pieces & (GetBridgeAxis(tile) == AXIS_X ? ROAD_X : ROAD_Y)) != 0) {
 
				goto do_clear;
 
			}
 

	
 
			/* check if clear land under bridge */
 
			if (IsTransportUnderBridge(tile)) {
 
				switch (GetTransportTypeUnderBridge(tile)) {
 
					case TRANSPORT_ROAD: return_cmd_error(STR_1007_ALREADY_BUILT);
 
					default: return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
 
				}
 
			} else {
 
				if (IsWaterUnderBridge(tile)) {
 
					return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 
				}
 
			}
 

	
train_cmd.c
Show inline comments
 
@@ -1774,97 +1774,97 @@ int32 CmdRefitRailVehicle(TileIndex tile
 
				switch (old_cid) {
 
					case CT_PASSENGERS: break;
 
					case CT_MAIL:
 
					case CT_GOODS: amount *= 2; break;
 
					default:       amount *= 4; break;
 
				}
 
				switch (new_cid) {
 
					case CT_PASSENGERS: break;
 
					case CT_MAIL:
 
					case CT_GOODS: amount /= 2; break;
 
					default:       amount /= 4; break;
 
				}
 
			};
 

	
 
			if (amount != 0) {
 
				if (new_cid != v->cargo_type) cost += _price.build_railvehicle >> 8;
 
				num += amount;
 
				if (flags & DC_EXEC) {
 
					v->cargo_count = 0;
 
					v->cargo_type = new_cid;
 
					v->cargo_cap = amount;
 
					InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
					InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
				}
 
			}
 
		}
 
	} while ((v = v->next) != NULL);
 

	
 
	_returned_refit_capacity = num;
 

	
 
	return cost;
 
}
 

	
 
typedef struct TrainFindDepotData {
 
	uint best_length;
 
	TileIndex tile;
 
	PlayerID owner;
 
	/**
 
	 * true if reversing is necessary for the train to get to this depot
 
	 * This value is unused when new depot finding and NPF are both disabled
 
	 */
 
	bool reverse;
 
} TrainFindDepotData;
 

	
 
static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
 
{
 
	if (IsTileType(tile, MP_RAILWAY) &&
 
			IsTileOwner(tile, tfdd->owner) &&
 
			GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT &&
 
			GetRailTileType(tile) == RAIL_TILE_DEPOT_WAYPOINT &&
 
			GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT) {
 
		tfdd->best_length = length;
 
		tfdd->tile = tile;
 
		return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
// returns the tile of a depot to goto to. The given vehicle must not be
 
// crashed!
 
static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
 
{
 
	TrainFindDepotData tfdd;
 
	TileIndex tile = v->tile;
 

	
 
	assert(!(v->vehstatus & VS_CRASHED));
 

	
 
	tfdd.owner = v->owner;
 
	tfdd.best_length = (uint)-1;
 
	tfdd.reverse = false;
 

	
 
	if (IsTileDepotType(tile, TRANSPORT_RAIL)){
 
		tfdd.tile = tile;
 
		tfdd.best_length = 0;
 
		return tfdd;
 
	}
 

	
 
	if (v->u.rail.track == 0x40) tile = GetVehicleOutOfTunnelTile(v);
 

	
 
	if (_patches.new_pathfinding_all) {
 
		NPFFoundTargetData ftd;
 
		Vehicle* last = GetLastVehicleInChain(v);
 
		Trackdir trackdir = GetVehicleTrackdir(v);
 
		Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
 

	
 
		assert (trackdir != INVALID_TRACKDIR);
 
		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
 
		if (ftd.best_bird_dist == 0) {
 
			/* Found target */
 
			tfdd.tile = ftd.node.tile;
 
			/* Our caller expects a number of tiles, so we just approximate that
 
			* number by this. It might not be completely what we want, but it will
 
			* work for now :-) We can possibly change this when the old pathfinder
 
			* is removed. */
 
			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
 
			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
 
		}
 
@@ -2655,97 +2655,97 @@ typedef struct {
 

	
 
static const RailtypeSlowdownParams _railtype_slowdown[] = {
 
	// normal accel
 
	{256/4, 256/2, 256/4, 2}, // normal
 
	{256/4, 256/2, 256/4, 2}, // electrified
 
	{256/4, 256/2, 256/4, 2}, // monorail
 
	{0,     256/2, 256/4, 2}, // maglev
 
};
 

	
 
/* Modify the speed of the vehicle due to a turn */
 
static void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
 
{
 
	DirDiff diff;
 
	const RailtypeSlowdownParams *rsp;
 

	
 
	if (_patches.realistic_acceleration) return;
 

	
 
	diff = DirDifference(v->direction, new_dir);
 
	if (diff == DIRDIFF_SAME) return;
 

	
 
	rsp = &_railtype_slowdown[v->u.rail.railtype];
 
	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
 
}
 

	
 
/* Modify the speed of the vehicle due to a change in altitude */
 
static void AffectSpeedByZChange(Vehicle *v, byte old_z)
 
{
 
	const RailtypeSlowdownParams *rsp;
 
	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
 

	
 
	rsp = &_railtype_slowdown[v->u.rail.railtype];
 

	
 
	if (old_z < v->z_pos) {
 
		v->cur_speed -= (v->cur_speed * rsp->z_up >> 8);
 
	} else {
 
		uint16 spd = v->cur_speed + rsp->z_down;
 
		if (spd <= v->max_speed) v->cur_speed = spd;
 
	}
 
}
 

	
 
static const DiagDirection _otherside_signal_directions[] = {
 
	DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE, 0, 0,
 
	DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
 
};
 

	
 
static void TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
 
{
 
	if (IsTileType(tile, MP_RAILWAY) &&
 
			GetRailTileType(tile) == RAIL_TYPE_SIGNALS) {
 
			GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
 
		uint i = FindFirstBit2x64(GetTrackBits(tile) * 0x101 & _reachable_tracks[dir]);
 
		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
 
	}
 
}
 

	
 

	
 
typedef struct TrainCollideChecker {
 
	const Vehicle *v;
 
	const Vehicle *v_skip;
 
} TrainCollideChecker;
 

	
 
static void *FindTrainCollideEnum(Vehicle *v, void *data)
 
{
 
	const TrainCollideChecker* tcc = data;
 

	
 
	if (v != tcc->v &&
 
			v != tcc->v_skip &&
 
			v->type == VEH_Train &&
 
			v->u.rail.track != 0x80 &&
 
			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
 
			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
 
			myabs(v->y_pos - tcc->v->y_pos) < 6) {
 
		return v;
 
	} else {
 
		return NULL;
 
	}
 
}
 

	
 
static void SetVehicleCrashed(Vehicle *v)
 
{
 
	Vehicle *u;
 

	
 
	if (v->u.rail.crash_anim_pos != 0) return;
 

	
 
	v->u.rail.crash_anim_pos++;
 

	
 
	u = v;
 
	BEGIN_ENUM_WAGONS(v)
 
		v->vehstatus |= VS_CRASHED;
 
	END_ENUM_WAGONS(v)
 

	
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, u->index, STATUS_BAR);
 
}
 

	
 
static uint CountPassengersInTrain(const Vehicle* v)
 
{
 
	uint num = 0;
 
	BEGIN_ENUM_WAGONS(v)
tunnelbridge_cmd.c
Show inline comments
 
@@ -289,97 +289,97 @@ int32 CmdBuildBridge(TileIndex end_tile,
 

	
 
	// false - end tile slope check
 
	terraformcost = CheckBridgeSlope(direction, tileh_end, false);
 
	if (CmdFailed(terraformcost) || (terraformcost && !allow_on_slopes))
 
		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
	cost += terraformcost;
 

	
 

	
 
	/* do the drill? */
 
	if (flags & DC_EXEC) {
 
		DiagDirection dir = AxisToDiagDir(direction);
 

	
 
		if (transport == TRANSPORT_RAIL) {
 
			MakeRailBridgeRamp(tile_start, _current_player, bridge_type, dir, railtype);
 
			MakeRailBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir), railtype);
 
		} else {
 
			MakeRoadBridgeRamp(tile_start, _current_player, bridge_type, dir);
 
			MakeRoadBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir));
 
		}
 
		MarkTileDirtyByTile(tile_start);
 
		MarkTileDirtyByTile(tile_end);
 
	}
 

	
 
	// position of middle part of the odd bridge (larger than MAX(i) otherwise)
 
	odd_middle_part = (bridge_len % 2) ? (bridge_len / 2) : bridge_len;
 

	
 
	tile = tile_start;
 
	delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
 
	for (i = 0; i != bridge_len; i++) {
 
		TransportType transport_under;
 
		Owner owner_under = OWNER_NONE;
 
		RailType rail_under = INVALID_RAILTYPE;
 
		uint z;
 

	
 
		tile += delta;
 

	
 
		if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) {
 
			return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
 
		}
 

	
 
		switch (GetTileType(tile)) {
 
			case MP_WATER:
 
				if (!EnsureNoVehicle(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY);
 
				if (!(IsWater(tile) || IsCoast(tile))) goto not_valid_below;
 
				transport_under = TRANSPORT_WATER;
 
				break;
 

	
 
			case MP_RAILWAY:
 
				if (GetRailTileType(tile) != RAIL_TYPE_NORMAL ||
 
				if (GetRailTileType(tile) != RAIL_TILE_NORMAL ||
 
						GetTrackBits(tile) != (direction == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X)) {
 
					goto not_valid_below;
 
				}
 
				transport_under = TRANSPORT_RAIL;
 
				owner_under = GetTileOwner(tile);
 
				rail_under = GetRailType(tile);
 
				break;
 

	
 
			case MP_STREET:
 
				if (GetRoadType(tile) != ROAD_NORMAL ||
 
						GetRoadBits(tile) != (direction == AXIS_X ? ROAD_Y : ROAD_X)) {
 
					goto not_valid_below;
 
				}
 
				transport_under = TRANSPORT_ROAD;
 
				owner_under = GetTileOwner(tile);
 
				break;
 

	
 
			default:
 
not_valid_below:;
 
				/* try and clear the middle landscape */
 
				ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
				if (CmdFailed(ret)) return ret;
 
				cost += ret;
 
				transport_under = INVALID_TRANSPORT;
 
				break;
 
		}
 

	
 
		if (flags & DC_EXEC) {
 
			uint piece;
 

	
 
			//bridges pieces sequence (middle parts)
 
			// bridge len 1: 0
 
			// bridge len 2: 0 1
 
			// bridge len 3: 0 4 1
 
			// bridge len 4: 0 2 3 1
 
			// bridge len 5: 0 2 5 3 1
 
			// bridge len 6: 0 2 3 2 3 1
 
			// bridge len 7: 0 2 3 4 2 3 1
 
			// #0 - always as first, #1 - always as last (if len>1)
 
			// #2,#3 are to pair in order
 
			// for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
 

	
 
			if (i == 0) { // first tile
 
				piece = 0;
 
			} else if (i == bridge_len - 1) { // last tile
 
				piece = 1;
 
			} else if (i == odd_middle_part) { // we are on the middle of odd bridge: #5 on even pos, #4 on odd
 
				piece = 5 - (i % 2);
waypoint.c
Show inline comments
 
@@ -137,97 +137,97 @@ static Waypoint *FindDeletedWaypointClos
 

	
 
	return best;
 
}
 

	
 
/**
 
 * Update waypoint graphics id against saved GRFID/localidx.
 
 * This is to ensure the chosen graphics are correct if GRF files are changed.
 
 */
 
void UpdateAllWaypointCustomGraphics(void)
 
{
 
	Waypoint *wp;
 

	
 
	FOR_ALL_WAYPOINTS(wp) {
 
		uint i;
 

	
 
		if (wp->grfid == 0) continue;
 

	
 
		for (i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
 
			const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
 
			if (statspec != NULL && statspec->grfid == wp->grfid && statspec->localidx == wp->localidx) {
 
				wp->stat_id = i;
 
				break;
 
			}
 
		}
 
	}
 
}
 

	
 
/** Convert existing rail to waypoint. Eg build a waypoint station over
 
 * piece of rail
 
 * @param tile tile where waypoint will be built
 
 * @param p1 graphics for waypoint type, 0 indicates standard graphics
 
 * @param p2 unused
 
 *
 
 * @todo When checking for the tile slope,
 
 * distingush between "Flat land required" and "land sloped in wrong direction"
 
 */
 
int32 CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Waypoint *wp;
 
	Slope tileh;
 
	Axis axis;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	/* if custom gfx are used, make sure it is within bounds */
 
	if (p1 >= GetNumCustomStations(STAT_CLASS_WAYP)) return CMD_ERROR;
 

	
 
	if (!IsTileType(tile, MP_RAILWAY) ||
 
			GetRailTileType(tile) != RAIL_TYPE_NORMAL || (
 
			GetRailTileType(tile) != RAIL_TILE_NORMAL || (
 
				(axis = AXIS_X, GetTrackBits(tile) != TRACK_BIT_X) &&
 
				(axis = AXIS_Y, GetTrackBits(tile) != TRACK_BIT_Y)
 
			)) {
 
		return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
 
	}
 

	
 
	if (!CheckTileOwnership(tile))
 
		return CMD_ERROR;
 

	
 
	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
	tileh = GetTileSlope(tile, NULL);
 
	if (tileh != SLOPE_FLAT) {
 
		if (!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))
 
			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 
	}
 

	
 
	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
 
	wp = FindDeletedWaypointCloseTo(tile);
 
	if (wp == NULL) {
 
		wp = AllocateWaypoint();
 
		if (wp == NULL) return CMD_ERROR;
 

	
 
		wp->town_index = 0;
 
		wp->string = STR_NULL;
 
		wp->town_cn = 0;
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		const StationSpec *statspec = NULL;
 
		MakeRailWaypoint(tile, GetTileOwner(tile), axis, GetRailType(tile), wp->index);
 
		MarkTileDirtyByTile(tile);
 

	
 
		if (GB(p1, 0, 8) < GetNumCustomStations(STAT_CLASS_WAYP))
 
			statspec = GetCustomStationSpec(STAT_CLASS_WAYP, GB(p1, 0, 8));
 

	
 
		if (statspec != NULL) {
 
			SetCustomWaypointSprite(tile);
 
			wp->stat_id = GB(p1, 0, 8);
 
			wp->grfid = statspec->grfid;
 
			wp->localidx = statspec->localidx;
 
		} else {
 
			// Specified custom graphics do not exist, so use default.
 
			ClearCustomWaypointSprite(tile);
 
			wp->stat_id = 0;
 
			wp->grfid = 0;
 
			wp->localidx = 0;
 
		}
waypoint.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef WAYPOINT_H
 
#define WAYPOINT_H
 

	
 
#include "pool.h"
 
#include "rail_map.h"
 

	
 
struct Waypoint {
 
	TileIndex xy;      ///< Tile of waypoint
 
	StationID index;   ///< Index of waypoint
 

	
 
	TownID town_index; ///< Town associated with the waypoint
 
	byte town_cn;      ///< The Nth waypoint for this town (consecutive number)
 
	StringID string;   ///< If this is zero (i.e. no custom name), town + town_cn is used for naming
 

	
 
	ViewportSign sign; ///< Dimensions of sign (not saved)
 
	uint16 build_date; ///< Date of construction
 

	
 
	byte stat_id;      ///< ID of waypoint within the waypoint class (not saved)
 
	uint32 grfid;      ///< ID of GRF file
 
	byte localidx;     ///< Index of station within GRF file
 

	
 
	byte deleted;      ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted.
 
};
 

	
 
enum {
 
	RAIL_TYPE_WAYPOINT = 0xC4,
 
	RAIL_TILE_WAYPOINT = 0xC4,
 
	RAIL_WAYPOINT_TRACK_MASK = 1,
 
};
 

	
 
extern MemoryPool _waypoint_pool;
 

	
 
/**
 
 * Get the pointer to the waypoint with index 'index'
 
 */
 
static inline Waypoint *GetWaypoint(uint index)
 
{
 
	return (Waypoint*)GetItemFromPool(&_waypoint_pool, index);
 
}
 

	
 
/**
 
 * Get the current size of the WaypointPool
 
 */
 
static inline uint16 GetWaypointPoolSize(void)
 
{
 
	return _waypoint_pool.total_items;
 
}
 

	
 
static inline bool IsWaypointIndex(uint index)
 
{
 
	return index < GetWaypointPoolSize();
 
}
 

	
 
#define FOR_ALL_WAYPOINTS_FROM(wp, start) for (wp = GetWaypoint(start); wp != NULL; wp = (wp->index + 1 < GetWaypointPoolSize()) ? GetWaypoint(wp->index + 1) : NULL)
 
#define FOR_ALL_WAYPOINTS(wp) FOR_ALL_WAYPOINTS_FROM(wp, 0)
 

	
 
static inline bool IsRailWaypoint(TileIndex tile)
 
{
 
	return (_m[tile].m5 & 0xFC) == 0xC4;
 
}
 

	
 
/**
 
 * Fetch a waypoint by tile
 
 * @param tile Tile of waypoint
 
 * @return Waypoint
 
 */
 
static inline Waypoint *GetWaypointByTile(TileIndex tile)
 
{
 
	assert(IsTileType(tile, MP_RAILWAY) && IsRailWaypoint(tile));
 
	return GetWaypoint(_m[tile].m2);
 
}
 

	
 
int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove);
 
Station *ComposeWaypointStation(TileIndex tile);
 
void ShowRenameWaypointWindow(const Waypoint *cp);
0 comments (0 inline, 0 general)