summaryrefslogtreecommitdiff
path: root/src/station_cmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/station_cmd.cpp')
-rw-r--r--src/station_cmd.cpp71
1 files changed, 48 insertions, 23 deletions
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 16f135df2..fa35b2fdf 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -13,6 +13,7 @@
#include "aircraft.h"
#include "bridge_map.h"
#include "cmd_helper.h"
+#include "layer_func.h"
#include "viewport_func.h"
#include "command_func.h"
#include "town.h"
@@ -97,23 +98,26 @@ bool IsHangar(TileIndex t)
* @return Succeeded command (if zero or one station found) or failed command (for two or more stations found).
*/
template <class T>
-CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
+CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st, bool layers=false)
{
ta.tile -= TileDiffXY(1, 1);
ta.w += 2;
ta.h += 2;
/* check around to see if there are any stations there owned by the company */
- TILE_AREA_LOOP(tile_cur, ta) {
- if (IsTileType(tile_cur, MP_STATION)) {
- StationID t = GetStationIndex(tile_cur);
- if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
- if (closest_station == INVALID_STATION) {
- closest_station = t;
- } else if (closest_station != t) {
- return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
+ FOR_ALL_LAYERS(layer) {
+ TILE_AREA_LOOP(tile_cur, ta) {
+ if (IsTileType(tile_cur, MP_STATION)) {
+ StationID t = GetStationIndex(tile_cur);
+ if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
+ if (closest_station == INVALID_STATION) {
+ closest_station = t;
+ } else if (closest_station != t) {
+ return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
+ }
}
}
+ if (!layers) break;
}
*st = (closest_station == INVALID_STATION) ? NULL : T::Get(closest_station);
return CommandCost();
@@ -1004,11 +1008,13 @@ CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis a
TileArea cur_ta = st->train_station;
/* determine new size of train station region.. */
- int x = min(TileX(cur_ta.tile), TileX(new_ta.tile));
- int y = min(TileY(cur_ta.tile), TileY(new_ta.tile));
- new_ta.w = max(TileX(cur_ta.tile) + cur_ta.w, TileX(new_ta.tile) + new_ta.w) - x;
- new_ta.h = max(TileY(cur_ta.tile) + cur_ta.h, TileY(new_ta.tile) + new_ta.h) - y;
- new_ta.tile = TileXY(x, y);
+ /* Фактически, подземная станция ("эскалатор") больше ширины карты.
+ * Поэтому проверям размер в пределах одного слоя */
+ int topx = min(LayerX(cur_ta.tile), LayerX(new_ta.tile));
+ int topy = min(LayerY(cur_ta.tile), LayerY(new_ta.tile));
+ new_ta.w = max(LayerX(cur_ta.tile) + cur_ta.w, LayerX(new_ta.tile) + new_ta.w) - topx;
+ new_ta.h = max(LayerY(cur_ta.tile) + cur_ta.h, LayerY(new_ta.tile) + new_ta.h) - topy;
+ new_ta.tile = TileXY(topx, topy);
/* make sure the final size is not too big. */
if (new_ta.w > _settings_game.station.station_spread || new_ta.h > _settings_game.station.station_spread) {
@@ -1080,7 +1086,7 @@ void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSp
* @return command cost with the error or 'okay'
*/
template <class T, StringID error_message>
-CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
+CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st, bool layers=false)
{
assert(*st == NULL);
bool check_surrounding = true;
@@ -1106,7 +1112,7 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
if (check_surrounding) {
/* Make sure there is no more than one other station around us that is owned by us. */
- CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
+ CommandCost ret = GetStationAround(ta, existing_station, _current_company, st, layers);
if (ret.Failed()) return ret;
}
@@ -1125,9 +1131,9 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
* @param st 'return' pointer for the found station
* @return command cost with the error or 'okay'
*/
-static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
+static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st, bool layers=false)
{
- return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
+ return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st, layers);
}
/**
@@ -1277,8 +1283,10 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
byte numtracks_orig;
Track track;
+ TileIndex top_tile = TopTile(new_location.tile);
st->train_station = new_location;
- st->AddFacility(FACIL_TRAIN, new_location.tile);
+ st->train_station.tile = top_tile;
+ st->AddFacility(FACIL_TRAIN, tile_org);
st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
@@ -1649,11 +1657,16 @@ CommandCost RemoveRailStation(T *st, DoCommandFlag flags, Money removal_cost)
/* determine width and height of platforms */
TileArea ta = st->train_station;
- assert(ta.w != 0 && ta.h != 0);
+ /* TileArea is top finite area */
+ assert(IsTopTile(ta.tile));
+ assert(ta.IsFinite());
CommandCost cost(EXPENSES_CONSTRUCTION);
+ /* Check all layers */
+ FOR_ALL_LAYERS(layer)
/* clear all areas of the station */
- TILE_AREA_LOOP(tile, ta) {
+ TILE_AREA_LOOP(top_tile, ta) {
+ TileIndex tile = top_tile + layer * LayerSize();
/* only remove tiles that are actually train station tiles */
if (st->TileBelongsToRailStation(tile)) {
SmallVector<T*, 4> affected_stations; // dummy
@@ -2027,13 +2040,21 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
/* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
- TileArea roadstop_area(tile, width, height);
+ /* Это территория удаления остановок (НЕ самих остановок) */
+ TileArea roadstop_area(TopTile(tile), width, height);
+
+ /* TileArea is top finite area */
+ assert(IsTopTile(roadstop_area.tile));
+ assert(roadstop_area.IsFinite());
CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
bool had_success = false;
- TILE_AREA_LOOP(cur_tile, roadstop_area) {
+ /* Check all layers */
+ FOR_ALL_LAYERS(layer)
+ TILE_AREA_LOOP(top_tile, roadstop_area) {
+ TileIndex cur_tile = top_tile + layer * LayerSize();
/* Make sure the specified tile is a road stop of the correct type */
if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
@@ -2217,6 +2238,10 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread) {
return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
}
+ /* can't make underground airport */
+ if (IsUnderground(tile)) {
+ return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND);
+ }
CommandCost cost = CheckFlatLand(airport_area, flags);
if (cost.Failed()) return cost;