Changeset - r12554:54cdb18a4143
[Not reviewed]
master
0 6 0
rubidium - 15 years ago 2009-07-31 16:28:28
rubidium@openttd.org
(svn r17002) -Change: also support distant join for waypoints
6 files changed with 70 insertions and 31 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -1583,13 +1583,15 @@ STR_RAILROAD_TRACK_WITH_EXIT_NOENTRYSIGN
 
STR_RAILROAD_TRACK_WITH_COMBO_PBSSIGNALS                        :Railway track with combo- and path signals
 
STR_RAILROAD_TRACK_WITH_COMBO_NOENTRYSIGNALS                    :Railway track with combo- and one-way path signals
 
STR_RAILROAD_TRACK_WITH_PBS_NOENTRYSIGNALS                      :Railway track with path and one-way path signals
 
STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Must remove railway station first
 
STR_MUST_REMOVE_RAILWAYPOINT_FIRST                              :{WHITE}Must remove rail waypoint first
 
STR_CREATE_SPLITTED_STATION                                     :{YELLOW}Build a separate station
 
STR_CREATE_SPLITTED_WAYPOINT                                    :{YELLOW}Build a separate waypoint
 
STR_SELECT_STATION_TO_JOIN                                      :{BLACK}Join station
 
STR_SELECT_WAYPOINT_TO_JOIN                                     :{BLACK}Join waypoint
 

	
 

	
 

	
 
##id 0x1800
 
STR_ERROR_MUST_REMOVE_ROAD_FIRST                                :{WHITE}Must remove road first
 
STR_ROAD_WORKS_IN_PROGRESS                                      :{WHITE}Road works in progress
 
@@ -1816,12 +1818,13 @@ STR_STATION_BUILD_CARGO_TRAM_ORIENTATION
 
STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST                       :{WHITE}Must demolish bus station first
 
STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST                     :{WHITE}Must demolish lorry station first
 
STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST            :{WHITE}Must demolish passenger tram station first
 
STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST                :{WHITE}Must demolish freight tram station first
 
STR_STATION_LIST_CAPTION                                        :{WHITE}{COMPANY} - {COMMA} Station{P "" s}
 
STR_STATION_LIST_STATION                                        :{YELLOW}{STATION} {STATIONFEATURES}
 
STR_STATION_LIST_WAYPOINT                                       :{YELLOW}{WAYPOINT}
 
STR_STATION_LIST_NONE                                           :{YELLOW}- None -
 
STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK                             :{WHITE}Too close to another dock
 
STR_ERROR_MUST_DEMOLISH_DOCK_FIRST                              :{WHITE}Must demolish dock first
 
STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP                  :{BLACK}Select railway station orientation
 
STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP                      :{BLACK}Select number of platforms for railway station
 
STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP                       :{BLACK}Select length of railway station
src/rail_gui.cpp
Show inline comments
 
@@ -773,13 +773,13 @@ struct BuildRailToolbarWindow : Window {
 
						} else {
 
							TileArea ta(start_tile, end_tile);
 
							uint32 p1 = _cur_railtype | (select_method == VPM_FIX_X ? AXIS_X : AXIS_Y) << 4 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24;
 
							uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16;
 

	
 
							CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT), CcPlaySound1E, "" };
 
							DoCommandP(&cmdcont);
 
							ShowSelectWaypointIfNeeded(cmdcont, ta);
 
						}
 
					}
 
					break;
 
			}
 
		}
 
	}
src/station_cmd.cpp
Show inline comments
 
@@ -825,13 +825,13 @@ void GetStationLayout(byte *layout, int 
 
		}
 
	}
 
}
 

	
 
/**
 
 * Find a nearby station that joins this station.
 
 * @param T the class to find a station for
 
 * @tparam T the class to find a station for
 
 * @param error_message the error message when building a station on top of others
 
 * @param existing_station an existing station we build over
 
 * @param station_to_join the station to join to
 
 * @param adjacent whether adjacent stations are allowed
 
 * @param ta the area of the newly build station
 
 * @param st 'return' pointer for the found station
 
@@ -864,12 +864,15 @@ CommandCost FindJoiningBaseStation(Stati
 

	
 
	if (check_surrounding) {
 
		/* Make sure there are no similar stations around us. */
 
		if (!GetStationAround(ta, existing_station, st)) return CMD_ERROR;
 
	}
 

	
 
	/* Distant join */
 
	if (*st == NULL && station_to_join != INVALID_STATION) *st = T::GetIfValid(station_to_join);
 

	
 
	return CommandCost();;
 
}
 

	
 
/**
 
 * Find a nearby station that joins this station.
 
 * @param existing_station an existing station we build over
 
@@ -878,18 +881,13 @@ CommandCost FindJoiningBaseStation(Stati
 
 * @param ta the area of the newly build station
 
 * @param st 'return' pointer for the found station
 
 * @return command cost with the error or 'okay'
 
 */
 
CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
 
{
 
	CommandCost cost = FindJoiningBaseStation<Station, STR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
 

	
 
	/* Distant join */
 
	if (*st == NULL && station_to_join != INVALID_STATION) *st = Station::GetIfValid(station_to_join);
 

	
 
	return cost;
 
	return FindJoiningBaseStation<Station, STR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
 
}
 

	
 
/**
 
 * Find a nearby waypoint that joins this waypoint.
 
 * @param existing_waypoint an existing waypoint we build over
 
 * @param waypoint_to_join the waypoint to join to
 
@@ -1181,13 +1179,13 @@ restart:
 
/**
 
 * Remove a number of tiles from any rail station within the area.
 
 * @param ta the area to clear station tile from
 
 * @param affected_stations the stations affected
 
 * @param flags the command flags
 
 * @param removal_cost the cost for removing the tile
 
 * @param T the type of station to remove
 
 * @tparam T the type of station to remove
 
 * @return the number of cleared tiles or an error
 
 */
 
template <class T>
 
CommandCost RemoveFromRailBaseStation(TileArea ta, SmallVector<T *, 4> &affected_stations, DoCommandFlag flags, Money removal_cost)
 
{
 
	/* Count of the number of tiles removed */
 
@@ -1334,13 +1332,13 @@ CommandCost CmdRemoveFromRailWaypoint(Ti
 

	
 

	
 
/**
 
 * Remove a rail road station/waypoint
 
 * @param st The station/waypoint to remove the rail part from
 
 * @param flags operation to perform
 
 * @param T the type of station to remove
 
 * @tparam T the type of station to remove
 
 * @return cost or failure of operation
 
 */
 
template <class T>
 
CommandCost RemoveRailStation(T *st, DoCommandFlag flags)
 
{
 
	/* Current company owns the station? */
src/station_gui.cpp
Show inline comments
 
@@ -17,12 +17,13 @@
 
#include "window_func.h"
 
#include "viewport_func.h"
 
#include "gfx_func.h"
 
#include "widgets/dropdown_func.h"
 
#include "newgrf_cargo.h"
 
#include "station_base.h"
 
#include "waypoint_base.h"
 
#include "tilehighlight_func.h"
 
#include "core/smallmap_type.hpp"
 
#include "company_base.h"
 
#include "sortlist_type.h"
 
#include "settings_type.h"
 

	
 
@@ -1078,13 +1079,15 @@ static SmallVector<StationID, 8> _statio
 

	
 
/**
 
 * Add station on this tile to _stations_nearby_list if it's fully within the
 
 * station spread.
 
 * @param tile Tile just being checked
 
 * @param user_data Pointer to TileArea context
 
 * @tparam T the type of station to look for
 
 */
 
template <class T>
 
static bool AddNearbyStation(TileIndex tile, void *user_data)
 
{
 
	TileArea *ctx = (TileArea *)user_data;
 

	
 
	/* First check if there were deleted stations here */
 
	for (uint i = 0; i < _deleted_stations_nearby.Length(); i++) {
 
@@ -1099,15 +1102,15 @@ static bool AddNearbyStation(TileIndex t
 
	/* Check if own station and if we stay within station spread */
 
	if (!IsTileType(tile, MP_STATION)) return false;
 

	
 
	StationID sid = GetStationIndex(tile);
 

	
 
	/* This station is (likely) a waypoint */
 
	if (!Station::IsValidID(sid)) return false;
 
	if (!T::IsValidID(sid)) return false;
 

	
 
	Station *st = Station::Get(sid);
 
	T *st = T::Get(sid);
 
	if (st->owner != _local_company || _stations_nearby_list.Contains(sid)) return false;
 

	
 
	if (st->rect.BeforeAddRect(ctx->tile, ctx->w, ctx->h, StationRect::ADD_TEST)) {
 
		*_stations_nearby_list.Append() = sid;
 
	}
 

	
 
@@ -1120,52 +1123,54 @@ static bool AddNearbyStation(TileIndex t
 
 * station spread and are our own station.
 
 * @param tile Base tile of the to-be-built station
 
 * @param w Width of the to-be-built station
 
 * @param h Height of the to-be-built station
 
 * @param distant_join Search for adjacent stations (false) or stations fully
 
 *                     within station spread
 
 * @tparam T the type of station to look for
 
 **/
 
static const Station *FindStationsNearby(TileArea ta, bool distant_join)
 
template <class T>
 
static const T *FindStationsNearby(TileArea ta, bool distant_join)
 
{
 
	TileArea ctx = ta;
 

	
 
	_stations_nearby_list.Clear();
 
	_deleted_stations_nearby.Clear();
 

	
 
	/* Check the inside, to return, if we sit on another station */
 
	TILE_LOOP(t, ta.w, ta.h, ta.tile) {
 
		if (t < MapSize() && IsTileType(t, MP_STATION) && Station::IsValidID(GetStationIndex(t))) return Station::GetByTile(t);
 
		if (t < MapSize() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return T::GetByTile(t);
 
	}
 

	
 
	/* Look for deleted stations */
 
	const BaseStation *st;
 
	FOR_ALL_BASE_STATIONS(st) {
 
		if (Station::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) {
 
		if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) {
 
			/* Include only within station spread (yes, it is strictly less than) */
 
			if (max(DistanceMax(ta.tile, st->xy), DistanceMax(TILE_ADDXY(ta.tile, ta.w - 1, ta.h - 1), st->xy)) < _settings_game.station.station_spread) {
 
				TileAndStation *ts = _deleted_stations_nearby.Append();
 
				ts->tile = st->xy;
 
				ts->station = st->index;
 

	
 
				/* Add the station when it's within where we're going to build */
 
				if (IsInsideBS(TileX(st->xy), TileX(ctx.tile), ctx.w) &&
 
						IsInsideBS(TileY(st->xy), TileY(ctx.tile), ctx.h)) {
 
					AddNearbyStation(st->xy, &ctx);
 
					AddNearbyStation<T>(st->xy, &ctx);
 
				}
 
			}
 
		}
 
	}
 

	
 
	/* Only search tiles where we have a chance to stay within the station spread.
 
	 * The complete check needs to be done in the callback as we don't know the
 
	 * extent of the found station, yet. */
 
	if (distant_join && min(ta.w, ta.h) >= _settings_game.station.station_spread) return NULL;
 
	uint max_dist = distant_join ? _settings_game.station.station_spread - min(ta.w, ta.h) : 1;
 

	
 
	TileIndex tile = TILE_ADD(ctx.tile, TileOffsByDir(DIR_N));
 
	CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation, &ctx);
 
	CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation<T>, &ctx);
 

	
 
	return NULL;
 
}
 

	
 
enum JoinStationWidgets {
 
	JSW_WIDGET_CLOSEBOX = 0,
 
@@ -1195,49 +1200,55 @@ static const NWidgetPart _nested_select_
 
			NWidget(WWT_SCROLLBAR, COLOUR_DARK_GREEN, JSW_SCROLLBAR),
 
			NWidget(WWT_RESIZEBOX, COLOUR_DARK_GREEN, JSW_RESIZEBOX),
 
		EndContainer(),
 
	EndContainer(),
 
};
 

	
 
/**
 
 * Window for selecting stations/waypoints to (distant) join to.
 
 * @tparam T The type of station to join with
 
 */
 
template <class T>
 
struct SelectStationWindow : Window {
 
	CommandContainer select_station_cmd; ///< Command to build new station
 
	TileArea area; ///< Location of new station
 

	
 
	SelectStationWindow(const WindowDesc *desc, CommandContainer cmd, TileArea ta) :
 
		Window(desc, 0),
 
		select_station_cmd(cmd),
 
		area(ta)
 
	{
 
		this->vscroll.cap = 6;
 
		this->resize.step_height = 10;
 

	
 
		FindStationsNearby(this->area, true);
 
		FindStationsNearby<T>(this->area, true);
 

	
 
		this->widget[JSW_WIDGET_CAPTION].data = T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_SELECT_WAYPOINT_TO_JOIN : STR_SELECT_STATION_TO_JOIN;
 
		this->FindWindowPlacementAndResize(desc);
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		SetVScrollCount(this, _stations_nearby_list.Length() + 1);
 

	
 
		this->DrawWidgets();
 

	
 
		uint y = 17;
 
		if (this->vscroll.pos == 0) {
 
			DrawString(3, this->widget[JSW_PANEL].right - 2, y, STR_CREATE_SPLITTED_STATION);
 
			DrawString(3, this->widget[JSW_PANEL].right - 2, y, T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_CREATE_SPLITTED_WAYPOINT : STR_CREATE_SPLITTED_STATION);
 
			y += 10;
 
		}
 

	
 
		for (uint i = max<uint>(1, this->vscroll.pos); i <= _stations_nearby_list.Length(); ++i, y += 10) {
 
			/* Don't draw anything if it extends past the end of the window. */
 
			if (i - this->vscroll.pos >= this->vscroll.cap) break;
 

	
 
			const Station *st = Station::Get(_stations_nearby_list[i - 1]);
 
			const T *st = T::Get(_stations_nearby_list[i - 1]);
 
			SetDParam(0, st->index);
 
			SetDParam(1, st->facilities);
 
			DrawString(3, this->widget[JSW_PANEL].right - 2, y, STR_STATION_LIST_STATION);
 
			DrawString(3, this->widget[JSW_PANEL].right - 2, y, T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION);
 
		}
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		if (widget != JSW_PANEL) return;
 
@@ -1271,13 +1282,13 @@ struct SelectStationWindow : Window {
 
	{
 
		this->vscroll.cap = (this->widget[JSW_PANEL].bottom - this->widget[JSW_PANEL].top) / 10;
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		FindStationsNearby(this->area, true);
 
		FindStationsNearby<T>(this->area, true);
 
		this->SetDirty();
 
	}
 
};
 

	
 
static const WindowDesc _select_station_desc(
 
	WDP_AUTO, WDP_AUTO, 200, 80, 200, 180,
 
@@ -1289,14 +1300,16 @@ static const WindowDesc _select_station_
 

	
 
/**
 
 * Check whether we need to show the station selection window.
 
 * @param cmd Command to build the station.
 
 * @param w Width of the to-be-built station
 
 * @param h Height of the to-be-built station
 
 * @tparam T the type of station
 
 * @return whether we need to show the station selection window.
 
 */
 
template <class T>
 
static bool StationJoinerNeeded(CommandContainer cmd, TileArea ta)
 
{
 
	/* Only show selection if distant join is enabled in the settings */
 
	if (!_settings_game.station.distant_join_stations) return false;
 

	
 
	/* If a window is already opened and we didn't ctrl-click,
 
@@ -1316,26 +1329,47 @@ static bool StationJoinerNeeded(CommandC
 
	/* Now check if we could build there */
 
	if (CmdFailed(DoCommand(&cmd, CommandFlagsToDCFlags(GetCommandFlags(cmd.cmd))))) return false;
 

	
 
	/* Test for adjacent station or station below selection.
 
	 * If adjacent-stations is disabled and we are building next to a station, do not show the selection window.
 
	 * but join the other station immediatelly. */
 
	const Station *st = FindStationsNearby(ta, false);
 
	const T *st = FindStationsNearby<T>(ta, false);
 
	return st == NULL && (_settings_game.station.adjacent_stations || _stations_nearby_list.Length() == 0);
 
}
 

	
 
/**
 
 * Show the station selection window when needed. If not, build the station.
 
 * @param cmd Command to build the station.
 
 * @param w Width of the to-be-built station
 
 * @param h Height of the to-be-built station
 
 * @param ta Area to build the station in
 
 * @tparam the class to find stations for
 
 */
 
void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta)
 
template <class T>
 
void ShowSelectBaseStationIfNeeded(CommandContainer cmd, TileArea ta)
 
{
 
	if (StationJoinerNeeded(cmd, ta)) {
 
	if (StationJoinerNeeded<T>(cmd, ta)) {
 
		if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
 
		if (BringWindowToFrontById(WC_SELECT_STATION, 0)) return;
 
		new SelectStationWindow(&_select_station_desc, cmd, ta);
 
		new SelectStationWindow<T>(&_select_station_desc, cmd, ta);
 
	} else {
 
		DoCommandP(&cmd);
 
	}
 
}
 

	
 
/**
 
 * Show the station selection window when needed. If not, build the station.
 
 * @param cmd Command to build the station.
 
 * @param ta Area to build the station in
 
 */
 
void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta)
 
{
 
	ShowSelectBaseStationIfNeeded<Station>(cmd, ta);
 
}
 

	
 
/**
 
 * Show the waypoint selection window when needed. If not, build the waypoint.
 
 * @param cmd Command to build the waypoint.
 
 * @param ta Area to build the waypoint in
 
 */
 
void ShowSelectWaypointIfNeeded(CommandContainer cmd, TileArea ta)
 
{
 
	ShowSelectBaseStationIfNeeded<Waypoint>(cmd, ta);
 
}
src/station_gui.h
Show inline comments
 
@@ -35,8 +35,9 @@ enum StationCoverageType {
 
};
 

	
 
int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageType sct, int rad, bool supplies);
 
void CheckRedrawStationCoverage(const Window *w);
 

	
 
void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta);
 
void ShowSelectWaypointIfNeeded(CommandContainer cmd, TileArea ta);
 

	
 
#endif /* STATION_GUI_H */
src/waypoint_cmd.cpp
Show inline comments
 
@@ -222,14 +222,17 @@ CommandCost CmdBuildRailWaypoint(TileInd
 
	/* The number of parts to build */
 
	byte count = axis == AXIS_X ? height : width;
 

	
 
	if ((axis == AXIS_X ? width : height) != 1) return CMD_ERROR;
 
	if (count == 0 || count > _settings_game.station.station_spread) return CMD_ERROR;
 

	
 
	/* Temporary */
 
	if (station_to_join != INVALID_STATION) return CMD_ERROR;
 
	bool reuse = (station_to_join != NEW_STATION);
 
	if (!reuse) station_to_join = INVALID_STATION;
 
	bool distant_join = (station_to_join != INVALID_STATION);
 

	
 
	if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
 

	
 
	/* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
 
	StationID est = INVALID_STATION;
 

	
 
	/* Check whether the tiles we're building on are valid rail or not. */
 
	TileIndexDiff offset = TileOffsByDiagDir(AxisToDiagDir(OtherAxis(axis)));
 
@@ -243,13 +246,13 @@ CommandCost CmdBuildRailWaypoint(TileInd
 
	TileArea new_location(TileArea(start_tile, width, height));
 
	CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, new_location, &wp);
 
	if (ret.Failed()) return ret;
 

	
 
	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
 
	TileIndex center_tile = start_tile + (count / 2) * offset;
 
	if (wp == NULL) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT);
 
	if (wp == NULL && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT);
 

	
 
	if (wp != NULL) {
 
		/* Reuse an existing station. */
 
		if (wp->owner != _current_company) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT);
 

	
 
		/* check if we want to expanding an already existing station? */
0 comments (0 inline, 0 general)