diff options
Diffstat (limited to 'src/station_cmd.cpp')
-rw-r--r-- | src/station_cmd.cpp | 71 |
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; |