changeset 12564:5add58f1ce2a draft

(svn r17002) -Change: also support distant join for waypoints
author rubidium <rubidium@openttd.org>
date Fri, 31 Jul 2009 16:28:28 +0000
parents bad474e5cd7e
children 2c356812d90d
files src/lang/english.txt src/rail_gui.cpp src/station_cmd.cpp src/station_gui.cpp src/station_gui.h src/waypoint_cmd.cpp
diffstat 6 files changed, 70 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1586,7 +1586,9 @@
 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
 
 
 
@@ -1819,6 +1821,7 @@
 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
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -776,7 +776,7 @@
 							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;
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -828,7 +828,7 @@
 
 /**
  * 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
@@ -867,6 +867,9 @@
 		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();;
 }
 
@@ -881,12 +884,7 @@
  */
 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);
 }
 
 /**
@@ -1184,7 +1182,7 @@
  * @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>
@@ -1337,7 +1335,7 @@
  * 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>
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -20,6 +20,7 @@
 #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"
@@ -1081,7 +1082,9 @@
  * 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;
@@ -1102,9 +1105,9 @@
 	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)) {
@@ -1123,8 +1126,10 @@
  * @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;
 
@@ -1133,13 +1138,13 @@
 
 	/* 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();
@@ -1149,7 +1154,7 @@
 				/* 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);
 				}
 			}
 		}
@@ -1162,7 +1167,7 @@
 	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;
 }
@@ -1198,6 +1203,11 @@
 	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
@@ -1210,8 +1220,9 @@
 		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);
 	}
 
@@ -1223,7 +1234,7 @@
 
 		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;
 		}
 
@@ -1231,10 +1242,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);
 		}
 	}
 
@@ -1274,7 +1285,7 @@
 
 	virtual void OnInvalidateData(int data)
 	{
-		FindStationsNearby(this->area, true);
+		FindStationsNearby<T>(this->area, true);
 		this->SetDirty();
 	}
 };
@@ -1292,8 +1303,10 @@
  * @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 */
@@ -1319,23 +1332,44 @@
 	/* 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);
+}
--- a/src/station_gui.h
+++ b/src/station_gui.h
@@ -38,5 +38,6 @@
 void CheckRedrawStationCoverage(const Window *w);
 
 void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta);
+void ShowSelectWaypointIfNeeded(CommandContainer cmd, TileArea ta);
 
 #endif /* STATION_GUI_H */
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -225,8 +225,11 @@
 	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;
@@ -246,7 +249,7 @@
 
 	/* 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. */