Changeset - r12462:a7cb564c6c56
[Not reviewed]
master
0 40 0
rubidium - 15 years ago 2009-07-22 08:59:57
rubidium@openttd.org
(svn r16909) -Fix [FS#2996]: NewGRF stations would be triggering assertions all over the place when using the more advanced station types.
-Change: make (rail) waypoints sub classes of 'base stations', make buoys waypoints and unify code between them where possible.
40 files changed with 697 insertions and 701 deletions:
0 comments (0 inline, 0 general)
src/ai/api/ai_buoylist.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/** @file ai_buoylist.cpp Implementation of AIBuoyList and friends. */
 

	
 
#include "ai_buoylist.hpp"
 
#include "../../station_base.h"
 
#include "../../waypoint.h"
 

	
 
AIBuoyList::AIBuoyList()
 
{
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		if (st->IsBuoy()) this->AddItem(st->xy);
 
	Waypoint *wp;
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->facilities & FACIL_DOCK) this->AddItem(wp->xy);
 
	}
 
}
src/ai/api/ai_order.cpp
Show inline comments
 
@@ -22,24 +22,20 @@ static OrderType GetOrderTypeByTile(Tile
 
{
 
	if (!::IsValidTile(t)) return OT_END;
 

	
 
	switch (::GetTileType(t)) {
 
		default: break;
 
		case MP_STATION:
 
			if (IsBuoy(t) || IsRailWaypoint(t)) return OT_GOTO_WAYPOINT;
 
			if (IsHangar(t)) return OT_GOTO_DEPOT;
 
			if (IsBuoy(t)) return OT_GOTO_WAYPOINT;
 
			return OT_GOTO_STATION;
 
			break;
 
		case MP_WATER:   if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
 
		case MP_ROAD:    if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
 
		case MP_RAILWAY:
 
			switch (::GetRailTileType(t)) {
 
				case RAIL_TILE_DEPOT:    return OT_GOTO_DEPOT;
 
				case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT;
 
				default: break;
 
			}
 
			if (IsRailDepot(t)) return OT_GOTO_DEPOT;
 
			break;
 
	}
 

	
 
	return OT_END;
 
}
 

	
 
@@ -356,13 +352,13 @@ static const Order *ResolveOrder(Vehicle
 
			order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
 
			order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
 
			order.SetStopLocation(OSL_PLATFORM_FAR_END);
 
			break;
 

	
 
		case OT_GOTO_WAYPOINT:
 
			order.MakeGoToWaypoint(::Vehicle::Get(vehicle_id)->type == VEH_TRAIN ? ::GetWaypointIndex(destination) : ::GetStationIndex(destination));
 
			order.MakeGoToWaypoint(::GetStationIndex(destination));
 
			break;
 

	
 
		default:
 
			return false;
 
	}
 

	
src/ai/api/ai_rail.cpp
Show inline comments
 
@@ -42,13 +42,13 @@
 
}
 

	
 
/* static */ bool AIRail::IsRailWaypointTile(TileIndex tile)
 
{
 
	if (!::IsValidTile(tile)) return false;
 

	
 
	return ::IsTileType(tile, MP_RAILWAY) && ::IsRailWaypointTile(tile);
 
	return ::IsRailWaypointTile(tile);
 
}
 

	
 
/* static */ bool AIRail::IsRailTypeAvailable(RailType rail_type)
 
{
 
	if ((::RailType)rail_type < RAILTYPE_BEGIN || (::RailType)rail_type >= RAILTYPE_END) return false;
 

	
 
@@ -197,14 +197,13 @@
 
}
 

	
 
/* static */ uint AIRail::GetRailTracks(TileIndex tile)
 
{
 
	if (!IsRailTile(tile)) return RAILTRACK_INVALID;
 

	
 
	if (IsRailWaypointTile(tile)) return ::GetRailWaypointBits(tile);
 
	if (IsRailStationTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
 
	if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
 
	if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile);
 
	if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE;
 
	return ::GetTrackBits(tile);
 
}
 

	
 
/* static */ bool AIRail::BuildRailTrack(TileIndex tile, RailTrack rail_track)
src/ai/api/ai_waypoint.cpp
Show inline comments
 
@@ -19,13 +19,13 @@
 
}
 

	
 
/* static */ WaypointID AIWaypoint::GetWaypointID(TileIndex tile)
 
{
 
	if (!AIRail::IsRailWaypointTile(tile)) return WAYPOINT_INVALID;
 

	
 
	return ::GetWaypointIndex(tile);
 
	return ::GetStationIndex(tile);
 
}
 

	
 
/* static */ char *AIWaypoint::GetName(WaypointID waypoint_id)
 
{
 
	if (!IsValidWaypoint(waypoint_id)) return NULL;
 

	
src/ai/api/ai_waypointlist.cpp
Show inline comments
 
@@ -10,13 +10,13 @@
 
#include "../../waypoint.h"
 

	
 
AIWaypointList::AIWaypointList()
 
{
 
	const Waypoint *wp;
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->owner == _current_company) this->AddItem(wp->index);
 
		if (wp->facilities & FACIL_TRAIN && wp->owner == _current_company) this->AddItem(wp->index);
 
	}
 
}
 

	
 
AIWaypointList_Vehicle::AIWaypointList_Vehicle(VehicleID vehicle_id)
 
{
 
	if (!AIVehicle::IsValidVehicle(vehicle_id)) return;
src/date.cpp
Show inline comments
 
@@ -151,13 +151,12 @@ Date ConvertYMDToDate(Year year, Month m
 

	
 
	return year * DAYS_IN_YEAR + nr_of_leap_years + days;
 
}
 

	
 
/** Functions used by the IncreaseDate function */
 

	
 
extern void WaypointsDailyLoop();
 
extern void EnginesDailyLoop();
 
extern void DisasterDailyLoop();
 
extern void IndustryDailyLoop();
 
extern void CompaniesMonthlyLoop();
 
extern void EnginesMonthlyLoop();
 
extern void TownsMonthlyLoop();
 
@@ -219,13 +218,12 @@ void IncreaseDate()
 

	
 
#ifdef ENABLE_NETWORK
 
	NetworkChatMessageDailyLoop();
 
#endif /* ENABLE_NETWORK */
 

	
 
	DisasterDailyLoop();
 
	WaypointsDailyLoop();
 
	IndustryDailyLoop();
 

	
 
	if (_game_mode != GM_MENU) {
 
		InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
 
		EnginesDailyLoop();
 
	}
src/elrail.cpp
Show inline comments
 
@@ -78,14 +78,12 @@ static TrackBits GetRailTrackBitsUnivers
 
	switch (GetTileType(t)) {
 
		case MP_RAILWAY:
 
			if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
 
			switch (GetRailTileType(t)) {
 
				case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
 
					return GetTrackBits(t);
 
				case RAIL_TILE_WAYPOINT:
 
					return GetRailWaypointBits(t);
 
				default:
 
					return TRACK_BIT_NONE;
 
			}
 
			break;
 

	
 
		case MP_TUNNELBRIDGE:
 
@@ -98,13 +96,13 @@ static TrackBits GetRailTrackBitsUnivers
 
		case MP_ROAD:
 
			if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
 
			if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
 
			return GetCrossingRailBits(t);
 

	
 
		case MP_STATION:
 
			if (!IsRailwayStation(t)) return TRACK_BIT_NONE;
 
			if (!IsRailwayStation(t) && !IsRailWaypoint(t)) return TRACK_BIT_NONE;
 
			if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
 
			if (!IsStationTileElectrifiable(t)) return TRACK_BIT_NONE;
 
			return TrackToTrackBits(GetRailStationTrack(t));
 

	
 
		default:
 
			return TRACK_BIT_NONE;
src/lang/english.txt
Show inline comments
 
@@ -1182,14 +1182,16 @@ STR_CHEAT_SETUP_PROD                    
 
STR_HEADING_FOR_WAYPOINT                                        :{LTBLUE}Heading for {WAYPOINT}
 
STR_HEADING_FOR_WAYPOINT_VEL                                    :{LTBLUE}Heading for {WAYPOINT}, {VELOCITY}
 

	
 
STR_GO_TO_WAYPOINT                                              :Go via {WAYPOINT}
 
STR_GO_NON_STOP_TO_WAYPOINT                                     :Go non-stop via {WAYPOINT}
 

	
 
STR_WAYPOINTNAME_CITY                                           :Waypoint {TOWN}
 
STR_WAYPOINTNAME_CITY_SERIAL                                    :Waypoint {TOWN} #{COMMA}
 
STR_WAYPOINTNAME_CITY                                           :{TOWN} Waypoint
 
STR_WAYPOINTNAME_CITY_SERIAL                                    :{TOWN} Waypoint #{COMMA}
 
STR_BUOYNAME_CITY                                               :{TOWN} Buoy
 
STR_BUOYNAME_CITY_SERIAL                                        :{TOWN} Buoy #{COMMA}
 
STR_LANDINFO_WAYPOINT                                           :Waypoint
 

	
 
STR_WAYPOINT                                                    :{WHITE}Waypoint
 
STR_WAYPOINT_GRAPHICS_TIP                                       :{BLACK}Select waypoint type
 

	
 
STR_WAYPOINT_VIEWPORT                                           :{WHITE}{WAYPOINT}
 
@@ -2074,21 +2076,15 @@ STR_SV_STNAME_WOODS                     
 
STR_SV_STNAME_LAKESIDE                                          :{STRING1} Lakeside
 
STR_SV_STNAME_EXCHANGE                                          :{STRING1} Exchange
 
STR_SV_STNAME_AIRPORT                                           :{STRING1} Airport
 
STR_SV_STNAME_OILFIELD                                          :{STRING1} Oilfield
 
STR_SV_STNAME_MINES                                             :{STRING1} Mines
 
STR_SV_STNAME_DOCKS                                             :{STRING1} Docks
 
STR_SV_STNAME_BUOY_1                                            :{STRING1} Buoy 1
 
STR_SV_STNAME_BUOY_2                                            :{STRING1} Buoy 2
 
STR_SV_STNAME_BUOY_3                                            :{STRING1} Buoy 3
 
STR_SV_STNAME_BUOY_4                                            :{STRING1} Buoy 4
 
STR_SV_STNAME_BUOY_5                                            :{STRING1} Buoy 5
 
STR_SV_STNAME_BUOY_6                                            :{STRING1} Buoy 6
 
STR_SV_STNAME_BUOY_7                                            :{STRING1} Buoy 7
 
STR_SV_STNAME_BUOY_8                                            :{STRING1} Buoy 8
 
STR_SV_STNAME_BUOY_9                                            :{STRING1} Buoy 9
 
STR_SV_STNAME_BUOY                                              :{STRING2}
 
STR_SV_STNAME_WAYPOINT                                          :{STRING2}
 
##id 0x6020
 
STR_SV_STNAME_ANNEXE                                            :{STRING1} Annexe
 
STR_SV_STNAME_SIDINGS                                           :{STRING1} Sidings
 
STR_SV_STNAME_BRANCH                                            :{STRING1} Branch
 
STR_SV_STNAME_UPPER                                             :Upper {STRING1}
 
STR_SV_STNAME_LOWER                                             :Lower {STRING1}
 
STR_SV_STNAME_HELIPORT                                          :{STRING1} Heliport
src/misc.cpp
Show inline comments
 
@@ -28,13 +28,12 @@
 
#include "table/sprites.h"
 

	
 
extern TileIndex _cur_tileloop_tile;
 
extern void MakeNewgameSettingsLive();
 

	
 
void InitializeVehicles();
 
void InitializeWaypoints();
 
void InitializeDepots();
 
void InitializeEngineRenews();
 
void InitializeOrders();
 
void InitializeClearLand();
 
void InitializeRailGui();
 
void InitializeRoadGui();
 
@@ -76,13 +75,12 @@ void InitializeGame(uint size_x, uint si
 
		SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
 
		InitializeOldNames();
 
	}
 

	
 
	InitializeEngineRenews();
 
	InitializeVehicles();
 
	InitializeWaypoints();
 
	InitializeDepots();
 
	InitializeOrders();
 
	InitializeGroup();
 

	
 
	InitNewsItemStructs();
 
	InitializeLandscape();
src/newgrf_station.cpp
Show inline comments
 
@@ -269,36 +269,26 @@ uint32 GetPlatformInfo(Axis axis, byte t
 
/* 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);
 
	StationID sid = GetStationIndex(tile);
 

	
 
	if (waypoint) {
 
		if (check_axis) orig_axis = GetWaypointAxis(tile);
 
	} else {
 
		if (check_type) orig_type = GetCustomStationSpecIndex(tile);
 
		if (check_axis) orig_axis = GetRailStationAxis(tile);
 
	}
 
	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 (!IsRailWaypointTile(new_tile)) 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;
 
		}
 
		if (!IsTileType(new_tile, MP_STATION) || GetStationIndex(new_tile) != sid) break;
 
		if (!IsRailwayStation(new_tile) && !IsRailWaypoint(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;
 
}
 

	
 
@@ -308,18 +298,17 @@ static uint32 GetPlatformInfoHelper(Tile
 
	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);
 
	return GetPlatformInfo(GetRailStationAxis(tile), GetStationGfx(tile), ex, ey, tx, ty, centred);
 
}
 

	
 

	
 
static uint32 GetRailContinuationInfo(TileIndex tile)
 
{
 
	/* Tile offsets and exit dirs for X axis */
 
@@ -327,13 +316,13 @@ static uint32 GetRailContinuationInfo(Ti
 
	static const DiagDirection x_exits[8] = { DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SW, DIAGDIR_NE };
 

	
 
	/* Tile offsets and exit dirs for Y axis */
 
	static const Direction y_dir[8] = { DIR_SE, DIR_NW, DIR_SW, DIR_NE, DIR_S, DIR_W, DIR_E, DIR_N };
 
	static const DiagDirection y_exits[8] = { DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SE, DIAGDIR_NW };
 

	
 
	Axis axis = IsTileType(tile, MP_RAILWAY) ? GetWaypointAxis(tile) : GetRailStationAxis(tile);
 
	Axis axis = GetRailStationAxis(tile);
 

	
 
	/* Choose appropriate lookup table to use */
 
	const Direction *dir = axis == AXIS_X ? x_dir : y_dir;
 
	const DiagDirection *diagdir = axis == AXIS_X ? x_exits : y_exits;
 

	
 
	uint32 res = 0;
 
@@ -447,18 +436,13 @@ static uint32 StationGetVariable(const R
 
		case 0x41:
 
			if (!HasBit(_svc.valid, 1)) { _svc.v41 = GetPlatformInfoHelper(tile, true,  false, false); SetBit(_svc.valid, 1); }
 
			return _svc.v41;
 

	
 
		case 0x42: return GetTerrainType(tile) | (GetRailType(tile) << 8);
 
		case 0x43: return st->owner; // Station owner
 
		case 0x44:
 
			if (IsRailWaypointTile(tile)) {
 
				return HasDepotReservation(tile) ? 7 : 4;
 
			} else {
 
				return HasStationReservation(tile) ? 7 : 4; // PBS status
 
			}
 
		case 0x44: return HasStationReservation(tile) ? 7 : 4; // PBS status
 
		case 0x45:
 
			if (!HasBit(_svc.valid, 2)) { _svc.v45 = GetRailContinuationInfo(tile); SetBit(_svc.valid, 2); }
 
			return _svc.v45;
 

	
 
		case 0x46:
 
			if (!HasBit(_svc.valid, 3)) { _svc.v46 = GetPlatformInfoHelper(tile, false, false, true); SetBit(_svc.valid, 3); }
 
@@ -580,13 +564,13 @@ uint32 Station::GetNewGRFVariable(const 
 
}
 

	
 
uint32 Waypoint::GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const
 
{
 
	switch (variable) {
 
		case 0x48: return 0; // Accepted cargo types
 
		case 0x8A: return HVOT_TRAIN;
 
		case 0x8A: return HVOT_WAYPOINT;
 
		case 0xF1: return 0; // airport type
 
		case 0xF2: return 0; // truck stop status
 
		case 0xF3: return 0; // bus stop status
 
		case 0xF6: return 0; // airport flags
 
		case 0xF7: return 0; // airport flags cont.
 
	}
 
@@ -941,26 +925,17 @@ bool DrawStationTile(int x, int y, RailT
 
	return true;
 
}
 

	
 

	
 
const StationSpec *GetStationSpec(TileIndex t)
 
{
 
	if (IsRailwayStationTile(t)) {
 
		if (!IsCustomStationSpecIndex(t)) return NULL;
 
	if (!IsCustomStationSpecIndex(t)) return NULL;
 

	
 
		const BaseStation *st = BaseStation::GetByTile(t);
 
		uint specindex = GetCustomStationSpecIndex(t);
 
		return specindex < st->num_specs ? st->speclist[specindex].spec : NULL;
 
	}
 

	
 
	if (IsRailWaypointTile(t)) {
 
		const BaseStation *st = BaseStation::GetByTile(t);
 
		return st->num_specs != 0 ? st->speclist[1].spec : NULL;
 
	}
 

	
 
	return NULL;
 
	const BaseStation *st = BaseStation::GetByTile(t);
 
	uint specindex = GetCustomStationSpecIndex(t);
 
	return specindex < st->num_specs ? st->speclist[specindex].spec : NULL;
 
}
 

	
 

	
 
/* Check if a rail station tile is traversable.
 
 * XXX This could be cached (during build) in the map array to save on all the dereferencing */
 
bool IsStationTileBlocked(TileIndex tile)
src/order_cmd.cpp
Show inline comments
 
@@ -539,24 +539,25 @@ CommandCost CmdInsertOrder(TileIndex til
 
			if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
 
			if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
 
			break;
 
		}
 

	
 
		case OT_GOTO_WAYPOINT: {
 
			const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
 
			if (wp == NULL) return CMD_ERROR;
 

	
 
			switch (v->type) {
 
				default: return CMD_ERROR;
 

	
 
				case VEH_TRAIN: {
 
					const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
 
					if (wp == NULL || !CheckOwnership(wp->owner)) return CMD_ERROR;
 
				} break;
 
				case VEH_TRAIN:
 
					if (!CheckOwnership(wp->owner)) return CMD_ERROR;
 
					break;
 

	
 
				case VEH_SHIP: {
 
					const Station *st = Station::GetIfValid(new_order.GetDestination());
 
					if (st == NULL || (!CheckOwnership(st->owner) && st->owner != OWNER_NONE)) return CMD_ERROR;
 
				} break;
 
				case VEH_SHIP:
 
					if (!CheckOwnership(wp->owner) && wp->owner != OWNER_NONE) return CMD_ERROR;
 
					break;
 
			}
 

	
 
			/* Order flags can be any of the following for waypoints:
 
			 * [non-stop]
 
			 * non-stop orders (if any) are only valid for trains */
 
			if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
src/order_gui.cpp
Show inline comments
 
@@ -250,21 +250,14 @@ void DrawOrderString(const Vehicle *v, c
 
				SetDParam(6, (order->GetDepotActionType() & ODATFB_HALT) ? STR_REFIT_STOP_ORDER : STR_REFIT_ORDER);
 
				SetDParam(7, CargoSpec::Get(order->GetRefitCargo())->name);
 
			}
 
			break;
 

	
 
		case OT_GOTO_WAYPOINT:
 
			if (v->type == VEH_TRAIN) {
 
				SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
 
				SetDParam(2, order->GetDestination());
 
			} else {
 
				SetDParam(1, STR_GO_TO_STATION);
 
				SetDParam(2, STR_ORDER_GO_VIA);
 
				SetDParam(3, order->GetDestination());
 
				SetDParam(4, STR_EMPTY);
 
			}
 
			SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
 
			SetDParam(2, order->GetDestination());
 
			break;
 

	
 
		case OT_CONDITIONAL:
 
			SetDParam(2, order->GetConditionSkipToOrder() + 1);
 
			if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) {
 
				SetDParam(1, STR_CONDITIONAL_UNCONDITIONAL);
 
@@ -354,13 +347,13 @@ static Order GetOrderCmdFromTile(const V
 
			IsTileOwner(tile, _local_company)) {
 
		order.MakeGoToWaypoint(Waypoint::GetByTile(tile)->index);
 
		if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
 
		return order;
 
	}
 

	
 
	if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
 
	if ((IsBuoyTile(tile) && v->type == VEH_SHIP) || (IsRailWaypointTile(tile) && v->type == VEH_TRAIN)) {
 
		order.MakeGoToWaypoint(GetStationIndex(tile));
 
		return order;
 
	}
 

	
 
	if (IsTileType(tile, MP_STATION)) {
 
		StationID st_index = GetStationIndex(tile);
 
@@ -772,18 +765,15 @@ public:
 
		this->RaiseWidget(ORDER_WIDGET_SERVICE);
 

	
 
		if (order != NULL) {
 
			this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 
			switch (order->GetType()) {
 
				case OT_GOTO_STATION:
 
					if (!Station::Get(order->GetDestination())->IsBuoy()) {
 
						this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
 
						this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
 
						break;
 
					}
 
					/* Fall-through */
 
					this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
 
					this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
 
					break;
 

	
 
				case OT_GOTO_WAYPOINT:
 
					this->DisableWidget(ORDER_WIDGET_FULL_LOAD_DROPDOWN);
 
					this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 
					this->DisableWidget(ORDER_WIDGET_UNLOAD_DROPDOWN);
 
					this->DisableWidget(ORDER_WIDGET_UNLOAD);
src/pbs.cpp
Show inline comments
 
@@ -23,13 +23,13 @@ TrackBits GetReservedTrackbits(TileIndex
 

	
 
		case MP_ROAD:
 
			if (IsLevelCrossing(t)) return GetCrossingReservationTrackBits(t);
 
			break;
 

	
 
		case MP_STATION:
 
			if (IsRailwayStation(t)) return GetStationReservationTrackBits(t);
 
			if (IsRailwayStation(t) || IsRailWaypoint(t)) return GetStationReservationTrackBits(t);
 
			break;
 

	
 
		case MP_TUNNELBRIDGE:
 
			if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) return GetTunnelBridgeReservationTrackBits(t);
 
			break;
 

	
 
@@ -96,13 +96,13 @@ bool TryReserveRailTrack(TileIndex tile,
 
				MarkTileDirtyByTile(tile); // crossing barred, make tile dirty
 
				return true;
 
			}
 
			break;
 

	
 
		case MP_STATION:
 
			if (IsRailwayStation(tile) && !HasStationReservation(tile)) {
 
			if ((IsRailwayStation(tile) || IsRailWaypoint(tile)) && !HasStationReservation(tile)) {
 
				SetRailwayStationReservation(tile, true);
 
				MarkTileDirtyByTile(tile); // some GRFs need redraw after reserving track
 
				return true;
 
			}
 
			break;
 

	
 
@@ -147,13 +147,13 @@ bool TryReserveRailTrack(TileIndex tile,
 
				SetCrossingReservation(tile, false);
 
				UpdateLevelCrossing(tile);
 
			}
 
			break;
 

	
 
		case MP_STATION:
 
			if (IsRailwayStation(tile)) {
 
			if (IsRailwayStation(tile) || IsRailWaypoint(tile)) {
 
				SetRailwayStationReservation(tile, false);
 
				MarkTileDirtyByTile(tile);
 
			}
 
			break;
 

	
 
		case MP_TUNNELBRIDGE:
src/rail.cpp
Show inline comments
 
@@ -152,13 +152,13 @@ RailType GetTileRailType(TileIndex tile)
 
		case MP_ROAD:
 
			/* rail/road crossing */
 
			if (IsLevelCrossing(tile)) return GetRailType(tile);
 
			break;
 

	
 
		case MP_STATION:
 
			if (IsRailwayStationTile(tile)) return GetRailType(tile);
 
			if (IsRailwayStation(tile) || IsRailWaypoint(tile)) return GetRailType(tile);
 
			break;
 

	
 
		case MP_TUNNELBRIDGE:
 
			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) return GetRailType(tile);
 
			break;
 

	
src/rail_cmd.cpp
Show inline comments
 
@@ -1278,13 +1278,13 @@ CommandCost CmdConvertRail(TileIndex til
 

	
 
			/* Check if there is any track on tile */
 
			switch (tt) {
 
				case MP_RAILWAY:
 
					break;
 
				case MP_STATION:
 
					if (!IsRailwayStation(tile)) continue;
 
					if (!IsRailwayStation(tile) && !IsRailWaypoint(tile)) continue;
 
					break;
 
				case MP_ROAD:
 
					if (!IsLevelCrossing(tile)) continue;
 
					break;
 
				case MP_TUNNELBRIDGE:
 
					if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
 
@@ -1326,20 +1326,12 @@ CommandCost CmdConvertRail(TileIndex til
 
				}
 
			}
 

	
 
			switch (tt) {
 
				case MP_RAILWAY:
 
					switch (GetRailTileType(tile)) {
 
						case RAIL_TILE_WAYPOINT:
 
							if (flags & DC_EXEC) {
 
								/* notify YAPF about the track layout change */
 
								YapfNotifyTrackLayoutChange(tile, GetRailWaypointTrack(tile));
 
							}
 
							cost.AddCost(RailConvertCost(type, totype));
 
							break;
 

	
 
						case RAIL_TILE_DEPOT:
 
							if (flags & DC_EXEC) {
 
								/* notify YAPF about the track layout change */
 
								YapfNotifyTrackLayoutChange(tile, GetRailDepotTrack(tile));
 

	
 
								/* Update build vehicle window related to this depot */
 
@@ -1498,15 +1490,12 @@ static CommandCost ClearTile_Track(TileI
 
			return cost;
 
		}
 

	
 
		case RAIL_TILE_DEPOT:
 
			return RemoveTrainDepot(tile, flags);
 

	
 
		case RAIL_TILE_WAYPOINT:
 
			return RemoveTrainWaypoint(tile, flags, false);
 

	
 
		default:
 
			return CMD_ERROR;
 
	}
 
}
 

	
 
/**
 
@@ -1903,92 +1892,51 @@ static void DrawTile_Track(TileInfo *ti)
 
		if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti);
 

	
 
		if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
 

	
 
		if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
 
	} else {
 
		/* draw depot/waypoint */
 
		/* draw depot */
 
		const DrawTileSprites *dts;
 
		const DrawTileSeqStruct *dtss;
 
		uint32 relocation;
 
		SpriteID pal = PAL_NONE;
 

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

	
 
		if (IsRailDepot(ti->tile)) {
 
			if (IsInvisibilitySet(TO_BUILDINGS)) {
 
				/* Draw rail instead of depot */
 
				dts = &_depot_invisible_gfx_table[GetRailDepotDirection(ti->tile)];
 
			} else {
 
				dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)];
 
			}
 

	
 
			relocation = rti->total_offset;
 

	
 
			image = dts->ground.sprite;
 
			if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
 

	
 
			/* adjust ground tile for desert
 
			 * don't adjust for snow, because snow in depots looks weird */
 
			if (IsSnowRailGround(ti->tile) && _settings_game.game_creation.landscape == LT_TROPIC) {
 
				if (image != SPR_FLAT_GRASS_TILE) {
 
					image += rti->snow_offset; // tile with tracks
 
				} else {
 
					image = SPR_FLAT_SNOWY_TILE; // flat ground
 
				}
 
			}
 
		if (IsInvisibilitySet(TO_BUILDINGS)) {
 
			/* Draw rail instead of depot */
 
			dts = &_depot_invisible_gfx_table[GetRailDepotDirection(ti->tile)];
 
		} else {
 
			/* look for customization */
 
			const StationSpec *statspec = GetStationSpec(ti->tile);
 

	
 
			if (statspec != NULL) {
 
				const BaseStation *st = BaseStation::GetByTile(ti->tile);
 
				uint gfx = 2;
 

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

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

	
 
				if (dts != NULL && dts->seq != NULL) {
 
					relocation = GetCustomStationRelocation(statspec, st, ti->tile);
 

	
 
					image = dts->ground.sprite;
 
					if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
 
						image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
 
						image += rti->custom_ground_offset;
 
					} else {
 
						image += rti->total_offset;
 
					}
 

	
 
					pal = dts->ground.pal;
 
				} else {
 
					goto default_waypoint;
 
				}
 
			dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)];
 
		}
 

	
 
		relocation = rti->total_offset;
 

	
 
		image = dts->ground.sprite;
 
		if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
 

	
 
		/* adjust ground tile for desert
 
			* don't adjust for snow, because snow in depots looks weird */
 
		if (IsSnowRailGround(ti->tile) && _settings_game.game_creation.landscape == LT_TROPIC) {
 
			if (image != SPR_FLAT_GRASS_TILE) {
 
				image += rti->snow_offset; // tile with tracks
 
			} else {
 
default_waypoint:
 
				/* There is no custom layout, fall back to the default graphics */
 
				dts = GetStationTileLayout(STATION_WAYPOINT, GetWaypointAxis(ti->tile));
 
				relocation = 0;
 
				image = dts->ground.sprite + rti->total_offset;
 
				if (IsSnowRailGround(ti->tile)) image += rti->snow_offset;
 
				image = SPR_FLAT_SNOWY_TILE; // flat ground
 
			}
 
		}
 

	
 
		DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, _drawtile_track_palette));
 

	
 
		/* PBS debugging, draw reserved tracks darker */
 
		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile) &&
 
				(!IsRailDepot(ti->tile) || GetRailDepotDirection(ti->tile) == DIAGDIR_SW || GetRailDepotDirection(ti->tile) == DIAGDIR_SE)) {
 
			DrawGroundSprite(GetWaypointAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH);
 
		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) {
 
			switch (GetRailDepotDirection(ti->tile)) {
 
				case DIAGDIR_SW: DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); break;
 
				case DIAGDIR_SE: DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); break;
 
				default: break;
 
			}
 
		}
 

	
 
		if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
 

	
 
		foreach_draw_tile_seq(dtss, dts->seq) {
 
			SpriteID image = dtss->image.sprite;
 
@@ -2289,28 +2237,23 @@ static TrackStatus GetTileTrackStatus_Tr
 

	
 
			if (side != INVALID_DIAGDIR && side != dir) break;
 

	
 
			trackbits = DiagDirToDiagTrackBits(dir);
 
			break;
 
		}
 

	
 
		case RAIL_TILE_WAYPOINT:
 
			trackbits = GetRailWaypointBits(tile);
 
			break;
 
	}
 

	
 
	return CombineTrackStatus(TrackBitsToTrackdirBits(trackbits), red_signals);
 
}
 

	
 
static bool ClickTile_Track(TileIndex tile)
 
{
 
	switch (GetRailTileType(tile)) {
 
		case RAIL_TILE_DEPOT:    ShowDepotWindow(tile, VEH_TRAIN);              return true;
 
		case RAIL_TILE_WAYPOINT: ShowWaypointWindow(Waypoint::GetByTile(tile)); return true;
 
		default: return false;
 
	}
 
	if (!IsRailDepot(tile)) return false;
 

	
 
	ShowDepotWindow(tile, VEH_TRAIN);
 
	return true;
 
}
 

	
 
static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
 
{
 
	td->owner[0] = GetTileOwner(tile);
 
	switch (GetRailTileType(tile)) {
 
@@ -2384,16 +2327,14 @@ static void GetTileDesc_Track(TileIndex 
 
		}
 

	
 
		case RAIL_TILE_DEPOT:
 
			td->str = STR_RAILROAD_TRAIN_DEPOT;
 
			break;
 

	
 
		case RAIL_TILE_WAYPOINT:
 
		default:
 
			td->str = STR_LANDINFO_WAYPOINT;
 
			break;
 
			NOT_REACHED();
 
	}
 
}
 

	
 
static void ChangeTileOwner_Track(TileIndex tile, Owner old_owner, Owner new_owner)
 
{
 
	if (!IsTileOwner(tile, old_owner)) return;
 
@@ -2576,28 +2517,15 @@ static CommandCost TerraformTile_Track(T
 

	
 
		/* Make the ground dirty */
 
		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
 

	
 
		/* allow terraforming */
 
		return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0);
 
	} else {
 
		if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
 
			switch (GetRailTileType(tile)) {
 
				case RAIL_TILE_WAYPOINT: {
 
					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
 
					if (!CmdFailed(cost)) return cost; // allow autoslope
 
					break;
 
				}
 

	
 
				case RAIL_TILE_DEPOT:
 
					if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
					break;
 

	
 
				default: NOT_REACHED();
 
			}
 
		}
 
	} else if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() &&
 
			AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) {
 
		return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
	}
 
	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
}
 

	
 

	
 
extern const TileTypeProcs _tile_type_rail_procs = {
src/rail_map.h
Show inline comments
 
@@ -15,13 +15,12 @@
 

	
 

	
 
/** Different types of Rail-related tiles */
 
enum RailTileType {
 
	RAIL_TILE_NORMAL   = 0, ///< Normal rail tile without signals
 
	RAIL_TILE_SIGNALS  = 1, ///< Normal rail tile with signals
 
	RAIL_TILE_WAYPOINT = 2, ///< Waypoint (X or Y direction)
 
	RAIL_TILE_DEPOT    = 3, ///< Depot (one entrance)
 
};
 

	
 
/**
 
 * Returns the RailTileType (normal with or without signals,
 
 * waypoint or depot).
 
@@ -80,33 +79,12 @@ static inline void SetHasSignals(TileInd
 
{
 
	assert(IsPlainRailTile(tile));
 
	SB(_m[tile].m5, 6, 1, signals);
 
}
 

	
 
/**
 
 * Is this rail tile a rail waypoint?
 
 * @param t the tile to get the information from
 
 * @pre IsTileType(t, MP_RAILWAY)
 
 * @return true if and only if the tile is a rail waypoint
 
 */
 
static inline bool IsRailWaypoint(TileIndex t)
 
{
 
	return GetRailTileType(t) == RAIL_TILE_WAYPOINT;
 
}
 

	
 
/**
 
 * Is this tile rail tile and a rail waypoint?
 
 * @param t the tile to get the information from
 
 * @return true if and only if the tile is a rail waypoint
 
 */
 
static inline bool IsRailWaypointTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_RAILWAY) && IsRailWaypoint(t);
 
}
 

	
 
/**
 
 * Is this rail tile a rail depot?
 
 * @param t the tile to get the information from
 
 * @pre IsTileType(t, MP_RAILWAY)
 
 * @return true if and only if the tile is a rail depot
 
 */
 
static inline bool IsRailDepot(TileIndex t)
 
@@ -200,57 +178,12 @@ static inline Track GetRailDepotTrack(Ti
 
{
 
	return DiagDirToDiagTrack(GetRailDepotDirection(t));
 
}
 

	
 

	
 
/**
 
 * Returns the axis of the waypoint
 
 * @param t the tile to get the waypoint axis from
 
 * @pre IsRailWaypointTile(t)
 
 * @return the axis of the waypoint
 
 */
 
static inline Axis GetWaypointAxis(TileIndex t)
 
{
 
	return (Axis)GB(_m[t].m5, 0, 1);
 
}
 

	
 
/**
 
 * Returns the track of the waypoint
 
 * @param t the tile to get the waypoint track from
 
 * @pre IsRailWaypointTile(t)
 
 * @return the track of the waypoint
 
 */
 
static inline Track GetRailWaypointTrack(TileIndex t)
 
{
 
	return AxisToTrack(GetWaypointAxis(t));
 
}
 

	
 
/**
 
 * Returns the track bits of the waypoint
 
 * @param t the tile to get the waypoint track bits from
 
 * @pre IsRailWaypointTile(t)
 
 * @return the track bits of the waypoint
 
 */
 
static inline TrackBits GetRailWaypointBits(TileIndex t)
 
{
 
	return TrackToTrackBits(GetRailWaypointTrack(t));
 
}
 

	
 
/**
 
 * Returns waypoint index (for the waypoint pool)
 
 * @param t the tile to get the waypoint index from
 
 * @pre IsRailWaypointTile(t)
 
 * @return the waypoint index
 
 */
 
static inline WaypointID GetWaypointIndex(TileIndex t)
 
{
 
	return (WaypointID)_m[t].m2;
 
}
 

	
 

	
 
/**
 
 * Returns the reserved track bits of the tile
 
 * @pre IsPlainRailTile(t)
 
 * @param t the tile to query
 
 * @return the track bits
 
 */
 
static inline TrackBits GetRailReservationTrackBits(TileIndex t)
 
@@ -333,23 +266,12 @@ static inline void SetDepotReservation(T
 
{
 
	assert(IsRailDepot(t));
 
	SB(_m[t].m5, 4, 1, (byte)b);
 
}
 

	
 
/**
 
 * Get the reserved track bits for a waypoint
 
 * @pre IsRailWaypoint(t)
 
 * @param t the tile
 
 * @return reserved track bits
 
 */
 
static inline TrackBits GetWaypointReservationTrackBits(TileIndex t)
 
{
 
	return HasDepotReservation(t) ? GetRailWaypointBits(t) : TRACK_BIT_NONE;
 
}
 

	
 
/**
 
 * Get the reserved track bits for a depot
 
 * @pre IsRailDepot(t)
 
 * @param t the tile
 
 * @return reserved track bits
 
 */
 
static inline TrackBits GetDepotReservationTrackBits(TileIndex t)
 
@@ -632,20 +554,7 @@ static inline void MakeRailDepot(TileInd
 
	_m[t].m4 = 0;
 
	_m[t].m5 = RAIL_TILE_DEPOT << 6 | d;
 
	SB(_m[t].m6, 2, 4, 0);
 
	_me[t].m7 = 0;
 
}
 

	
 

	
 
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_TILE_WAYPOINT << 6 | a;
 
	SB(_m[t].m6, 2, 4, 0);
 
	_me[t].m7 = 0;
 
}
 

	
 
#endif /* RAIL_MAP_H */
src/saveload/afterload.cpp
Show inline comments
 
@@ -603,15 +603,13 @@ bool AfterLoadGame()
 
	}
 

	
 
	for (TileIndex t = 0; t < map_size; t++) {
 
		switch (GetTileType(t)) {
 
			case MP_STATION: {
 
				Station *st = Station::GetByTile(t);
 

	
 
				/* Set up station spread; buoys do not have one */
 
				if (!IsBuoy(t)) st->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
 
				if (st == NULL) break;
 

	
 
				switch (GetStationType(t)) {
 
					case STATION_TRUCK:
 
					case STATION_BUS:
 
						if (CheckSavegameVersion(6)) {
 
							/* From this version on there can be multiple road stops of the
 
@@ -984,35 +982,17 @@ bool AfterLoadGame()
 
	 * replaced, shall keep their old length. In all prior versions, just default
 
	 * to false */
 
	if (CheckSavegameVersionOldStyle(16, 1)) {
 
		FOR_ALL_COMPANIES(c) c->settings.renew_keep_length = false;
 
	}
 

	
 
	/* In version 17, ground type is moved from m2 to m4 for depots and
 
	 * waypoints to make way for storing the index in m2. The custom graphics
 
	 * id which was stored in m4 is now saved as a grf/id reference in the
 
	 * waypoint struct. */
 
	if (CheckSavegameVersion(17)) {
 
		Waypoint *wp;
 

	
 
		FOR_ALL_WAYPOINTS(wp) {
 
			if (wp->delete_ctr == 0) {
 
				if (HasBit(_m[wp->xy].m3, 4)) {
 
					AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1), wp, true);
 
				}
 

	
 
				/* Move ground type bits from m2 to m4. */
 
				_m[wp->xy].m4 = GB(_m[wp->xy].m2, 0, 4);
 
				/* Store waypoint index in the tile. */
 
				_m[wp->xy].m2 = wp->index;
 
			}
 
		}
 
	} else {
 
		/* As of version 17, we recalculate the custom graphic ID of waypoints
 
		 * from the GRF ID / station index. */
 
		AfterLoadWaypoints();
 
	if (CheckSavegameVersion(123)) {
 
		/* Waypoints became subclasses of stations ... */
 
		MoveWaypointsToBaseStations();
 
		/* ... and buoys were moved to waypoints. */
 
		MoveBuoysToWaypoints();
 
	}
 

	
 
	/* From version 15, we moved a semaphore bit from bit 2 to bit 3 in m4, making
 
	 *  room for PBS. Now in version 21 move it back :P. */
 
	if (CheckSavegameVersion(21) && !CheckSavegameVersion(15)) {
 
		for (TileIndex t = 0; t < map_size; t++) {
 
@@ -1272,15 +1252,15 @@ bool AfterLoadGame()
 
		}
 
	}
 

	
 
	/* Buoys do now store the owner of the previous water tile, which can never
 
	 * be OWNER_NONE. So replace OWNER_NONE with OWNER_WATER. */
 
	if (CheckSavegameVersion(46)) {
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->IsBuoy() && IsTileOwner(st->xy, OWNER_NONE) && TileHeight(st->xy) == 0) SetTileOwner(st->xy, OWNER_WATER);
 
		Waypoint *wp;
 
		FOR_ALL_WAYPOINTS(wp) {
 
			if ((wp->facilities & FACIL_DOCK) != 0 && IsTileOwner(wp->xy, OWNER_NONE) && TileHeight(wp->xy) == 0) SetTileOwner(wp->xy, OWNER_WATER);
 
		}
 
	}
 

	
 
	if (CheckSavegameVersion(50)) {
 
		Aircraft *v;
 
		/* Aircraft units changed from 8 mph to 1 km/h */
 
@@ -1484,21 +1464,12 @@ bool AfterLoadGame()
 
				v->current_order.SetLoadType(OLFB_NO_LOAD);
 
			}
 
		}
 
	}
 

	
 
	if (CheckSavegameVersion(84)) {
 
		/* Update go to buoy orders because they are just waypoints */
 
		Order *order;
 
		FOR_ALL_ORDERS(order) {
 
			if (order->IsType(OT_GOTO_STATION) && Station::Get(order->GetDestination())->IsBuoy()) {
 
				order->SetLoadType(OLF_LOAD_IF_POSSIBLE);
 
				order->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
 
			}
 
		}
 

	
 
		/* Set all share owners to INVALID_COMPANY for
 
		 * 1) all inactive companies
 
		 *     (when inactive companies were stored in the savegame - TTD, TTDP and some
 
		 *      *really* old revisions of OTTD; else it is already set in InitializeCompanies())
 
		 * 2) shares that are owned by inactive companies or self
 
		 *     (caused by cheating clients in earlier revisions) */
 
@@ -1558,13 +1529,13 @@ bool AfterLoadGame()
 
					_current_company = o;
 
					ChangeTileOwner(t, o, INVALID_OWNER);
 
				}
 
				if (IsBuoyTile(t)) {
 
					/* reset buoy owner to OWNER_NONE in the station struct
 
					 * (even if it is owned by active company) */
 
					Station::GetByTile(t)->owner = OWNER_NONE;
 
					Waypoint::GetByTile(t)->owner = OWNER_NONE;
 
				}
 
			} else if (IsTileType(t, MP_ROAD)) {
 
				/* works for all RoadTileType */
 
				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 
					/* update even non-existing road types to update tile owner too */
 
					Owner o = GetRoadOwner(t, rt);
 
@@ -1802,22 +1773,12 @@ bool AfterLoadGame()
 
		 * The conversion affects oil rigs and buoys too, but it doesn't matter as
 
		 * they have st->owner == OWNER_NONE already. */
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (!Company::IsValidID(st->owner)) st->owner = OWNER_NONE;
 
		}
 

	
 
		/* Give owners to waypoints, based on rail tracks it is sitting on.
 
		 * If none is available, specify OWNER_NONE.
 
		 * This code was in CheckSavegameVersion(101) in the past, but in some cases,
 
		 * the owner of waypoints could be incorrect. */
 
		Waypoint *wp;
 
		FOR_ALL_WAYPOINTS(wp) {
 
			Owner owner = IsTileType(wp->xy, MP_RAILWAY) ? GetTileOwner(wp->xy) : OWNER_NONE;
 
			wp->owner = Company::IsValidID(owner) ? owner : OWNER_NONE;
 
		}
 
	}
 

	
 
	/* Trains could now stop in a specific location. */
 
	if (CheckSavegameVersion(117)) {
 
		Order *o;
 
		FOR_ALL_ORDERS(o) {
 
@@ -1910,20 +1871,12 @@ bool AfterLoadGame()
 
						if (Industry::IsValidID(s->from) && Industry::IsValidID(s->to)) continue;
 
						break;
 
				}
 
			}
 
			s->cargo_type = CT_INVALID;
 
		}
 

	
 
		Order *o;
 
		FOR_ALL_ORDERS(o) {
 
			/* Buoys are now go to waypoint orders */
 
			if (!o->IsType(OT_GOTO_STATION) || !Station::Get(o->GetDestination())->IsBuoy()) continue;
 

	
 
			o->MakeGoToWaypoint(o->GetDestination());
 
		}
 
	}
 

	
 
	AfterLoadLabelMaps();
 

	
 
	GamelogPrintDebug(1);
 

	
 
@@ -1947,14 +1900,13 @@ void ReloadNewGRFData()
 
	ResetEconomy();
 
	/* reload vehicles */
 
	ResetVehiclePosHash();
 
	AfterLoadVehicles(false);
 
	StartupEngines();
 
	SetCachedEngineCounts();
 
	/* update station and waypoint graphics */
 
	AfterLoadWaypoints();
 
	/* update station graphics */
 
	AfterLoadStations();
 
	/* Check and update house and town values */
 
	UpdateHousesAndTowns();
 
	/* Update livery selection windows */
 
	for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) InvalidateWindowData(WC_COMPANY_COLOUR, i);
 
	/* redraw the whole screen */
src/saveload/saveload.cpp
Show inline comments
 
@@ -38,13 +38,13 @@
 
#include "../engine_base.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "saveload_internal.h"
 

	
 
extern const uint16 SAVEGAME_VERSION = 122;
 
extern const uint16 SAVEGAME_VERSION = 123;
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
 
uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
@@ -870,12 +870,13 @@ size_t SlCalcObjMemberLength(const void 
 
				case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld));
 
				default: NOT_REACHED();
 
			}
 
			break;
 
		case SL_WRITEBYTE: return 1; // a byte is logically of size 1
 
		case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
 
		case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
 
		default: NOT_REACHED();
 
	}
 
	return 0;
 
}
 

	
 

	
 
@@ -931,12 +932,16 @@ bool SlObjectMember(void *ptr, const Sav
 

	
 
		/* SL_VEH_INCLUDE loads common code for vehicles */
 
		case SL_VEH_INCLUDE:
 
			SlObject(ptr, GetVehicleDescription(VEH_END));
 
			break;
 

	
 
		case SL_ST_INCLUDE:
 
			SlObject(ptr, GetBaseStationDescription());
 
			break;
 

	
 
		default: NOT_REACHED();
 
	}
 
	return true;
 
}
 

	
 
/**
src/saveload/saveload.h
Show inline comments
 
@@ -179,12 +179,13 @@ enum SaveLoadTypes {
 
	SL_ARR         =  2,
 
	SL_STR         =  3,
 
	SL_LST         =  4,
 
	/* non-normal save-load types */
 
	SL_WRITEBYTE   =  8,
 
	SL_VEH_INCLUDE =  9,
 
	SL_ST_INCLUDE  = 10,
 
	SL_END         = 15
 
};
 

	
 
typedef byte SaveLoadType;
 

	
 
/** SaveLoad type struct. Do NOT use this directly but use the SLE_ macros defined just below! */
 
@@ -232,12 +233,13 @@ typedef SaveLoad SaveLoadGlobVarList;
 

	
 
#define SLE_VARX(offset, type) SLE_CONDVARX(offset, type, 0, SL_MAX_VERSION)
 
#define SLE_REFX(offset, type) SLE_CONDREFX(offset, type, 0, SL_MAX_VERSION)
 

	
 
#define SLE_WRITEBYTEX(offset, something) SLE_GENERALX(SL_WRITEBYTE, offset, 0, 0, something, 0)
 
#define SLE_VEH_INCLUDEX() SLE_GENERALX(SL_VEH_INCLUDE, 0, 0, 0, 0, SL_MAX_VERSION)
 
#define SLE_ST_INCLUDEX() SLE_GENERALX(SL_ST_INCLUDE, 0, 0, 0, 0, SL_MAX_VERSION)
 

	
 
/* End marker */
 
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL}
 

	
 
/* Simple variables, references (pointers) and arrays, but for global variables */
 
#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable}
src/saveload/saveload_internal.h
Show inline comments
 
@@ -13,13 +13,16 @@
 

	
 
void InitializeOldNames();
 
StringID RemapOldStringID(StringID s);
 
char *CopyFromOldName(StringID id);
 
void ResetOldNames();
 

	
 
void AfterLoadWaypoints();
 
void MoveBuoysToWaypoints();
 
void MoveWaypointsToBaseStations();
 
const SaveLoad *GetBaseStationDescription();
 

	
 
void AfterLoadVehicles(bool part_of_load);
 
void AfterLoadStations();
 
void AfterLoadLabelMaps();
 
void UpdateHousesAndTowns();
 

	
 
void UpdateOldAircraft();
src/saveload/station_sl.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/** @file station_sl.cpp Code handling saving and loading of economy data */
 

	
 
#include "../stdafx.h"
 
#include "../station_base.h"
 
#include "../waypoint.h"
 
#include "../roadstop_base.h"
 
#include "../order_base.h"
 
#include "../vehicle_base.h"
 
#include "../core/bitmath_func.hpp"
 
#include "../core/alloc_func.hpp"
 
#include "../variables.h"
 
#include "../newgrf_station.h"
 

	
 
#include "saveload.h"
 
#include "table/strings.h"
 

	
 
/**
 
 * Update the buoy orders to be waypoint orders.
 
 * @param o the order 'list' to check.
 
 */
 
static void UpdateWaypointOrder(Order *o)
 
{
 
	if (!o->IsType(OT_GOTO_STATION)) return;
 

	
 
	const Station *st = Station::Get(o->GetDestination());
 
	if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) return;
 

	
 
	o->MakeGoToWaypoint(o->GetDestination());
 
}
 

	
 
/**
 
 * Perform all steps to upgrade from the old station buoys to the new version
 
 * that uses waypoints. This includes some old saveload mechanics.
 
 */
 
void MoveBuoysToWaypoints()
 
{
 
	/* Buoy orders become waypoint orders */
 
	OrderList *ol;
 
	FOR_ALL_ORDER_LISTS(ol) {
 
		if (ol->GetFirstSharedVehicle()->type != VEH_SHIP) continue;
 

	
 
		for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
 
	}
 

	
 
	Vehicle *v;
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type != VEH_SHIP) continue;
 

	
 
		UpdateWaypointOrder(&v->current_order);
 
	}
 

	
 
	/* Now make the stations waypoints */
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue;
 

	
 
		StationID index    = st->index;
 
		TileIndex xy       = st->xy;
 
		Town *town         = st->town;
 
		StringID string_id = st->string_id;
 
		char *name         = st->name;
 
		Date build_date    = st->build_date;
 

	
 
		/* Delete the station, so we can make it a real waypoint. */
 
		delete st;
 

	
 
		Waypoint *wp = new (index) Waypoint(xy);
 
		wp->town       = town;
 
		wp->string_id  = STR_SV_STNAME_BUOY;
 
		wp->name       = name;
 
		wp->delete_ctr = 0; // Just reset delete counter for once.
 
		wp->build_date = build_date;
 
		wp->owner      = OWNER_NONE;
 

	
 
		if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY;
 

	
 
		if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
 
			wp->facilities |= FACIL_DOCK;
 
		}
 
	}
 
}
 

	
 
void AfterLoadStations()
 
{
 
	/* Update the speclists of all stations to point to the currently loaded custom stations. */
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
	BaseStation *st;
 
	FOR_ALL_BASE_STATIONS(st) {
 
		for (uint i = 0; i < st->num_specs; i++) {
 
			if (st->speclist[i].grfid == 0) continue;
 

	
 
			st->speclist[i].spec = GetCustomStationSpecByGrf(st->speclist[i].grfid, st->speclist[i].localidx, NULL);
 
		}
 

	
 
		for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
 
		if (Station::IsExpected(st)) {
 
			for (CargoID c = 0; c < NUM_CARGO; c++) Station::From(st)->goods[c].cargo.InvalidateCache();
 
		}
 

	
 
		StationUpdateAnimTriggers(st);
 
	}
 
}
 

	
 
static const SaveLoad _roadstop_desc[] = {
 
@@ -45,13 +116,13 @@ static const SaveLoad _roadstop_desc[] =
 
	SLE_CONDNULL(4, 0, 24),
 
	SLE_CONDNULL(1, 25, 25),
 

	
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _station_desc[] = {
 
static const SaveLoad _old_station_desc[] = {
 
	SLE_CONDVAR(Station, xy,                         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
 
	SLE_CONDVAR(Station, xy,                         SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDNULL(4, 0, 5),  ///< bus/lorry tile
 
	SLE_CONDVAR(Station, train_tile,                 SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
 
	SLE_CONDVAR(Station, train_tile,                 SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(Station, airport_tile,               SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
 
@@ -142,85 +213,209 @@ const SaveLoad *GetGoodsDesc()
 
	};
 

	
 
	return goods_desc;
 
}
 

	
 

	
 
static void SaveLoad_STNS(Station *st)
 
{
 
	SlObject(st, _station_desc);
 

	
 
	_waiting_acceptance = 0;
 

	
 
	uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
 
	for (CargoID i = 0; i < num_cargo; i++) {
 
		GoodsEntry *ge = &st->goods[i];
 
		SlObject(ge, GetGoodsDesc());
 
		if (CheckSavegameVersion(68)) {
 
			SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
 
			if (GB(_waiting_acceptance, 0, 12) != 0) {
 
				/* Don't construct the packet with station here, because that'll fail with old savegames */
 
				CargoPacket *cp = new CargoPacket();
 
				/* In old versions, enroute_from used 0xFF as INVALID_STATION */
 
				cp->source          = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
 
				cp->count           = GB(_waiting_acceptance, 0, 12);
 
				cp->days_in_transit = _cargo_days;
 
				cp->feeder_share    = _cargo_feeder_share;
 
				cp->source_xy       = _cargo_source_xy;
 
				cp->days_in_transit = _cargo_days;
 
				cp->feeder_share    = _cargo_feeder_share;
 
				SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
 
				ge->cargo.Append(cp);
 
			}
 
		}
 
	}
 

	
 
	if (st->num_specs != 0) {
 
		/* Allocate speclist memory when loading a game */
 
		if (st->speclist == NULL) st->speclist = CallocT<StationSpecList>(st->num_specs);
 
		for (uint i = 0; i < st->num_specs; i++) {
 
			SlObject(&st->speclist[i], _station_speclist_desc);
 
		}
 
	}
 
}
 

	
 
static void Save_STNS()
 
{
 
	Station *st;
 
	/* Write the stations */
 
	FOR_ALL_STATIONS(st) {
 
		SlSetArrayIndex(st->index);
 
		SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
 
	}
 
}
 

	
 
static void Load_STNS()
 
{
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		Station *st = new (index) Station();
 

	
 
		SaveLoad_STNS(st);
 
		SlObject(st, _old_station_desc);
 

	
 
		_waiting_acceptance = 0;
 

	
 
		uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
 
		for (CargoID i = 0; i < num_cargo; i++) {
 
			GoodsEntry *ge = &st->goods[i];
 
			SlObject(ge, GetGoodsDesc());
 
			if (CheckSavegameVersion(68)) {
 
				SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
 
				if (GB(_waiting_acceptance, 0, 12) != 0) {
 
					/* Don't construct the packet with station here, because that'll fail with old savegames */
 
					CargoPacket *cp = new CargoPacket();
 
					/* In old versions, enroute_from used 0xFF as INVALID_STATION */
 
					cp->source          = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
 
					cp->count           = GB(_waiting_acceptance, 0, 12);
 
					cp->days_in_transit = _cargo_days;
 
					cp->feeder_share    = _cargo_feeder_share;
 
					cp->source_xy       = _cargo_source_xy;
 
					cp->days_in_transit = _cargo_days;
 
					cp->feeder_share    = _cargo_feeder_share;
 
					SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
 
					ge->cargo.Append(cp);
 
				}
 
			}
 
		}
 

	
 
		if (st->num_specs != 0) {
 
			/* Allocate speclist memory when loading a game */
 
			st->speclist = CallocT<StationSpecList>(st->num_specs);
 
			for (uint i = 0; i < st->num_specs; i++) {
 
				SlObject(&st->speclist[i], _station_speclist_desc);
 
			}
 
		}
 
	}
 
}
 

	
 
void Ptrs_STNS()
 
{
 
	/* Don't run when savegame version is higher than or equal to 123. */
 
	if (!CheckSavegameVersion(123)) return;
 

	
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		if (!CheckSavegameVersion(68)) {
 
			for (CargoID i = 0; i < NUM_CARGO; i++) {
 
				GoodsEntry *ge = &st->goods[i];
 
				SlObject(ge, GetGoodsDesc());
 
			}
 
		}
 
		SlObject(st, _station_desc);
 
		SlObject(st, _old_station_desc);
 
	}
 
}
 

	
 

	
 
static const SaveLoad _base_station_desc[] = {
 
	      SLE_VAR(BaseStation, xy,                     SLE_UINT32),
 
	      SLE_REF(BaseStation, town,                   REF_TOWN),
 
	      SLE_VAR(BaseStation, string_id,              SLE_STRINGID),
 
	      SLE_STR(BaseStation, name,                   SLE_STR, 0),
 
	      SLE_VAR(BaseStation, delete_ctr,             SLE_UINT8),
 
	      SLE_VAR(BaseStation, owner,                  SLE_UINT8),
 
	      SLE_VAR(BaseStation, facilities,             SLE_UINT8),
 
	      SLE_VAR(BaseStation, build_date,             SLE_INT32),
 

	
 
	/* Used by newstations for graphic variations */
 
	      SLE_VAR(BaseStation, random_bits,            SLE_UINT16),
 
	      SLE_VAR(BaseStation, waiting_triggers,       SLE_UINT8),
 
	      SLE_VAR(BaseStation, num_specs,              SLE_UINT8),
 

	
 
	      SLE_END()
 
};
 

	
 
static const SaveLoad _station_desc[] = {
 
	SLE_WRITEBYTE(Station, facilities,                 FACIL_NONE),
 
	SLE_ST_INCLUDEX(),
 

	
 
	      SLE_VAR(Station, train_tile,                 SLE_UINT32),
 
	      SLE_VAR(Station, trainst_w,                  SLE_UINT8),
 
	      SLE_VAR(Station, trainst_h,                  SLE_UINT8),
 

	
 
	      SLE_REF(Station, bus_stops,                  REF_ROADSTOPS),
 
	      SLE_REF(Station, truck_stops,                REF_ROADSTOPS),
 
	      SLE_VAR(Station, dock_tile,                  SLE_UINT32),
 
	      SLE_VAR(Station, airport_tile,               SLE_UINT32),
 
	      SLE_VAR(Station, airport_type,               SLE_UINT8),
 
	      SLE_VAR(Station, airport_flags,              SLE_UINT64),
 

	
 
	      SLE_VAR(Station, indtype,                    SLE_UINT8),
 

	
 
	      SLE_VAR(Station, time_since_load,            SLE_UINT8),
 
	      SLE_VAR(Station, time_since_unload,          SLE_UINT8),
 
	      SLE_VAR(Station, last_vehicle_type,          SLE_UINT8),
 
	      SLE_VAR(Station, had_vehicle_of_type,        SLE_UINT8),
 
	      SLE_LST(Station, loading_vehicles,           REF_VEHICLE),
 

	
 
	      SLE_END()
 
};
 

	
 
static const SaveLoad _waypoint_desc[] = {
 
	SLE_WRITEBYTE(Waypoint, facilities,                FACIL_WAYPOINT),
 
	SLE_ST_INCLUDEX(),
 

	
 
	      SLE_VAR(Waypoint, town_cn,                   SLE_UINT16),
 

	
 
	      SLE_END()
 
};
 

	
 
/**
 
 * Get the base station description to be used for SL_ST_INCLUDE
 
 * @return the base station description.
 
 */
 
const SaveLoad *GetBaseStationDescription()
 
{
 
	return _base_station_desc;
 
}
 

	
 
static void RealSave_STNN(BaseStation *bst)
 
{
 
	bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0;
 
	SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
 

	
 
	if (!waypoint) {
 
		Station *st = Station::From(bst);
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			SlObject(&st->goods[i], GetGoodsDesc());
 
		}
 
	}
 

	
 
	for (uint i = 0; i < bst->num_specs; i++) {
 
		SlObject(&bst->speclist[i], _station_speclist_desc);
 
	}
 
}
 

	
 
static void Save_STNN()
 
{
 
	BaseStation *st;
 
	/* Write the stations */
 
	FOR_ALL_BASE_STATIONS(st) {
 
		SlSetArrayIndex(st->index);
 
		SlAutolength((AutolengthProc*)RealSave_STNN, st);
 
	}
 
}
 

	
 
static void Load_STNN()
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
 

	
 
		BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
 
		SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
 

	
 
		if (!waypoint) {
 
			Station *st = Station::From(bst);
 
			for (CargoID i = 0; i < NUM_CARGO; i++) {
 
				SlObject(&st->goods[i], GetGoodsDesc());
 
			}
 
		}
 

	
 
		if (bst->num_specs != 0) {
 
			/* Allocate speclist memory when loading a game */
 
			bst->speclist = CallocT<StationSpecList>(bst->num_specs);
 
			for (uint i = 0; i < bst->num_specs; i++) {
 
				SlObject(&bst->speclist[i], _station_speclist_desc);
 
			}
 
		}
 
	}
 
}
 

	
 
static void Ptrs_STNN()
 
{
 
	/* Don't run when savegame version lower than 123. */
 
	if (CheckSavegameVersion(123)) return;
 

	
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			GoodsEntry *ge = &st->goods[i];
 
			SlObject(ge, GetGoodsDesc());
 
		}
 
		SlObject(st, _station_desc);
 
	}
 

	
 
	Waypoint *wp;
 
	FOR_ALL_WAYPOINTS(wp) {
 
		SlObject(wp, _waypoint_desc);
 
	}
 
}
 

	
 
static void Save_ROADSTOP()
 
{
 
	RoadStop *rs;
 

	
 
	FOR_ALL_ROADSTOPS(rs) {
 
		SlSetArrayIndex(rs->index);
 
@@ -245,9 +440,10 @@ static void Ptrs_ROADSTOP()
 
	FOR_ALL_ROADSTOPS(rs) {
 
		SlObject(rs, _roadstop_desc);
 
	}
 
}
 

	
 
extern const ChunkHandler _station_chunk_handlers[] = {
 
	{ 'STNS', Save_STNS,     Load_STNS,     Ptrs_STNS,     CH_ARRAY },
 
	{ 'STNS', NULL,          Load_STNS,     Ptrs_STNS,     CH_ARRAY },
 
	{ 'STNN', Save_STNN,     Load_STNN,     Ptrs_STNN,     CH_ARRAY },
 
	{ 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, CH_ARRAY | CH_LAST},
 
};
src/saveload/waypoint_sl.cpp
Show inline comments
 
@@ -2,123 +2,190 @@
 

	
 
/** @file waypoint_sl.cpp Code handling saving and loading of waypoints */
 

	
 
#include "../stdafx.h"
 
#include "../waypoint.h"
 
#include "../newgrf_station.h"
 
#include "../vehicle_base.h"
 
#include "../town.h"
 
#include "../station_map.h"
 

	
 
#include "table/strings.h"
 

	
 
#include "saveload.h"
 
#include "saveload_internal.h"
 

	
 
/**
 
 * Update waypoint graphics id against saved GRFID/localidx.
 
 * This is to ensure the chosen graphics are correct if GRF files are changed.
 
 */
 
void AfterLoadWaypoints()
 
{
 
	Waypoint *wp;
 
/** Helper structure to convert from the old waypoint system. */
 
struct OldWaypoint {
 
	size_t index;
 
	TileIndex xy;
 
	TownID town_index;
 
	Town *town;
 
	uint16 town_cn;
 
	StringID string_id;
 
	char *name;
 
	uint8 delete_ctr;
 
	Date build_date;
 
	uint8 localidx;
 
	uint32 grfid;
 
	const StationSpec *spec;
 
	OwnerByte owner;
 

	
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->num_specs == 0) continue;
 
	size_t new_index;
 
};
 

	
 
/** Temporary array with old waypoints. */
 
static SmallVector<OldWaypoint, 16> _old_waypoints;
 

	
 
		for (uint i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
 
			const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
 
			if (statspec != NULL && statspec->grffile->grfid == wp->speclist[1].grfid && statspec->localidx == wp->speclist[1].localidx) {
 
				wp->speclist[1].spec = statspec;
 
				break;
 
			}
 
		}
 
/**
 
 * Update the waypoint orders to get the new waypoint ID.
 
 * @param o the order 'list' to check.
 
 */
 
static void UpdateWaypointOrder(Order *o)
 
{
 
	if (!o->IsType(OT_GOTO_WAYPOINT)) return;
 

	
 
	for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
 
		if (wp->index != o->GetDestination()) continue;
 

	
 
		o->SetDestination(wp->new_index);
 
		return;
 
	}
 
}
 

	
 
static uint16 _waypoint_town_index;
 
static StringID _waypoint_string_id;
 
static StationSpecList _waypoint_spec;
 
/**
 
 * Perform all steps to upgrade from the old waypoints to the new version
 
 * that uses station. This includes some old saveload mechanics.
 
 */
 
void MoveWaypointsToBaseStations()
 
{
 
	/* In version 17, ground type is moved from m2 to m4 for depots and
 
	 * waypoints to make way for storing the index in m2. The custom graphics
 
	 * id which was stored in m4 is now saved as a grf/id reference in the
 
	 * waypoint struct. */
 
	if (CheckSavegameVersion(17)) {
 
		for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
 
			if (wp->delete_ctr == 0 && HasBit(_m[wp->xy].m3, 4)) {
 
				wp->spec = GetCustomStationSpec(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1);
 
			}
 
		}
 
	} else {
 
		/* As of version 17, we recalculate the custom graphic ID of waypoints
 
		 * from the GRF ID / station index. */
 
		for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
 
			for (uint i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
 
				const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
 
				if (statspec != NULL && statspec->grffile->grfid == wp->grfid && statspec->localidx == wp->localidx) {
 
					wp->spec = statspec;
 
					break;
 
				}
 
			}
 
		}
 
	}
 

	
 
	/* All saveload conversions have been done. Create the new waypoints! */
 
	for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
 
		Waypoint *new_wp = new Waypoint(wp->xy);
 
		new_wp->town       = wp->town;
 
		new_wp->town_cn    = wp->town_cn;
 
		new_wp->name       = wp->name;
 
		new_wp->delete_ctr = 0; // Just reset delete counter for once.
 
		new_wp->build_date = wp->build_date;
 
		new_wp->owner      = wp->owner;
 

	
 
		new_wp->string_id = STR_SV_STNAME_WAYPOINT;
 

	
 
		TileIndex t = wp->xy;
 
		if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp->index) {
 
			/* The tile might've been reserved! */
 
			bool reserved = !CheckSavegameVersion(100) && HasBit(_m[t].m5, 4);
 

	
 
static const SaveLoad _waypoint_desc[] = {
 
	 SLE_CONDVAR(Waypoint, xy,            SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
 
	 SLE_CONDVAR(Waypoint, xy,            SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLEG_CONDVAR(_waypoint_town_index,    SLE_UINT16,                 12, 121),
 
	 SLE_CONDREF(Waypoint, town,          REF_TOWN,                  122, SL_MAX_VERSION),
 
	 SLE_CONDVAR(Waypoint, town_cn,       SLE_FILE_U8 | SLE_VAR_U16,  12, 88),
 
	 SLE_CONDVAR(Waypoint, town_cn,       SLE_UINT16,                 89, SL_MAX_VERSION),
 
	SLEG_CONDVAR(_waypoint_string_id,     SLE_STRINGID,                0, 83),
 
	 SLE_CONDSTR(Waypoint, name,          SLE_STR, 0,                 84, SL_MAX_VERSION),
 
	     SLE_VAR(Waypoint, delete_ctr,    SLE_UINT8),
 
			/* The tile really has our waypoint, so reassign the map array */
 
			MakeRailWaypoint(t, GetTileOwner(t), new_wp->index, (Axis)GB(_m[t].m5, 0, 1), 0, GetRailType(t));
 
			new_wp->facilities |= FACIL_TRAIN;
 
			new_wp->owner = GetTileOwner(t);
 

	
 
			SetRailwayStationReservation(t, reserved);
 

	
 
			if (wp->spec != NULL) {
 
				SetCustomStationSpecIndex(t, AllocateSpecToStation(wp->spec, new_wp, true));
 
			}
 
		}
 

	
 
		wp->new_index = new_wp->index;
 
	}
 

	
 
	/* Update the orders of vehicles */
 
	OrderList *ol;
 
	FOR_ALL_ORDER_LISTS(ol) {
 
		if (ol->GetFirstSharedVehicle()->type != VEH_TRAIN) continue;
 

	
 
		for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
 
	}
 

	
 
	 SLE_CONDVAR(Waypoint, build_date,    SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
 
	 SLE_CONDVAR(Waypoint, build_date,    SLE_INT32,                  31, SL_MAX_VERSION),
 
	SLEG_CONDVAR(_waypoint_spec.localidx, SLE_UINT8,                   3, SL_MAX_VERSION),
 
	SLEG_CONDVAR(_waypoint_spec.grfid,    SLE_UINT32,                 17, SL_MAX_VERSION),
 
	 SLE_CONDVAR(Waypoint, owner,         SLE_UINT8,                 101, SL_MAX_VERSION),
 
	Vehicle *v;
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type != VEH_TRAIN) continue;
 

	
 
		UpdateWaypointOrder(&v->current_order);
 
	}
 

	
 
	_old_waypoints.Reset();
 
}
 

	
 
static const SaveLoad _old_waypoint_desc[] = {
 
	SLE_CONDVAR(OldWaypoint, xy,         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
 
	SLE_CONDVAR(OldWaypoint, xy,         SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, town_index, SLE_UINT16,                 12, 121),
 
	SLE_CONDREF(OldWaypoint, town,       REF_TOWN,                  122, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, town_cn,    SLE_FILE_U8 | SLE_VAR_U16,  12, 88),
 
	SLE_CONDVAR(OldWaypoint, town_cn,    SLE_UINT16,                 89, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, string_id,  SLE_STRINGID,                0, 83),
 
	SLE_CONDSTR(OldWaypoint, name,       SLE_STR, 0,                 84, SL_MAX_VERSION),
 
	    SLE_VAR(OldWaypoint, delete_ctr, SLE_UINT8),
 

	
 
	SLE_CONDVAR(OldWaypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
 
	SLE_CONDVAR(OldWaypoint, build_date, SLE_INT32,                  31, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, localidx,   SLE_UINT8,                   3, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, grfid,      SLE_UINT32,                 17, SL_MAX_VERSION),
 
	SLE_CONDVAR(OldWaypoint, owner,      SLE_UINT8,                 101, SL_MAX_VERSION),
 

	
 
	SLE_END()
 
};
 

	
 
static void Save_WAYP()
 
{
 
	Waypoint *wp;
 

	
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->num_specs == 0) {
 
			_waypoint_spec.grfid = 0;
 
		} else {
 
			_waypoint_spec = wp->speclist[1];
 
		}
 

	
 
		SlSetArrayIndex(wp->index);
 
		SlObject(wp, _waypoint_desc);
 
	}
 
}
 

	
 
static void Load_WAYP()
 
{
 
	/* Precaution for when loading failed and it didn't get cleared */
 
	_old_waypoints.Clear();
 

	
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		_waypoint_string_id = 0;
 
		_waypoint_town_index = 0;
 
		_waypoint_spec.grfid = 0;
 

	
 
		Waypoint *wp = new (index) Waypoint();
 
		SlObject(wp, _waypoint_desc);
 

	
 
		wp->facilities |= FACIL_TRAIN;
 
		OldWaypoint *wp = _old_waypoints.Append();
 
		memset(wp, 0, sizeof(*wp));
 

	
 
		if (_waypoint_spec.grfid != 0) {
 
			wp->num_specs = 2;
 
			wp->speclist = CallocT<StationSpecList>(2);
 
			wp->speclist[1] = _waypoint_spec;
 
		}
 

	
 
		if (CheckSavegameVersion(84)) wp->name = (char *)(size_t)_waypoint_string_id;
 
		if (CheckSavegameVersion(122)) wp->town = (Town *)(size_t)_waypoint_town_index;
 
		wp->index = index;
 
		SlObject(wp, _old_waypoint_desc);
 
	}
 
}
 

	
 
static void Ptrs_WAYP()
 
{
 
	Waypoint *wp;
 
	for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
 
		SlObject(wp, _old_waypoint_desc);
 

	
 
	FOR_ALL_WAYPOINTS(wp) {
 
		SlObject(wp, _waypoint_desc);
 

	
 
		StringID sid = (StringID)(size_t)wp->name;
 
		if (CheckSavegameVersion(12)) {
 
			wp->town_cn = (sid & 0xC000) == 0xC000 ? (sid >> 8) & 0x3F : 0;
 
			wp->town_cn = (wp->string_id & 0xC000) == 0xC000 ? (wp->string_id >> 8) & 0x3F : 0;
 
			wp->town = ClosestTownFromTile(wp->xy, UINT_MAX);
 
		} else if (CheckSavegameVersion(122)) {
 
			/* Only for versions 12 .. 122 */
 
			wp->town = Town::Get((size_t)wp->town);
 
			wp->town = Town::Get(wp->town_index);
 
		}
 
		if (CheckSavegameVersion(84)) {
 
			wp->name = CopyFromOldName(sid);
 
			wp->name = CopyFromOldName(wp->string_id);
 
		}
 
	}
 
}
 

	
 
extern const ChunkHandler _waypoint_chunk_handlers[] = {
 
	{ 'CHKP', Save_WAYP, Load_WAYP, Ptrs_WAYP, CH_ARRAY | CH_LAST},
 
	{ 'CHKP', NULL, Load_WAYP, Ptrs_WAYP, CH_ARRAY | CH_LAST},
 
};
src/signal.cpp
Show inline comments
 
@@ -285,20 +285,12 @@ static SigFlags ExploreSegment(Owner own
 
						continue;
 
					} else {
 
						continue;
 
					}
 
				}
 

	
 
				if (GetRailTileType(tile) == RAIL_TILE_WAYPOINT) {
 
					if (GetWaypointAxis(tile) != DiagDirToAxis(enterdir)) continue;
 
					if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
 
					tile += TileOffsByDiagDir(exitdir);
 
					/* enterdir and exitdir stay the same */
 
					break;
 
				}
 

	
 
				TrackBits tracks = GetTrackBits(tile); // trackbits of tile
 
				TrackBits tracks_masked = (TrackBits)(tracks & _enterdir_to_trackbits[enterdir]); // only incidating trackbits
 

	
 
				if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check
 
					tracks = tracks_masked;
 
					if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, &tracks, &EnsureNoTrainOnTrackProc)) flags |= SF_TRAIN;
src/station.cpp
Show inline comments
 
@@ -47,18 +47,12 @@ Station::Station(TileIndex tile) :
 
	time_since_unload(255),
 
	last_vehicle_type(VEH_INVALID)
 
{
 
	/* this->random_bits is set in Station::AddFacility() */
 
}
 

	
 
/* static */ BaseStation *BaseStation::GetByTile(TileIndex tile)
 
{
 
	if (IsRailWaypointTile(tile)) return Waypoint::GetByTile(tile);
 
	return Station::GetByTile(tile);
 
}
 

	
 
/**
 
 * Clean up a station by clearing vehicle orders and invalidating windows.
 
 * Aircraft-Hangar orders need special treatment here, as the hangars are
 
 * actually part of a station (tiletype is STATION), but the order type
 
 * is OT_GOTO_DEPOT.
 
 */
src/station_base.h
Show inline comments
 
@@ -18,13 +18,13 @@
 
#include "industry_type.h"
 
#include "core/geometry_type.hpp"
 
#include "viewport_type.h"
 
#include "station_map.h"
 
#include <list>
 

	
 
typedef Pool<Station, StationID, 32, 64000> StationPool;
 
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
 
extern StationPool _station_pool;
 

	
 
static const byte INITIAL_STATION_RATING = 175;
 

	
 
struct GoodsEntry {
 
	enum AcceptancePickup {
 
@@ -82,13 +82,13 @@ struct TileArea {
 
	TileIndex tile; ///< The base tile of the area
 
	uint8 w;        ///< The width of the area
 
	uint8 h;        ///< The height of the area
 
};
 

	
 
/** Base class for all station-ish types */
 
struct BaseStation {
 
struct BaseStation : StationPool::PoolItem<&_station_pool> {
 
	TileIndex xy;                   ///< Base tile of the station
 
	ViewportSign sign;              ///< NOSAVE: Dimensions of sign
 
	byte delete_ctr;                ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted.
 

	
 
	char *name;                     ///< Custom name
 
	StringID string_id;             ///< Default name (town area) of station
 
@@ -141,15 +141,20 @@ struct BaseStation {
 

	
 
	/**
 
	 * Get the base station belonging to a specific tile.
 
	 * @param tile The tile to get the base station from.
 
	 * @return the station associated with that tile.
 
	 */
 
	static BaseStation *GetByTile(TileIndex tile);
 
	static FORCEINLINE BaseStation *GetByTile(TileIndex tile)
 
	{
 
		return BaseStation::Get(GetStationIndex(tile));
 
	}
 
};
 

	
 
#define FOR_ALL_BASE_STATIONS(var) FOR_ALL_ITEMS_FROM(BaseStation, station_index, var, 0)
 

	
 
/**
 
 * Class defining several overloaded accessors so we don't
 
 * have to cast base stations that often
 
 */
 
template <class T, bool Tis_waypoint>
 
struct SpecializedStation : public BaseStation {
 
@@ -173,12 +178,50 @@ struct SpecializedStation : public BaseS
 
	static FORCEINLINE bool IsExpected(const BaseStation *st)
 
	{
 
		return (st->facilities & FACIL_WAYPOINT) == EXPECTED_FACIL;
 
	}
 

	
 
	/**
 
	 * Tests whether given index is a valid index for station of this type
 
	 * @param index tested index
 
	 * @return is this index valid index of T?
 
	 */
 
	static FORCEINLINE bool IsValidID(size_t index)
 
	{
 
		return BaseStation::IsValidID(index) && IsExpected(BaseStation::Get(index));
 
	}
 

	
 
	/**
 
	 * Gets station with given index
 
	 * @return pointer to station with given index casted to T *
 
	 */
 
	static FORCEINLINE T *Get(size_t index)
 
	{
 
		return (T *)BaseStation::Get(index);
 
	}
 

	
 
	/**
 
	 * Returns station if the index is a valid index for this station type
 
	 * @return pointer to station with given index if it's a station of this type
 
	 */
 
	static FORCEINLINE T *GetIfValid(size_t index)
 
	{
 
		return IsValidID(index) ? Get(index) : NULL ;
 
	}
 

	
 
	/**
 
	 * Get the station belonging to a specific tile.
 
	 * @param tile The tile to get the station from.
 
	 * @return the station associated with that tile.
 
	 */
 
	static FORCEINLINE T *GetByTile(TileIndex tile)
 
	{
 
		return GetIfValid(GetStationIndex(tile));
 
	}
 

	
 
	/**
 
	 * Converts a BaseStation to SpecializedStation with type checking.
 
	 * @param st BaseStation pointer
 
	 * @return pointer to SpecializedStation
 
	 */
 
	static FORCEINLINE T *From(BaseStation *st)
 
	{
 
@@ -195,17 +238,19 @@ struct SpecializedStation : public BaseS
 
	{
 
		assert(IsExpected(st));
 
		return (const T *)st;
 
	}
 
};
 

	
 
#define FOR_ALL_BASE_STATIONS_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, station_index, var, 0) if (name::IsExpected(var))
 

	
 

	
 
typedef SmallVector<Industry *, 2> IndustryVector;
 

	
 
/** Station data structure */
 
struct Station : StationPool::PoolItem<&_station_pool>, SpecializedStation<Station, false> {
 
struct Station : SpecializedStation<Station, false> {
 
public:
 
	RoadStop *GetPrimaryRoadStop(RoadStopType type) const
 
	{
 
		return type == ROADSTOP_BUS ? bus_stops : truck_stops;
 
	}
 

	
 
@@ -271,27 +316,12 @@ public:
 
	}
 

	
 
	/* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
 

	
 
	/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
 

	
 
	/**
 
	 * Determines whether a station is a buoy only.
 
	 * @todo Ditch this encoding of buoys
 
	 */
 
	FORCEINLINE bool IsBuoy() const
 
	{
 
		return (this->had_vehicle_of_type & HVOT_BUOY) != 0;
 
	}
 

	
 
	static FORCEINLINE Station *GetByTile(TileIndex tile)
 
	{
 
		return Station::Get(GetStationIndex(tile));
 
	}
 

	
 
	static void PostDestructor(size_t index);
 
};
 

	
 
#define FOR_ALL_STATIONS_FROM(var, start) FOR_ALL_ITEMS_FROM(Station, station_index, var, start)
 
#define FOR_ALL_STATIONS(var) FOR_ALL_STATIONS_FROM(var, 0)
 
#define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
 

	
 
#endif /* STATION_BASE_H */
src/station_cmd.cpp
Show inline comments
 
@@ -194,13 +194,12 @@ static bool CMSAForest(TileIndex tile)
 
enum StationNaming {
 
	STATIONNAMING_RAIL,
 
	STATIONNAMING_ROAD,
 
	STATIONNAMING_AIRPORT,
 
	STATIONNAMING_OILRIG,
 
	STATIONNAMING_DOCK,
 
	STATIONNAMING_BUOY,
 
	STATIONNAMING_HELIPORT,
 
};
 

	
 
/** Information to handle station action 0 property 24 correctly */
 
struct StationNameInformation {
 
	uint32 free_names; ///< Current bitset of free names (we can remove names).
 
@@ -236,13 +235,12 @@ static StringID GenerateStationName(Stat
 
	static const uint32 _gen_station_name_bits[] = {
 
		0,                                       // STATIONNAMING_RAIL
 
		0,                                       // STATIONNAMING_ROAD
 
		1U << M(STR_SV_STNAME_AIRPORT),          // STATIONNAMING_AIRPORT
 
		1U << M(STR_SV_STNAME_OILFIELD),         // STATIONNAMING_OILRIG
 
		1U << M(STR_SV_STNAME_DOCKS),            // STATIONNAMING_DOCK
 
		0x1FFU << M(STR_SV_STNAME_BUOY_1),       // STATIONNAMING_BUOY
 
		1U << M(STR_SV_STNAME_HELIPORT),         // STATIONNAMING_HELIPORT
 
	};
 

	
 
	const Town *t = st->town;
 
	uint32 free_names = UINT32_MAX;
 

	
 
@@ -263,30 +261,28 @@ static StringID GenerateStationName(Stat
 
				}
 
				ClrBit(free_names, str);
 
			}
 
		}
 
	}
 

	
 
	if (name_class != STATIONNAMING_BUOY) {
 
		TileIndex indtile = tile;
 
		StationNameInformation sni = { free_names, indtypes };
 
		if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) {
 
			/* An industry has been found nearby */
 
			IndustryType indtype = GetIndustryType(indtile);
 
			const IndustrySpec *indsp = GetIndustrySpec(indtype);
 
			/* STR_NULL means it only disables oil rig/mines */
 
			if (indsp->station_name != STR_NULL) {
 
				st->indtype = indtype;
 
				return STR_SV_STNAME_FALLBACK;
 
			}
 
	TileIndex indtile = tile;
 
	StationNameInformation sni = { free_names, indtypes };
 
	if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) {
 
		/* An industry has been found nearby */
 
		IndustryType indtype = GetIndustryType(indtile);
 
		const IndustrySpec *indsp = GetIndustrySpec(indtype);
 
		/* STR_NULL means it only disables oil rig/mines */
 
		if (indsp->station_name != STR_NULL) {
 
			st->indtype = indtype;
 
			return STR_SV_STNAME_FALLBACK;
 
		}
 

	
 
		/* Oil rigs/mines name could be marked not free by looking for a near by industry. */
 
		free_names = sni.free_names;
 
	}
 

	
 
	/* Oil rigs/mines name could be marked not free by looking for a near by industry. */
 
	free_names = sni.free_names;
 

	
 
	/* check default names */
 
	uint32 tmp = free_names & _gen_station_name_bits[name_class];
 
	if (tmp != 0) return STR_SV_STNAME + FindFirstBit(tmp);
 

	
 
	/* check mine? */
 
	if (HasBit(free_names, M(STR_SV_STNAME_MINES))) {
 
@@ -537,15 +533,12 @@ CargoArray GetAcceptanceAroundTiles(Tile
 
/** Update the acceptance for a station.
 
 * @param st Station to update
 
 * @param show_msg controls whether to display a message that acceptance was changed.
 
 */
 
static void UpdateStationAcceptance(Station *st, bool show_msg)
 
{
 
	/* Don't update acceptance for a buoy */
 
	if (st->IsBuoy()) return;
 

	
 
	/* old accepted goods types */
 
	uint old_acc = GetAcceptanceMask(st);
 

	
 
	/* And retrieve the acceptance. */
 
	CargoArray acceptance;
 
	if (!st->rect.IsEmpty()) {
 
@@ -1960,37 +1953,29 @@ CommandCost CmdBuildBuoy(TileIndex tile,
 
	if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
 
	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
 

	
 
	/* allocate and initialize new station */
 
	if (!Station::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
 
	if (!Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
 

	
 
	if (flags & DC_EXEC) {
 
		Station *st = new Station(tile);
 

	
 
		st->town = ClosestTownFromTile(tile, UINT_MAX);
 
		st->string_id = GenerateStationName(st, tile, STATIONNAMING_BUOY);
 

	
 
		if (Company::IsValidID(_current_company)) {
 
			SetBit(st->town->have_ratings, _current_company);
 
		}
 
		st->dock_tile = tile;
 
		Waypoint *st = new Waypoint(tile);
 

	
 
		st->string_id = STR_SV_STNAME_BUOY;
 

	
 
		st->facilities |= FACIL_DOCK;
 
		/* Buoys are marked in the Station struct by this flag. Yes, it is this
 
		 * braindead.. */
 
		st->had_vehicle_of_type |= HVOT_BUOY;
 
		st->owner = OWNER_NONE;
 

	
 
		st->build_date = _date;
 

	
 
		if (st->town == NULL) MakeDefaultWaypointName(st);
 

	
 
		MakeBuoy(tile, st->index, GetWaterClass(tile));
 

	
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
 
}
 
@@ -2005,13 +1990,13 @@ bool HasStationInUse(StationID station, 
 
{
 
	const Vehicle *v;
 
	FOR_ALL_VEHICLES(v) {
 
		if (company == INVALID_COMPANY || v->owner == company) {
 
			const Order *order;
 
			FOR_VEHICLE_ORDERS(v, order) {
 
				if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == station) {
 
				if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
 
					return true;
 
				}
 
			}
 
		}
 
	}
 
	return false;
 
@@ -2025,36 +2010,31 @@ bool HasStationInUse(StationID station, 
 
 */
 
static CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
 
{
 
	/* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
 
	if (!Company::IsValidID(_current_company) && !(flags & DC_BANKRUPT)) return_cmd_error(INVALID_STRING_ID);
 

	
 
	Station *st = Station::GetByTile(tile);
 
	Waypoint *st = Waypoint::GetByTile(tile);
 

	
 
	if (HasStationInUse(st->index, INVALID_COMPANY)) return_cmd_error(STR_BUOY_IS_IN_USE);
 
	/* remove the buoy if there is a ship on tile when company goes bankrupt... */
 
	if (!(flags & DC_BANKRUPT) && !EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		st->dock_tile = INVALID_TILE;
 
		/* Buoys are marked in the Station struct by this flag. Yes, it is this
 
		 * braindead.. */
 
		st->facilities &= ~FACIL_DOCK;
 
		st->had_vehicle_of_type &= ~HVOT_BUOY;
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 

	
 
		/* We have to set the water tile's state to the same state as before the
 
		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
 
		 * remove it and flood the land (if the canal edge is at level 0) */
 
		MakeWaterKeepingClass(tile, GetTileOwner(tile));
 
		MarkTileDirtyByTile(tile);
 

	
 
		st->UpdateVirtCoord();
 
		st->RecomputeIndustriesNear();
 
		DeleteStationIfEmpty(st);
 
		st->delete_ctr = 0;
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_truck_station);
 
}
 

	
 
static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
 
@@ -2224,24 +2204,24 @@ static void DrawTile_Station(TileInfo *t
 
{
 
	const DrawTileSprites *t = NULL;
 
	RoadTypes roadtypes;
 
	int32 total_offset;
 
	int32 custom_ground_offset;
 

	
 
	if (IsRailwayStation(ti->tile)) {
 
	if (IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) {
 
		const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
		roadtypes = ROADTYPES_NONE;
 
		total_offset = rti->total_offset;
 
		custom_ground_offset = rti->custom_ground_offset;
 
	} else {
 
		roadtypes = IsRoadStop(ti->tile) ? GetRoadTypes(ti->tile) : ROADTYPES_NONE;
 
		total_offset = 0;
 
		custom_ground_offset = 0;
 
	}
 
	uint32 relocation = 0;
 
	const Station *st = NULL;
 
	const BaseStation *st = NULL;
 
	const StationSpec *statspec = NULL;
 
	Owner owner = GetTileOwner(ti->tile);
 

	
 
	SpriteID palette;
 
	if (Company::IsValidID(owner)) {
 
		palette = COMPANY_SPRITE_COLOUR(owner);
 
@@ -2253,13 +2233,13 @@ static void DrawTile_Station(TileInfo *t
 
	/* don't show foundation for docks */
 
	if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile))
 
		DrawFoundation(ti, FOUNDATION_LEVELED);
 

	
 
	if (IsCustomStationSpecIndex(ti->tile)) {
 
		/* look for customization */
 
		st = Station::GetByTile(ti->tile);
 
		st = BaseStation::GetByTile(ti->tile);
 
		statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
 

	
 
		if (statspec != NULL) {
 
			uint tile = GetStationGfx(ti->tile);
 

	
 
			relocation = GetCustomStationRelocation(statspec, st, ti->tile);
 
@@ -2301,26 +2281,31 @@ static void DrawTile_Station(TileInfo *t
 
		} else {
 
			image += total_offset;
 
		}
 
		DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
 

	
 
		/* PBS debugging, draw reserved tracks darker */
 
		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && IsRailwayStation(ti->tile) && HasStationReservation(ti->tile)) {
 
		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && (IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) && HasStationReservation(ti->tile)) {
 
			const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
			DrawGroundSprite(GetRailStationAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH);
 
		}
 
	}
 

	
 
	if (IsRailwayStation(ti->tile) && HasCatenaryDrawn(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
 
	if ((IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) && HasCatenaryDrawn(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
 

	
 
	if (HasBit(roadtypes, ROADTYPE_TRAM)) {
 
		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
 
		DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
 
		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
 
	}
 

	
 
	if (IsRailWaypoint(ti->tile)) {
 
		/* Don't offset the waypoint graphics; they're always the same. */
 
		total_offset = 0;
 
	}
 

	
 
	const DrawTileSeqStruct *dtss;
 
	foreach_draw_tile_seq(dtss, t->seq) {
 
		SpriteID image = dtss->image.sprite;
 

	
 
		/* Stop drawing sprite sequence once we meet a sprite that doesn't have to be opaque */
 
		if (IsInvisibilitySet(TO_BUILDINGS) && !HasBit(image, SPRITE_MODIFIER_OPAQUE)) return;
 
@@ -2405,13 +2390,13 @@ static void GetTileDesc_Station(TileInde
 
			if (tram_owner != INVALID_OWNER) {
 
				td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
 
				td->owner[i] = tram_owner;
 
			}
 
		}
 
	}
 
	td->build_date = Station::GetByTile(tile)->build_date;
 
	td->build_date = BaseStation::GetByTile(tile)->build_date;
 

	
 
	const StationSpec *spec = GetStationSpec(tile);
 

	
 
	if (spec != NULL) {
 
		td->station_class = GetStationClassName(spec->sclass);
 
		td->station_name = spec->name;
 
@@ -2422,33 +2407,34 @@ static void GetTileDesc_Station(TileInde
 
		}
 
	}
 

	
 
	StringID str;
 
	switch (GetStationType(tile)) {
 
		default: NOT_REACHED();
 
		case STATION_RAIL:    str = STR_STATION_DESCRIPTION_RAILROAD_STATION; break;
 
		case STATION_RAIL:     str = STR_STATION_DESCRIPTION_RAILROAD_STATION; break;
 
		case STATION_AIRPORT:
 
			str = (IsHangar(tile) ? STR_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_STATION_DESCRIPTION_AIRPORT);
 
			break;
 
		case STATION_TRUCK:   str = STR_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
 
		case STATION_BUS:     str = STR_STATION_DESCRIPTION_BUS_STATION; break;
 
		case STATION_OILRIG:  str = STR_INDUSTRY_NAME_OIL_RIG; break;
 
		case STATION_DOCK:    str = STR_STATION_DESCRIPTION_SHIP_DOCK; break;
 
		case STATION_BUOY:    str = STR_STATION_DESCRIPTION_BUOY; break;
 
		case STATION_TRUCK:    str = STR_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
 
		case STATION_BUS:      str = STR_STATION_DESCRIPTION_BUS_STATION; break;
 
		case STATION_OILRIG:   str = STR_INDUSTRY_NAME_OIL_RIG; break;
 
		case STATION_DOCK:     str = STR_STATION_DESCRIPTION_SHIP_DOCK; break;
 
		case STATION_BUOY:     str = STR_STATION_DESCRIPTION_BUOY; break;
 
		case STATION_WAYPOINT: str = STR_LANDINFO_WAYPOINT; break;
 
	}
 
	td->str = str;
 
}
 

	
 

	
 
static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
 
{
 
	TrackBits trackbits = TRACK_BIT_NONE;
 

	
 
	switch (mode) {
 
		case TRANSPORT_RAIL:
 
			if (IsRailwayStation(tile) && !IsStationTileBlocked(tile)) {
 
			if ((IsRailwayStation(tile) || IsRailWaypoint(tile)) && !IsStationTileBlocked(tile)) {
 
				trackbits = TrackToTrackBits(GetRailStationTrack(tile));
 
			}
 
			break;
 

	
 
		case TRANSPORT_WATER:
 
			/* buoy is coded as a station, it is always on open water */
 
@@ -2548,16 +2534,20 @@ static void AnimateTile_Station(TileInde
 
	}
 
}
 

	
 

	
 
static bool ClickTile_Station(TileIndex tile)
 
{
 
	if (IsHangar(tile)) {
 
	const BaseStation *st = BaseStation::GetByTile(tile);
 

	
 
	if (st->facilities & FACIL_WAYPOINT) {
 
		ShowWaypointWindow(Waypoint::From(st));
 
	} else if (IsHangar(tile)) {
 
		ShowDepotWindow(tile, VEH_AIRCRAFT);
 
	} else {
 
		ShowStationViewWindow(GetStationIndex(tile));
 
		ShowStationViewWindow(st->index);
 
	}
 
	return true;
 
}
 

	
 
static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
 
{
 
@@ -2647,21 +2637,21 @@ static VehicleEnterTileStatus VehicleEnt
 
/**
 
 * This function is called for each station once every 250 ticks.
 
 * Not all stations will get the tick at the same time.
 
 * @param st the station receiving the tick.
 
 * @return true if the station is still valid (wasn't deleted)
 
 */
 
static bool StationHandleBigTick(Station *st)
 
static bool StationHandleBigTick(BaseStation *st)
 
{
 
	UpdateStationAcceptance(st, true);
 

	
 
	if (st->facilities == 0 && ++st->delete_ctr >= 8) {
 
	if ((st->facilities & ~FACIL_WAYPOINT) == 0 && ++st->delete_ctr >= 8) {
 
		delete st;
 
		return false;
 
	}
 

	
 
	if ((st->facilities & FACIL_WAYPOINT) == 0) UpdateStationAcceptance(Station::From(st), true);
 

	
 
	return true;
 
}
 

	
 
static inline void byte_inc_sat(byte *p)
 
{
 
	byte b = *p + 1;
 
@@ -2775,29 +2765,29 @@ static void UpdateStationRating(Station 
 
	} else {
 
		InvalidateWindowWidget(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
 
	}
 
}
 

	
 
/* called for every station each tick */
 
static void StationHandleSmallTick(Station *st)
 
static void StationHandleSmallTick(BaseStation *st)
 
{
 
	if (st->facilities == 0) return;
 
	if ((st->facilities & FACIL_WAYPOINT) != 0 || st->facilities == 0) return;
 

	
 
	byte b = st->delete_ctr + 1;
 
	if (b >= 185) b = 0;
 
	st->delete_ctr = b;
 

	
 
	if (b == 0) UpdateStationRating(st);
 
	if (b == 0) UpdateStationRating(Station::From(st));
 
}
 

	
 
void OnTick_Station()
 
{
 
	if (_game_mode == GM_EDITOR) return;
 

	
 
	Station *st;
 
	FOR_ALL_STATIONS(st) {
 
	BaseStation *st;
 
	FOR_ALL_BASE_STATIONS(st) {
 
		StationHandleSmallTick(st);
 

	
 
		/* Run 250 tick interval trigger for station animation.
 
		 * Station index is included so that triggers are not all done
 
		 * at the same time. */
 
		if ((_tick_counter + st->index) % 250 == 0) {
 
@@ -2881,13 +2871,13 @@ CommandCost CmdRenameStation(TileIndex t
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Find all (non-buoy) stations around a rectangular producer (industry, house, headquarter, ...)
 
 * Find all stations around a rectangular producer (industry, house, headquarter, ...)
 
 *
 
 * @param tile North tile of producer
 
 * @param w_prod X extent of producer
 
 * @param h_prod Y extent of producer
 
 *
 
 * @return: Set of found stations
 
@@ -2900,14 +2890,13 @@ void FindStationsAroundTiles(TileIndex t
 
	for (int dy = -max_rad; dy < h_prod + max_rad; dy++) {
 
		for (int dx = -max_rad; dx < w_prod + max_rad; dx++) {
 
			TileIndex cur_tile = TileAddWrap(tile, dx, dy);
 
			if (cur_tile == INVALID_TILE || !IsTileType(cur_tile, MP_STATION)) continue;
 

	
 
			Station *st = Station::GetByTile(cur_tile);
 

	
 
			if (st->IsBuoy()) continue; // bouys don't accept cargo
 
			if (st == NULL) continue;
 

	
 
			if (_settings_game.station.modified_catchment) {
 
				int rad = st->GetCatchmentRadius();
 
				if (dx < -rad || dx >= rad + w_prod || dy < -rad || dy >= rad + h_prod) continue;
 
			}
 

	
 
@@ -3117,37 +3106,39 @@ static bool CanRemoveRoadWithStop(TileIn
 

	
 
static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
 
{
 
	if (flags & DC_AUTO) {
 
		switch (GetStationType(tile)) {
 
			default: break;
 
			case STATION_RAIL:    return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
 
			case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
 
			case STATION_TRUCK:   return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
 
			case STATION_BUS:     return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
 
			case STATION_BUOY:    return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
 
			case STATION_DOCK:    return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
 
			case STATION_RAIL:     return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
 
			case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
 
			case STATION_AIRPORT:  return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
 
			case STATION_TRUCK:    return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
 
			case STATION_BUS:      return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
 
			case STATION_BUOY:     return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
 
			case STATION_DOCK:     return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
 
			case STATION_OILRIG:
 
				SetDParam(0, STR_INDUSTRY_NAME_OIL_RIG);
 
				return_cmd_error(STR_OBJECT_IN_THE_WAY);
 
		}
 
	}
 

	
 
	switch (GetStationType(tile)) {
 
		case STATION_RAIL:    return RemoveRailroadStation(tile, flags);
 
		case STATION_AIRPORT: return RemoveAirport(tile, flags);
 
		case STATION_RAIL:     return RemoveRailroadStation(tile, flags);
 
		case STATION_WAYPOINT: return RemoveTrainWaypoint(tile, flags, false);
 
		case STATION_AIRPORT:  return RemoveAirport(tile, flags);
 
		case STATION_TRUCK:
 
			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
 
				return_cmd_error(STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
 
			return RemoveRoadStop(tile, flags);
 
		case STATION_BUS:
 
			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
 
				return_cmd_error(STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
 
			return RemoveRoadStop(tile, flags);
 
		case STATION_BUOY:    return RemoveBuoy(tile, flags);
 
		case STATION_DOCK:    return RemoveDock(tile, flags);
 
		case STATION_BUOY:     return RemoveBuoy(tile, flags);
 
		case STATION_DOCK:     return RemoveDock(tile, flags);
 
		default: break;
 
	}
 

	
 
	return CMD_ERROR;
 
}
 

	
 
@@ -3156,12 +3147,13 @@ static CommandCost TerraformTile_Station
 
	if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
 
		/* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
 
		 *       TTDP does not call it.
 
		 */
 
		if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
 
			switch (GetStationType(tile)) {
 
				case STATION_WAYPOINT:
 
				case STATION_RAIL: {
 
					DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
 
					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
 
					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
 
					return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
				}
src/station_gui.cpp
Show inline comments
 
@@ -140,13 +140,13 @@ protected:
 
		DEBUG(misc, 3, "Building station list for company %d", owner);
 

	
 
		this->stations.Clear();
 

	
 
		const Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy() && HasStationInUse(st->index, owner))) {
 
			if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, owner))) {
 
				if (this->facilities & st->facilities) { // only stations with selected facilities
 
					int num_waiting_cargo = 0;
 
					for (CargoID j = 0; j < NUM_CARGO; j++) {
 
						if (!st->goods[j].cargo.Empty()) {
 
							num_waiting_cargo++; // count number of waiting cargo
 
							if (HasBit(this->cargo_filter, j)) {
 
@@ -375,13 +375,13 @@ public:
 
			int x;
 

	
 
			assert(st->xy != INVALID_TILE);
 

	
 
			/* Do not do the complex check HasStationInUse here, it may be even false
 
			 * when the order had been removed and the station list hasn't been removed yet */
 
			assert(st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy()));
 
			assert(st->owner == owner || st->owner == OWNER_NONE);
 

	
 
			SetDParam(0, st->index);
 
			SetDParam(1, st->facilities);
 
			x = DrawString(xb, this->widget[SLW_LIST].right, y, STR_STATION_LIST_STATION) + 5;
 

	
 
			/* show cargo waiting and station ratings */
 
@@ -406,13 +406,13 @@ public:
 
				id_v += this->vscroll.pos;
 

	
 
				if (id_v >= this->stations.Length()) return; // click out of list bound
 

	
 
				const Station *st = this->stations[id_v];
 
				/* do not check HasStationInUse - it is slow and may be invalid */
 
				assert(st->owner == (Owner)this->window_number || (st->owner == OWNER_NONE && !st->IsBuoy()));
 
				assert(st->owner == (Owner)this->window_number || st->owner == OWNER_NONE);
 

	
 
				if (_ctrl_pressed) {
 
					ShowExtraViewPortWindow(st->xy);
 
				} else {
 
					ScrollMainWindowToTile(st->xy);
 
				}
src/station_map.h
Show inline comments
 
@@ -85,12 +85,34 @@ static inline bool IsRailwayStation(Tile
 

	
 
static inline bool IsRailwayStationTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_STATION) && IsRailwayStation(t);
 
}
 

	
 
/**
 
 * Is this station tile a rail waypoint?
 
 * @param t the tile to get the information from
 
 * @pre IsTileType(t, MP_STATION)
 
 * @return true if and only if the tile is a rail waypoint
 
 */
 
static inline bool IsRailWaypoint(TileIndex t)
 
{
 
	return GetStationType(t) == STATION_WAYPOINT;
 
}
 

	
 
/**
 
 * Is this tile a station tile and a rail waypoint?
 
 * @param t the tile to get the information from
 
 * @return true if and only if the tile is a rail waypoint
 
 */
 
static inline bool IsRailWaypointTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_STATION) && IsRailWaypoint(t);
 
}
 

	
 

	
 
static inline bool IsAirport(TileIndex t)
 
{
 
	return GetStationType(t) == STATION_AIRPORT;
 
}
 

	
 
bool IsHangar(TileIndex t);
 
@@ -183,13 +205,13 @@ static inline bool IsHangarTile(TileInde
 
	return IsTileType(t, MP_STATION) && IsHangar(t);
 
}
 

	
 

	
 
static inline Axis GetRailStationAxis(TileIndex t)
 
{
 
	assert(IsRailwayStation(t));
 
	assert(IsRailwayStation(t) || IsRailWaypoint(t));
 
	return HasBit(GetStationGfx(t), 0) ? AXIS_Y : AXIS_X;
 
}
 

	
 

	
 
static inline Track GetRailStationTrack(TileIndex t)
 
{
 
@@ -211,37 +233,37 @@ static inline bool IsCompatibleTrainStat
 
		GetStationIndex(t1) == GetStationIndex(t2) &&
 
		!IsStationTileBlocked(t1);
 
}
 

	
 
/**
 
 * Get the reservation state of the rail station
 
 * @pre IsRailwayStationTile(t)
 
 * @pre IsRailwayStation(t) || IsRailWaypoint(t)
 
 * @param t the station tile
 
 * @return reservation state
 
 */
 
static inline bool HasStationReservation(TileIndex t)
 
{
 
	assert(IsRailwayStationTile(t));
 
	assert(IsRailwayStation(t) || IsRailWaypoint(t));
 
	return HasBit(_m[t].m6, 2);
 
}
 

	
 
/**
 
 * Set the reservation state of the rail station
 
 * @pre IsRailwayStationTile(t)
 
 * @pre IsRailwayStation(t) || IsRailWaypoint(t)
 
 * @param t the station tile
 
 * @param b the reservation state
 
 */
 
static inline void SetRailwayStationReservation(TileIndex t, bool b)
 
{
 
	assert(IsRailwayStationTile(t));
 
	assert(IsRailwayStation(t) || IsRailWaypoint(t));
 
	SB(_m[t].m6, 2, 1, b ? 1 : 0);
 
}
 

	
 
/**
 
 * Get the reserved track bits for a waypoint
 
 * @pre IsRailwayStationTile(t)
 
 * @pre IsRailwayStation(t) || IsRailWaypoint(t)
 
 * @param t the tile
 
 * @return reserved track bits
 
 */
 
static inline TrackBits GetStationReservationTrackBits(TileIndex t)
 
{
 
	return HasStationReservation(t) ? GetRailStationTrackBits(t) : TRACK_BIT_NONE;
 
@@ -322,12 +344,19 @@ static inline void MakeRailStation(TileI
 
{
 
	MakeStation(t, o, sid, STATION_RAIL, section + a);
 
	SetRailType(t, rt);
 
	SetRailwayStationReservation(t, false);
 
}
 

	
 
static inline void MakeRailWaypoint(TileIndex t, Owner o, StationID sid, Axis a, byte section, RailType rt)
 
{
 
	MakeStation(t, o, sid, STATION_WAYPOINT, section + a);
 
	SetRailType(t, rt);
 
	SetRailwayStationReservation(t, false);
 
}
 

	
 
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d)
 
{
 
	MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), d);
 
	SetRoadTypes(t, rt);
 
	SetRoadOwner(t, ROADTYPE_ROAD, o);
 
	SetRoadOwner(t, ROADTYPE_TRAM, o);
src/station_type.h
Show inline comments
 
@@ -54,15 +54,14 @@ enum StationHadVehicleOfType {
 
	HVOT_NONE     = 0,      ///< Station has seen no vehicles
 
	HVOT_TRAIN    = 1 << 1, ///< Station has seen a train
 
	HVOT_BUS      = 1 << 2, ///< Station has seen a bus
 
	HVOT_TRUCK    = 1 << 3, ///< Station has seen a truck
 
	HVOT_AIRCRAFT = 1 << 4, ///< Station has seen an aircraft
 
	HVOT_SHIP     = 1 << 5, ///< Station has seen a ship
 
	/* This bit is used to mark stations. No, it does not belong here, but what
 
	 * can we do? ;-) */
 
	HVOT_BUOY     = 1 << 6
 

	
 
	HVOT_WAYPOINT = 1 << 6, ///< Station is a waypoint (NewGRF only!)
 
};
 
DECLARE_ENUM_AS_BIT_SET(StationHadVehicleOfType);
 
typedef SimpleTinyEnumT<StationHadVehicleOfType, byte> StationHadVehicleOfTypeByte;
 

	
 
/** The different catchment areas used */
 
enum CatchmentArea {
src/strings.cpp
Show inline comments
 
@@ -860,14 +860,14 @@ static char *FormatString(char *buff, co
 
				if (wp->name != NULL) {
 
					buff = strecpy(buff, wp->name, last);
 
				} else {
 
					int64 temp[2];
 
					temp[0] = wp->town->index;
 
					temp[1] = wp->town_cn + 1;
 
					StringID str = wp->town_cn == 0 ? STR_WAYPOINTNAME_CITY : STR_WAYPOINTNAME_CITY_SERIAL;
 

	
 
					StringID str = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_BUOYNAME_CITY : STR_WAYPOINTNAME_CITY);
 
					if (wp->town_cn != 0) str++;
 
					buff = GetStringWithArgs(buff, str, temp, last);
 
				}
 
				break;
 
			}
 

	
 
			case SCC_STATION_NAME: { // {STATION}
src/terraform_gui.cpp
Show inline comments
 
@@ -632,16 +632,16 @@ static void ResetLandscapeConfirmationCa
 
			delete c;
 
		}
 

	
 
		_generating_world = false;
 

	
 
		/* Delete all station signs */
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
		BaseStation *st;
 
		FOR_ALL_BASE_STATIONS(st) {
 
			/* There can be buoys, remove them */
 
			if (st->IsBuoy() && IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
 
			if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
 
			if (st->facilities == 0) delete st;
 
		}
 

	
 
		/* The same for waypoints */
 
		Waypoint *wp;
 
		FOR_ALL_WAYPOINTS(wp) {
src/train_cmd.cpp
Show inline comments
 
@@ -479,13 +479,13 @@ int GetTrainCurveSpeedLimit(Train *v)
 
static int GetTrainAcceleration(Train *v, bool mode)
 
{
 
	int max_speed = v->tcache.cached_max_curve_speed;
 
	assert(max_speed == GetTrainCurveSpeedLimit(v)); // safety check, will be removed later
 
	int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
 

	
 
	if (IsTileType(v->tile, MP_STATION) && v->IsFrontEngine()) {
 
	if (IsRailwayStationTile(v->tile) && v->IsFrontEngine()) {
 
		StationID sid = GetStationIndex(v->tile);
 
		if (v->current_order.ShouldStopAtStation(v, sid)) {
 
			int station_ahead;
 
			int station_length;
 
			int stop_at = GetTrainStopLocation(sid, v->tile, v, &station_ahead, &station_length);
 

	
 
@@ -4440,18 +4440,16 @@ static bool TrainLocoHandler(Train *v, b
 

	
 
			/* No more moving this tick */
 
			if (j < adv_spd || v->cur_speed == 0) break;
 

	
 
			OrderType order_type = v->current_order.GetType();
 
			/* Do not skip waypoints (incl. 'via' stations) when passing through at full speed. */
 
			if ((order_type == OT_GOTO_WAYPOINT &&
 
						v->dest_tile == v->tile) ||
 
					(order_type == OT_GOTO_STATION &&
 
			if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
 
						(v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) &&
 
						IsTileType(v->tile, MP_STATION) &&
 
						v->current_order.GetDestination() == GetStationIndex(v->tile))) {
 
						v->current_order.GetDestination() == GetStationIndex(v->tile)) {
 
				ProcessOrders(v);
 
			}
 
		}
 
		SetLastSpeed(v, v->cur_speed);
 
	}
 

	
src/vehicle_gui.cpp
Show inline comments
 
@@ -785,14 +785,12 @@ static void DrawSmallOrderList(const Veh
 

	
 
	FOR_VEHICLE_ORDERS(v, order) {
 
		if (sel == 0) DrawString(left - 6, left, y, STR_SMALL_RIGHT_ARROW, TC_BLACK);
 
		sel--;
 

	
 
		if (order->IsType(OT_GOTO_STATION)) {
 
			if (v->type == VEH_SHIP && Station::Get(order->GetDestination())->IsBuoy()) continue;
 

	
 
			SetDParam(0, order->GetDestination());
 
			DrawString(left, right, y, STR_ORDER_STATION_SMALL);
 

	
 
			y += 6;
 
			if (++i == 4) break;
 
		}
 
@@ -1947,13 +1945,13 @@ struct VehicleViewWindow : Window {
 
					str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
 
					break;
 

	
 
				case OT_GOTO_WAYPOINT: {
 
					assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
 
					SetDParam(0, v->current_order.GetDestination());
 
					str = (v->type == VEH_TRAIN ? STR_HEADING_FOR_WAYPOINT : STR_HEADING_FOR_STATION) + _settings_client.gui.vehicle_speed;
 
					str = STR_HEADING_FOR_WAYPOINT + _settings_client.gui.vehicle_speed;
 
					SetDParam(1, v->GetDisplaySpeed());
 
					break;
 
				}
 

	
 
				case OT_LEAVESTATION:
 
					if (v->type != VEH_AIRCRAFT) {
src/viewport.cpp
Show inline comments
 
@@ -1215,13 +1215,13 @@ static void ViewportAddSigns(DrawPixelIn
 
	}
 
}
 

	
 

	
 
static void AddWaypoint(const Waypoint *wp, StringID str, uint16 width)
 
{
 
	AddStringToDraw(wp->sign.left + 1, wp->sign.top + 1, str, wp->index, 0, (wp->delete_ctr != 0 ? 0xE : _company_colours[wp->owner]), width);
 
	AddStringToDraw(wp->sign.left + 1, wp->sign.top + 1, str, wp->index, 0, (wp->owner == OWNER_NONE || (wp->facilities & ~FACIL_WAYPOINT) == 0) ? 0xE : _company_colours[wp->owner], width);
 
}
 

	
 

	
 
static void ViewportAddWaypoints(DrawPixelInfo *dpi)
 
{
 
	const Waypoint *wp;
src/waypoint.cpp
Show inline comments
 
@@ -9,29 +9,12 @@
 
#include "station_base.h"
 
#include "town.h"
 
#include "waypoint.h"
 
#include "window_func.h"
 
#include "newgrf_station.h"
 
#include "order_func.h"
 
#include "core/pool_func.hpp"
 

	
 
WaypointPool _waypoint_pool("Waypoint");
 
INSTANTIATE_POOL_METHODS(Waypoint)
 

	
 
/**
 
 * Daily loop for waypoints
 
 */
 
void WaypointsDailyLoop()
 
{
 
	Waypoint *wp;
 

	
 
	/* Check if we need to delete a waypoint */
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->delete_ctr != 0 && --wp->delete_ctr == 0) delete wp;
 
	}
 
}
 

	
 
/**
 
 * Draw a waypoint
 
 * @param x coordinate
 
 * @param y coordinate
 
 * @param stat_id station id
 
@@ -64,11 +47,6 @@ Waypoint::~Waypoint()
 
	if (CleaningPool()) return;
 
	DeleteWindowById(WC_WAYPOINT_VIEW, this->index);
 
	RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index);
 

	
 
	this->sign.MarkDirty();
 
}
 

	
 
void InitializeWaypoints()
 
{
 
	_waypoint_pool.CleanPool();
 
}
src/waypoint.h
Show inline comments
 
@@ -11,45 +11,32 @@
 
#include "station_base.h"
 
#include "town_type.h"
 
#include "viewport_type.h"
 
#include "date_type.h"
 
#include "core/pool_type.hpp"
 

	
 
typedef Pool<Waypoint, WaypointID, 32, 64000> WaypointPool;
 
extern WaypointPool _waypoint_pool;
 

	
 
struct Waypoint : WaypointPool::PoolItem<&_waypoint_pool>, SpecializedStation<Waypoint, true> {
 
struct Waypoint : SpecializedStation<Waypoint, true> {
 
	uint16 town_cn;    ///< The Nth waypoint for this town (consecutive number)
 

	
 
	Waypoint(TileIndex tile = INVALID_TILE) : SpecializedStation<Waypoint, true>(tile) { }
 
	~Waypoint();
 

	
 
	void UpdateVirtCoord();
 

	
 
	/* virtual */ FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
 
	{
 
		return this->delete_ctr == 0 && this->xy == tile;
 
		return IsRailWaypointTile(tile) && GetStationIndex(tile) == this->index;
 
	}
 

	
 
	/* virtual */ uint32 GetNewGRFVariable(const struct ResolverObject *object, byte variable, byte parameter, bool *available) const;
 

	
 
	/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
 

	
 
	/**
 
	 * Fetch a waypoint by tile
 
	 * @param tile Tile of waypoint
 
	 * @return Waypoint
 
	 */
 
	static FORCEINLINE Waypoint *GetByTile(TileIndex tile)
 
	{
 
		return Waypoint::Get(GetWaypointIndex(tile));
 
	}
 
};
 

	
 
#define FOR_ALL_WAYPOINTS_FROM(var, start) FOR_ALL_ITEMS_FROM(Waypoint, waypoint_index, var, start)
 
#define FOR_ALL_WAYPOINTS(var) FOR_ALL_WAYPOINTS_FROM(var, 0)
 
#define FOR_ALL_WAYPOINTS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Waypoint, var)
 

	
 
CommandCost RemoveTrainWaypoint(TileIndex tile, DoCommandFlag flags, bool justremove);
 
void ShowWaypointWindow(const Waypoint *wp);
 
void DrawWaypointSprite(int x, int y, int stat_id, RailType railtype);
 
void MakeDefaultWaypointName(Waypoint *wp);
 

	
 
#endif /* WAYPOINT_H */
src/waypoint_cmd.cpp
Show inline comments
 
@@ -36,13 +36,13 @@ void Waypoint::UpdateVirtCoord()
 
}
 

	
 
/**
 
 * Set the default name for a waypoint
 
 * @param wp Waypoint to work on
 
 */
 
static void MakeDefaultWaypointName(Waypoint *wp)
 
void MakeDefaultWaypointName(Waypoint *wp)
 
{
 
	uint32 used = 0; // bitmap of used waypoint numbers, sliding window with 'next' as base
 
	uint32 next = 0; // first waypoint number in the bitmap
 
	WaypointID idx = 0; // index where we will stop
 

	
 
	wp->town = ClosestTownFromTile(wp->xy, UINT_MAX);
 
@@ -61,13 +61,13 @@ static void MakeDefaultWaypointName(Wayp
 
	do {
 
		Waypoint *lwp = Waypoint::Get(cid);
 

	
 
		/* check only valid waypoints... */
 
		if (lwp != NULL && wp != lwp) {
 
			/* only waypoints with 'generic' name within the same city */
 
			if (lwp->name == NULL && lwp->town == wp->town) {
 
			if (lwp->name == NULL && lwp->town == wp->town && lwp->string_id == wp->string_id) {
 
				/* if lwp->town_cn < next, uint will overflow to '+inf' */
 
				uint i = (uint)lwp->town_cn - next;
 

	
 
				if (i < 32) {
 
					SetBit(used, i); // update bitmap
 
					if (i == 0) {
 
@@ -101,13 +101,13 @@ static void MakeDefaultWaypointName(Wayp
 
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
 
{
 
	Waypoint *wp, *best = NULL;
 
	uint thres = 8;
 

	
 
	FOR_ALL_WAYPOINTS(wp) {
 
		if (wp->delete_ctr != 0 && wp->owner == _current_company) {
 
		if ((wp->facilities & ~FACIL_WAYPOINT) == 0 && wp->owner == _current_company) {
 
			uint cur_dist = DistanceManhattan(tile, wp->xy);
 

	
 
			if (cur_dist < thres) {
 
				thres = cur_dist;
 
				best = wp;
 
			}
 
@@ -160,16 +160,12 @@ CommandCost CmdBuildTrainWaypoint(TileIn
 
	wp = FindDeletedWaypointCloseTo(tile);
 
	if (wp == NULL && !Waypoint::CanAllocateItem()) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		if (wp == NULL) {
 
			wp = new Waypoint(tile);
 

	
 
			wp->town = NULL;
 
			wp->name = NULL;
 
			wp->town_cn = 0;
 
		} else {
 
			/* Move existing (recently deleted) waypoint to the new location */
 

	
 
			/* First we update the destination for all vehicles that
 
			 * have the old waypoint in their orders. */
 
			Vehicle *v;
 
@@ -183,21 +179,22 @@ CommandCost CmdBuildTrainWaypoint(TileIn
 
			wp->xy = tile;
 
			InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
 
		}
 
		wp->owner = owner;
 

	
 
		bool reserved = HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis));
 
		MakeRailWaypoint(tile, owner, axis, GetRailType(tile), wp->index);
 
		SetDepotReservation(tile, reserved);
 
		MakeRailWaypoint(tile, owner, wp->index, axis, 0, GetRailType(tile));
 
		SetRailwayStationReservation(tile, reserved);
 
		MarkTileDirtyByTile(tile);
 

	
 
		AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, p1), wp, true);
 
		SetCustomStationSpecIndex(tile, AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, p1), wp, true));
 

	
 
		wp->delete_ctr = 0;
 
		wp->facilities |= FACIL_TRAIN;
 
		wp->build_date = _date;
 
		wp->string_id = STR_SV_STNAME_WAYPOINT;
 

	
 
		if (wp->town == NULL) MakeDefaultWaypointName(wp);
 

	
 
		wp->UpdateVirtCoord();
 
		YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis));
 
	}
 
@@ -221,38 +218,38 @@ CommandCost RemoveTrainWaypoint(TileInde
 
			(!CheckTileOwnership(tile) && _current_company != OWNER_WATER) ||
 
			!EnsureNoVehicleOnGround(tile)) {
 
		return CMD_ERROR;
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		Track track = GetRailWaypointTrack(tile);
 
		Track track = GetRailStationTrack(tile);
 
		wp = Waypoint::GetByTile(tile);
 

	
 
		wp->delete_ctr = 30; // let it live for this many days before we do the actual deletion.
 
		wp->sign.MarkDirty();
 
		wp->facilities &= ~FACIL_TRAIN;
 

	
 
		Train *v = NULL;
 
		uint specindex = GetCustomStationSpecIndex(tile);
 
		if (justremove) {
 
			TrackBits tracks = GetRailWaypointBits(tile);
 
			bool reserved = HasDepotReservation(tile);
 
			TrackBits tracks = GetRailStationTrackBits(tile);
 
			bool reserved = HasStationReservation(tile);
 
			MakeRailNormal(tile, wp->owner, tracks, GetRailType(tile));
 
			if (reserved) SetTrackReservation(tile, tracks);
 
			MarkTileDirtyByTile(tile);
 
		} else {
 
			if (HasDepotReservation(tile)) {
 
			if (HasStationReservation(tile)) {
 
				v = GetTrainForReservation(tile, track);
 
				if (v != NULL) FreeTrainTrackReservation(v);
 
			}
 
			DoClearSquare(tile);
 
			AddTrackToSignalBuffer(tile, track, wp->owner);
 
		}
 
		YapfNotifyTrackLayoutChange(tile, track);
 
		if (v != NULL) TryPathReserve(v, true);
 

	
 
		DeallocateSpecFromStation(wp, wp->num_specs > 0 ? 1 : 0);
 
		DeallocateSpecFromStation(wp, specindex);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot);
 
}
 

	
 
/**
 
@@ -287,13 +284,13 @@ static bool IsUniqueWaypointName(const c
 
 * @param p2 unused
 
 * @return cost of operation or error
 
 */
 
CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Waypoint *wp = Waypoint::GetIfValid(p1);
 
	if (wp == NULL || !CheckOwnership(wp->owner)) return CMD_ERROR;
 
	if (wp == NULL || !(CheckOwnership(wp->owner) || wp->owner == OWNER_NONE)) return CMD_ERROR;
 

	
 
	bool reset = StrEmpty(text);
 

	
 
	if (!reset) {
 
		if (strlen(text) >= MAX_LENGTH_WAYPOINT_NAME_BYTES) return CMD_ERROR;
 
		if (!IsUniqueWaypointName(text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
src/waypoint_gui.cpp
Show inline comments
 
@@ -34,13 +34,13 @@ private:
 
	Waypoint *wp;
 

	
 
public:
 
	WaypointWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 
	{
 
		this->wp = Waypoint::Get(this->window_number);
 
		this->vt = (wp->facilities & FACIL_TRAIN) ? VEH_TRAIN : VEH_SHIP;
 
		this->vt = (wp->string_id == STR_SV_STNAME_WAYPOINT) ? VEH_TRAIN : VEH_SHIP;
 

	
 
		if (this->wp->owner != OWNER_NONE) this->owner = this->wp->owner;
 

	
 
		this->flags4 |= WF_DISABLE_VP_SCROLL;
 
		InitializeWindowViewport(this, 3, 17, 254, 86, this->wp->xy, ZOOM_LVL_MIN);
 

	
src/yapf/yapf_costrail.hpp
Show inline comments
 
@@ -403,13 +403,13 @@ no_entry_cost: // jump here at the begin
 
				/* We don't know yet if the station is our target or not. Act like
 
				 * if it is pass-through station (not our destination). */
 
				segment_cost += Yapf().PfGetSettings().rail_station_penalty * platform_length;
 
				/* We will end in this pass (station is possible target) */
 
				end_segment_reason |= ESRB_STATION;
 

	
 
			} else if (cur.tile_type == MP_RAILWAY && IsRailWaypoint(cur.tile)) {
 
			} else if (cur.tile_type == MP_STATION && IsRailWaypoint(cur.tile)) {
 
				/* Waypoint is also a good reason to finish. */
 
				end_segment_reason |= ESRB_WAYPOINT;
 
			} else if (TrackFollower::DoTrackMasking() && cur.tile_type == MP_RAILWAY) {
 
				/* Searching for a safe tile? */
 
				if (HasSignalOnTrackdir(cur.tile, cur.td) && !IsPbsSignal(GetSignalType(cur.tile, TrackdirToTrack(cur.td)))) {
 
					end_segment_reason |= ESRB_SAFE_TILE;
src/yapf/yapf_destrail.hpp
Show inline comments
 
@@ -131,28 +131,17 @@ public:
 
			case OT_GOTO_STATION:
 
				m_destTile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile);
 
				m_dest_station_id = v->current_order.GetDestination();
 
				m_destTrackdirs = INVALID_TRACKDIR_BIT;
 
				break;
 

	
 
			case OT_GOTO_WAYPOINT: {
 
				Waypoint *wp = Waypoint::Get(v->current_order.GetDestination());
 
				if (wp == NULL) {
 
					/* Invalid waypoint in orders! */
 
					DEBUG(yapf, 0, "Invalid waypoint in orders == 0x%04X (train %d, company %d)", v->current_order.GetDestination(), v->unitnumber, (CompanyID)v->owner);
 
					break;
 
				}
 
				m_destTile = wp->xy;
 
				if (m_destTile != v->dest_tile) {
 
					/* Something is wrong with orders! */
 
					DEBUG(yapf, 0, "Invalid v->dest_tile == 0x%04X (train %d, company %d)", v->dest_tile, v->unitnumber, (CompanyID)v->owner);
 
				}
 
			case OT_GOTO_WAYPOINT:
 
				m_destTile = Waypoint::Get(v->current_order.GetDestination())->xy;
 
				m_dest_station_id = INVALID_STATION;
 
				m_destTrackdirs = TrackToTrackdirBits(AxisToTrack(GetWaypointAxis(wp->xy)));
 
				m_destTrackdirs = IsRailWaypointTile(m_destTile) ? TrackToTrackdirBits(GetRailStationTrack(m_destTile)) : INVALID_TRACKDIR_BIT;
 
				break;
 
			}
 

	
 
			default:
 
				m_destTile = v->dest_tile;
 
				m_dest_station_id = INVALID_STATION;
 
				m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0));
 
				break;
0 comments (0 inline, 0 general)