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.cpp99
1 files changed, 70 insertions, 29 deletions
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index dc898d9bc..acfbc55de 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"
@@ -48,6 +49,7 @@
#include "table/airporttile_ids.h"
#include "newgrf_airporttiles.h"
#include "order_backup.h"
+#include "cargodest_func.h"
#include "newgrf_house.h"
#include "company_gui.h"
#include "widgets/station_widget.h"
@@ -85,24 +87,28 @@ 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, T **st)
+CommandCost GetStationAround(TileArea ta, StationID closest_station, T **st, bool layers=false)
{
ta.tile -= TileDiffXY(1, 1);
ta.w += 2;
ta.h += 2;
/* check around to see if there's any stations there */
- TILE_AREA_LOOP(tile_cur, ta) {
- if (IsTileType(tile_cur, MP_STATION)) {
- StationID t = GetStationIndex(tile_cur);
- if (!T::IsValidID(t)) 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, ta) {
+ TileIndex tile_cur = (layers ? TopTile(tile) + layer*LayerSize() : tile);
+ if (IsTileType(tile_cur, MP_STATION)) {
+ StationID t = GetStationIndex(tile_cur);
+ if (!T::IsValidID(t)) 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();
@@ -656,7 +662,6 @@ static CommandCost BuildStationPart(Station **st, DoCommandFlag flags, bool reus
if (flags & DC_EXEC) {
*st = new Station(area.tile);
-
(*st)->town = ClosestTownFromTile(area.tile, UINT_MAX);
(*st)->string_id = GenerateStationName(*st, area.tile, name_class);
@@ -967,11 +972,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) {
@@ -1043,7 +1050,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;
@@ -1069,7 +1076,7 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
if (check_surrounding) {
/* Make sure there are no similar stations around us. */
- CommandCost ret = GetStationAround(ta, existing_station, st);
+ CommandCost ret = GetStationAround(ta, existing_station, st, layers);
if (ret.Failed()) return ret;
}
@@ -1088,9 +1095,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);
}
/**
@@ -1216,8 +1223,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);
@@ -1497,7 +1506,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, SmallVector<T *, 4> &affected
/* now we need to make the "spanned" area of the railway station smaller
* if we deleted something at the edges.
* we also need to adjust train_tile. */
- MakeRailStationAreaSmaller(st);
+ st->rect.AfterRemoveTile(st, st->xy);
UpdateStationSignCoord(st);
/* if we deleted the whole station, delete the train facility. */
@@ -1590,11 +1599,16 @@ CommandCost RemoveRailStation(T *st, DoCommandFlag flags)
/* 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)) continue;
@@ -1992,11 +2006,20 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
/* Check if the first tile and the last tile are valid */
if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, height - 1) == INVALID_TILE) 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());
int quantity = 0;
CommandCost cost(EXPENSES_CONSTRUCTION);
- 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;
@@ -2173,6 +2196,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;
@@ -3349,6 +3376,17 @@ void OnTick_Station()
TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
}
+
+ if (Station::IsExpected(st)) {
+ /* Age and expire route links. */
+ Station *s = Station::From(st);
+ if (s->index % DAY_TICKS == _date_fract) AgeRouteLinks(s);
+
+ /* Decrement cargo update counter. */
+ for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
+ if (s->goods[cid].cargo_counter > 0) s->goods[cid].cargo_counter--;
+ }
+ }
}
}
@@ -3385,7 +3423,7 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad
}
}
-static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
+uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id, TileIndex dest_tile, SourceType dest_type, SourceID dest_id, OrderID next_hop, StationID next_unload, byte flags)
{
/* We can't allocate a CargoPacket? Then don't do anything
* at all; i.e. just discard the incoming cargo. */
@@ -3399,7 +3437,7 @@ static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceT
/* No new "real" cargo item yet. */
if (amount == 0) return 0;
- ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id));
+ ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id, dest_tile, dest_type, dest_id, next_hop, next_unload, flags));
if (!HasBit(ge.acceptance_pickup, GoodsEntry::GES_PICKUP)) {
InvalidateWindowData(WC_STATION_LIST, st->index);
@@ -3524,11 +3562,14 @@ const StationList *StationFinder::GetStations()
return &this->stations;
}
-uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
+uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations, TileIndex src_tile)
{
/* Return if nothing to do. Also the rounding below fails for 0. */
if (amount == 0) return 0;
+ /* Handle cargo that has cargo destinations enabled. */
+ if (MoveCargoWithDestinationToStation(type, &amount, source_type, source_id, all_stations, src_tile)) return amount;
+
Station *st1 = NULL; // Station with best rating
Station *st2 = NULL; // Second best station
uint best_rating1 = 0; // rating of st1