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