mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r17002) -Change: also support distant join for waypoints
This commit is contained in:
parent
097e79a86d
commit
a148a991bb
|
@ -1586,7 +1586,9 @@ STR_RAILROAD_TRACK_WITH_PBS_NOENTRYSIGNALS :Railway track w
|
|||
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_PASSENGER_TRAM_STATION_FIRST :{WHITE}Must dem
|
|||
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
|
||||
|
|
|
@ -776,7 +776,7 @@ struct BuildRailToolbarWindow : Window {
|
|||
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;
|
||||
|
|
|
@ -828,7 +828,7 @@ void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSp
|
|||
|
||||
/**
|
||||
* 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 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
|
|||
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 FindJoiningBaseStation(StationID existing_station, StationID station
|
|||
*/
|
||||
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 @@ restart:
|
|||
* @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 @@ CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint
|
|||
* 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>
|
||||
|
|
|
@ -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 @@ static SmallVector<StationID, 8> _stations_nearby_list;
|
|||
* 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 @@ static bool AddNearbyStation(TileIndex tile, void *user_data)
|
|||
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 @@ static bool AddNearbyStation(TileIndex tile, void *user_data)
|
|||
* @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 @@ static const Station *FindStationsNearby(TileArea ta, bool distant_join)
|
|||
|
||||
/* 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 @@ static const Station *FindStationsNearby(TileArea ta, bool distant_join)
|
|||
/* 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 @@ static const Station *FindStationsNearby(TileArea ta, bool distant_join)
|
|||
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 @@ static const NWidgetPart _nested_select_station_widgets[] = {
|
|||
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 @@ struct SelectStationWindow : Window {
|
|||
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 @@ struct SelectStationWindow : Window {
|
|||
|
||||
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 @@ struct SelectStationWindow : Window {
|
|||
/* 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 @@ struct SelectStationWindow : Window {
|
|||
|
||||
virtual void OnInvalidateData(int data)
|
||||
{
|
||||
FindStationsNearby(this->area, true);
|
||||
FindStationsNearby<T>(this->area, true);
|
||||
this->SetDirty();
|
||||
}
|
||||
};
|
||||
|
@ -1292,8 +1303,10 @@ static const WindowDesc _select_station_desc(
|
|||
* @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 @@ static bool StationJoinerNeeded(CommandContainer cmd, TileArea ta)
|
|||
/* 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);
|
||||
}
|
||||
|
|
|
@ -38,5 +38,6 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageTyp
|
|||
void CheckRedrawStationCoverage(const Window *w);
|
||||
|
||||
void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta);
|
||||
void ShowSelectWaypointIfNeeded(CommandContainer cmd, TileArea ta);
|
||||
|
||||
#endif /* STATION_GUI_H */
|
||||
|
|
|
@ -225,8 +225,11 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
|||
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 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
|||
|
||||
/* 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. */
|
||||
|
|
Loading…
Reference in New Issue