OpenTTD Source  20241120-master-g6d3adc6169
station.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "company_func.h"
12 #include "company_base.h"
13 #include "roadveh.h"
14 #include "viewport_func.h"
15 #include "viewport_kdtree.h"
16 #include "command_func.h"
17 #include "news_func.h"
18 #include "aircraft.h"
19 #include "vehiclelist.h"
20 #include "core/pool_func.hpp"
21 #include "station_base.h"
22 #include "station_kdtree.h"
23 #include "roadstop_base.h"
24 #include "industry.h"
25 #include "town.h"
26 #include "core/random_func.hpp"
27 #include "linkgraph/linkgraph.h"
29 
30 #include "table/strings.h"
31 
32 #include "safeguards.h"
33 
37 
38 
39 StationKdtree _station_kdtree{};
40 
41 void RebuildStationKdtree()
42 {
43  std::vector<StationID> stids;
44  for (const Station *st : Station::Iterate()) {
45  stids.push_back(st->index);
46  }
47  _station_kdtree.Build(stids.begin(), stids.end());
48 }
49 
50 
51 BaseStation::~BaseStation()
52 {
53  if (CleaningPool()) return;
54 
55  CloseWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->index).Pack());
56  CloseWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->index).Pack());
57  CloseWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).Pack());
58  CloseWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).Pack());
59 
60  this->sign.MarkDirty();
61 }
62 
63 Station::Station(TileIndex tile) :
64  SpecializedStation<Station, false>(tile),
65  bus_station(INVALID_TILE, 0, 0),
66  truck_station(INVALID_TILE, 0, 0),
67  ship_station(INVALID_TILE, 0, 0),
68  indtype(IT_INVALID),
69  time_since_load(255),
70  time_since_unload(255),
71  last_vehicle_type(VEH_INVALID)
72 {
73  /* this->random_bits is set in Station::AddFacility() */
74 }
75 
84 {
85  if (CleaningPool()) {
86  for (GoodsEntry &ge : this->goods) {
87  ge.cargo.OnCleanPool();
88  }
89  return;
90  }
91 
92  while (!this->loading_vehicles.empty()) {
93  this->loading_vehicles.front()->LeaveStation();
94  }
95 
96  for (Aircraft *a : Aircraft::Iterate()) {
97  if (!a->IsNormalAircraft()) continue;
98  if (a->targetairport == this->index) a->targetairport = INVALID_STATION;
99  }
100 
101  for (CargoID c = 0; c < NUM_CARGO; ++c) {
102  LinkGraph *lg = LinkGraph::GetIfValid(this->goods[c].link_graph);
103  if (lg == nullptr) continue;
104 
105  for (NodeID node = 0; node < lg->Size(); ++node) {
106  Station *st = Station::Get((*lg)[node].station);
107  st->goods[c].flows.erase(this->index);
108  if ((*lg)[node].HasEdgeTo(this->goods[c].node) && (*lg)[node][this->goods[c].node].LastUpdate() != EconomyTime::INVALID_DATE) {
109  st->goods[c].flows.DeleteFlows(this->index);
110  RerouteCargo(st, c, this->index, st->index);
111  }
112  }
113  lg->RemoveNode(this->goods[c].node);
114  if (lg->Size() == 0) {
116  delete lg;
117  }
118  }
119 
120  for (Vehicle *v : Vehicle::Iterate()) {
121  /* Forget about this station if this station is removed */
122  if (v->last_station_visited == this->index) {
123  v->last_station_visited = INVALID_STATION;
124  }
125  if (v->last_loading_station == this->index) {
126  v->last_loading_station = INVALID_STATION;
127  }
128  }
129 
130  /* Remove station from industries and towns that reference it. */
131  this->RemoveFromAllNearbyLists();
132 
133  /* Clear the persistent storage. */
134  delete this->airport.psa;
135 
136  if (this->owner == OWNER_NONE) {
137  /* Invalidate all in case of oil rigs. */
139  } else {
141  }
142 
144 
145  /* Now delete all orders that go to the station */
146  RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index);
147 
148  /* Remove all news items */
149  DeleteStationNews(this->index);
150 
151  for (GoodsEntry &ge : this->goods) {
152  ge.cargo.Truncate();
153  }
154 
156 
157  _station_kdtree.Remove(this->index);
158  if (this->sign.kdtree_valid) _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeStation(this->index));
159 }
160 
161 
167 {
169 }
170 
171 bool BaseStation::SetRoadStopTileData(TileIndex tile, uint8_t data, bool animation)
172 {
173  for (RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
174  if (tile_data.tile == tile) {
175  uint8_t &v = animation ? tile_data.animation_frame : tile_data.random_bits;
176  if (v == data) return false;
177  v = data;
178  return true;
179  }
180  }
181  RoadStopTileData tile_data;
182  tile_data.tile = tile;
183  tile_data.animation_frame = animation ? data : 0;
184  tile_data.random_bits = animation ? 0 : data;
185  this->custom_roadstop_tile_data.push_back(tile_data);
186  return data != 0;
187 }
188 
189 void BaseStation::RemoveRoadStopTileData(TileIndex tile)
190 {
191  for (RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
192  if (tile_data.tile == tile) {
193  tile_data = this->custom_roadstop_tile_data.back();
194  this->custom_roadstop_tile_data.pop_back();
195  return;
196  }
197  }
198 }
199 
205 RoadStop *Station::GetPrimaryRoadStop(const RoadVehicle *v) const
206 {
207  RoadStop *rs = this->GetPrimaryRoadStop(v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK);
208 
209  for (; rs != nullptr; rs = rs->next) {
210  /* The vehicle cannot go to this roadstop (different roadtype) */
211  if (!HasTileAnyRoadType(rs->xy, v->compatible_roadtypes)) continue;
212  /* The vehicle is articulated and can therefore not go to a standard road stop. */
213  if (IsBayRoadStopTile(rs->xy) && v->HasArticulatedPart()) continue;
214 
215  /* The vehicle can actually go to this road stop. So, return it! */
216  break;
217  }
218 
219  return rs;
220 }
221 
226 void Station::AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
227 {
228  if (this->facilities == FACIL_NONE) {
229  this->MoveSign(facil_xy);
230  this->random_bits = Random();
231  }
232  this->facilities |= new_facility_bit;
233  this->owner = _current_company;
236 }
237 
243 void Station::MarkTilesDirty(bool cargo_change) const
244 {
245  if (this->train_station.tile == INVALID_TILE) return;
246 
247  /* cargo_change is set if we're refreshing the tiles due to cargo moving
248  * around. */
249  if (cargo_change) {
250  /* Don't waste time updating if there are no custom station graphics
251  * that might change. Even if there are custom graphics, they might
252  * not change. Unfortunately we have no way of telling. */
253  if (this->speclist.empty()) return;
254  }
255 
256  for (TileIndex tile : this->train_station) {
257  if (this->TileBelongsToRailStation(tile)) {
258  MarkTileDirtyByTile(tile);
259  }
260  }
261 }
262 
263 /* virtual */ uint Station::GetPlatformLength(TileIndex tile) const
264 {
265  assert(this->TileBelongsToRailStation(tile));
266 
268 
269  TileIndex t = tile;
270  uint len = 0;
271  do {
272  t -= delta;
273  len++;
274  } while (IsCompatibleTrainStationTile(t, tile));
275 
276  t = tile;
277  do {
278  t += delta;
279  len++;
280  } while (IsCompatibleTrainStationTile(t, tile));
281 
282  return len - 1;
283 }
284 
285 /* virtual */ uint Station::GetPlatformLength(TileIndex tile, DiagDirection dir) const
286 {
287  TileIndex start_tile = tile;
288  uint length = 0;
289  assert(IsRailStationTile(tile));
290  assert(dir < DIAGDIR_END);
291 
292  do {
293  length++;
294  tile += TileOffsByDiagDir(dir);
295  } while (IsCompatibleTrainStationTile(tile, start_tile));
296 
297  return length;
298 }
299 
307 static uint GetTileCatchmentRadius(TileIndex tile, const Station *st)
308 {
309  assert(IsTileType(tile, MP_STATION));
310 
312  switch (GetStationType(tile)) {
313  case STATION_RAIL: return CA_TRAIN;
314  case STATION_OILRIG: return CA_UNMODIFIED;
315  case STATION_AIRPORT: return st->airport.GetSpec()->catchment;
316  case STATION_TRUCK: return CA_TRUCK;
317  case STATION_BUS: return CA_BUS;
318  case STATION_DOCK: return CA_DOCK;
319 
320  default: NOT_REACHED();
321  case STATION_BUOY:
322  case STATION_WAYPOINT:
323  case STATION_ROADWAYPOINT: return CA_NONE;
324  }
325  } else {
326  switch (GetStationType(tile)) {
327  default: return CA_UNMODIFIED;
328  case STATION_BUOY:
329  case STATION_WAYPOINT:
330  case STATION_ROADWAYPOINT: return CA_NONE;
331  }
332  }
333 }
334 
340 {
341  uint ret = CA_NONE;
342 
344  if (this->bus_stops != nullptr) ret = std::max<uint>(ret, CA_BUS);
345  if (this->truck_stops != nullptr) ret = std::max<uint>(ret, CA_TRUCK);
346  if (this->train_station.tile != INVALID_TILE) ret = std::max<uint>(ret, CA_TRAIN);
347  if (this->ship_station.tile != INVALID_TILE) ret = std::max<uint>(ret, CA_DOCK);
348  if (this->airport.tile != INVALID_TILE) ret = std::max<uint>(ret, this->airport.GetSpec()->catchment);
349  } else {
350  if (this->bus_stops != nullptr || this->truck_stops != nullptr || this->train_station.tile != INVALID_TILE || this->ship_station.tile != INVALID_TILE || this->airport.tile != INVALID_TILE) {
351  ret = CA_UNMODIFIED;
352  }
353  }
354 
355  return ret;
356 }
357 
363 {
364  assert(!this->rect.IsEmpty());
365 
366  /* Compute acceptance rectangle */
367  int catchment_radius = this->GetCatchmentRadius();
368 
369  Rect ret = {
370  std::max<int>(this->rect.left - catchment_radius, 0),
371  std::max<int>(this->rect.top - catchment_radius, 0),
372  std::min<int>(this->rect.right + catchment_radius, Map::MaxX()),
373  std::min<int>(this->rect.bottom + catchment_radius, Map::MaxY())
374  };
375 
376  return ret;
377 }
378 
386 {
387  /* Using DistanceMax to get about the same order as with previously used CircularTileSearch. */
388  uint distance = DistanceMax(this->xy, tile);
389 
390  /* Don't check further if this industry is already in the list but update the distance if it's closer */
391  auto pos = std::find_if(this->industries_near.begin(), this->industries_near.end(), [&](const IndustryListEntry &e) { return e.industry->index == ind->index; });
392  if (pos != this->industries_near.end()) {
393  if (pos->distance > distance) {
394  auto node = this->industries_near.extract(pos);
395  node.value().distance = distance;
396  this->industries_near.insert(std::move(node));
397  }
398  return;
399  }
400 
401  /* Include only industries that can accept cargo */
402  if (!ind->IsCargoAccepted()) return;
403 
404  this->industries_near.insert(IndustryListEntry{distance, ind});
405 }
406 
412 {
413  auto pos = std::find_if(this->industries_near.begin(), this->industries_near.end(), [&](const IndustryListEntry &e) { return e.industry->index == ind->index; });
414  if (pos != this->industries_near.end()) {
415  this->industries_near.erase(pos);
416  }
417 }
418 
419 
424 {
425  std::set<TownID> towns;
426  std::set<IndustryID> industries;
427 
428  for (const auto &tile : this->catchment_tiles) {
429  TileType type = GetTileType(tile);
430  if (type == MP_HOUSE) {
431  towns.insert(GetTownIndex(tile));
432  } else if (type == MP_INDUSTRY) {
433  industries.insert(GetIndustryIndex(tile));
434  }
435  }
436 
437  for (const TownID &townid : towns) { Town::Get(townid)->stations_near.erase(this); }
438  for (const IndustryID &industryid : industries) { Industry::Get(industryid)->stations_near.erase(this); }
439 }
440 
448 bool Station::CatchmentCoversTown(TownID t) const
449 {
451  for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
452  if (IsTileType(tile, MP_HOUSE) && GetTownIndex(tile) == t) return true;
453  }
454  return false;
455 }
456 
462 void Station::RecomputeCatchment(bool no_clear_nearby_lists)
463 {
464  this->industries_near.clear();
465  if (!no_clear_nearby_lists) this->RemoveFromAllNearbyLists();
466 
467  if (this->rect.IsEmpty()) {
468  this->catchment_tiles.Reset();
469  return;
470  }
471 
472  if (!_settings_game.station.serve_neutral_industries && this->industry != nullptr) {
473  /* Station is associated with an industry, so we only need to deliver to that industry. */
475  for (TileIndex tile : this->industry->location) {
476  if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == this->industry->index) {
477  this->catchment_tiles.SetTile(tile);
478  }
479  }
480  /* The industry's stations_near may have been computed before its neutral station was built so clear and re-add here. */
481  for (Station *st : this->industry->stations_near) {
483  }
484  this->industry->stations_near.clear();
485  this->industry->stations_near.insert(this);
486  this->industries_near.insert(IndustryListEntry{0, this->industry});
487  return;
488  }
489 
491 
492  /* Loop finding all station tiles */
493  TileArea ta(TileXY(this->rect.left, this->rect.top), TileXY(this->rect.right, this->rect.bottom));
494  for (TileIndex tile : ta) {
495  if (!IsTileType(tile, MP_STATION) || GetStationIndex(tile) != this->index) continue;
496 
497  uint r = GetTileCatchmentRadius(tile, this);
498  if (r == CA_NONE) continue;
499 
500  /* This tile sub-loop doesn't need to test any tiles, they are simply added to the catchment set. */
501  TileArea ta2 = TileArea(tile, 1, 1).Expand(r);
502  for (TileIndex tile2 : ta2) this->catchment_tiles.SetTile(tile2);
503  }
504 
505  /* Search catchment tiles for towns and industries */
507  for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
508  if (IsTileType(tile, MP_HOUSE)) {
509  Town *t = Town::GetByTile(tile);
510  t->stations_near.insert(this);
511  }
512  if (IsTileType(tile, MP_INDUSTRY)) {
513  Industry *i = Industry::GetByTile(tile);
514 
515  /* Ignore industry if it has a neutral station. It already can't be this station. */
516  if (!_settings_game.station.serve_neutral_industries && i->neutral_station != nullptr) continue;
517 
518  i->stations_near.insert(this);
519 
520  /* Add if we can deliver to this industry as well */
521  this->AddIndustryToDeliver(i, tile);
522  }
523  }
524 }
525 
531 {
532  for (Town *t : Town::Iterate()) { t->stations_near.clear(); }
533  for (Industry *i : Industry::Iterate()) { i->stations_near.clear(); }
534  for (Station *st : Station::Iterate()) { st->RecomputeCatchment(true); }
535 }
536 
537 /************************************************************************/
538 /* StationRect implementation */
539 /************************************************************************/
540 
541 StationRect::StationRect()
542 {
543  this->MakeEmpty();
544 }
545 
546 void StationRect::MakeEmpty()
547 {
548  this->left = this->top = this->right = this->bottom = 0;
549 }
550 
560 bool StationRect::PtInExtendedRect(int x, int y, int distance) const
561 {
562  return this->left - distance <= x && x <= this->right + distance &&
563  this->top - distance <= y && y <= this->bottom + distance;
564 }
565 
566 bool StationRect::IsEmpty() const
567 {
568  return this->left == 0 || this->left > this->right || this->top > this->bottom;
569 }
570 
571 CommandCost StationRect::BeforeAddTile(TileIndex tile, StationRectMode mode)
572 {
573  int x = TileX(tile);
574  int y = TileY(tile);
575  if (this->IsEmpty()) {
576  /* we are adding the first station tile */
577  if (mode != ADD_TEST) {
578  this->left = this->right = x;
579  this->top = this->bottom = y;
580  }
581  } else if (!this->PtInExtendedRect(x, y)) {
582  /* current rect is not empty and new point is outside this rect
583  * make new spread-out rectangle */
584  Rect new_rect = {std::min(x, this->left), std::min(y, this->top), std::max(x, this->right), std::max(y, this->bottom)};
585 
586  /* check new rect dimensions against preset max */
587  int w = new_rect.Width();
588  int h = new_rect.Height();
589  if (mode != ADD_FORCE && (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread)) {
590  assert(mode != ADD_TRY);
591  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
592  }
593 
594  /* spread-out ok, return true */
595  if (mode != ADD_TEST) {
596  /* we should update the station rect */
597  *this = new_rect;
598  }
599  } else {
600  ; // new point is inside the rect, we don't need to do anything
601  }
602  return CommandCost();
603 }
604 
605 CommandCost StationRect::BeforeAddRect(TileIndex tile, int w, int h, StationRectMode mode)
606 {
607  if (mode == ADD_FORCE || (w <= _settings_game.station.station_spread && h <= _settings_game.station.station_spread)) {
608  /* Important when the old rect is completely inside the new rect, resp. the old one was empty. */
609  CommandCost ret = this->BeforeAddTile(tile, mode);
610  if (ret.Succeeded()) ret = this->BeforeAddTile(TileAddXY(tile, w - 1, h - 1), mode);
611  return ret;
612  }
613  return CommandCost();
614 }
615 
625 /* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
626 {
627  TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a));
628  for (TileIndex tile : ta) {
629  if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
630  }
631 
632  return false;
633 }
634 
635 bool StationRect::AfterRemoveTile(BaseStation *st, TileIndex tile)
636 {
637  int x = TileX(tile);
638  int y = TileY(tile);
639 
640  /* look if removed tile was on the bounding rect edge
641  * and try to reduce the rect by this edge
642  * do it until we have empty rect or nothing to do */
643  for (;;) {
644  /* check if removed tile is on rect edge */
645  bool left_edge = (x == this->left);
646  bool right_edge = (x == this->right);
647  bool top_edge = (y == this->top);
648  bool bottom_edge = (y == this->bottom);
649 
650  /* can we reduce the rect in either direction? */
651  bool reduce_x = ((left_edge || right_edge) && !ScanForStationTiles(st->index, x, this->top, x, this->bottom));
652  bool reduce_y = ((top_edge || bottom_edge) && !ScanForStationTiles(st->index, this->left, y, this->right, y));
653  if (!(reduce_x || reduce_y)) break; // nothing to do (can't reduce)
654 
655  if (reduce_x) {
656  /* reduce horizontally */
657  if (left_edge) {
658  /* move left edge right */
659  this->left = x = x + 1;
660  } else {
661  /* move right edge left */
662  this->right = x = x - 1;
663  }
664  }
665  if (reduce_y) {
666  /* reduce vertically */
667  if (top_edge) {
668  /* move top edge down */
669  this->top = y = y + 1;
670  } else {
671  /* move bottom edge up */
672  this->bottom = y = y - 1;
673  }
674  }
675 
676  if (left > right || top > bottom) {
677  /* can't continue, if the remaining rectangle is empty */
678  this->MakeEmpty();
679  return true; // empty remaining rect
680  }
681  }
682  return false; // non-empty remaining rect
683 }
684 
685 bool StationRect::AfterRemoveRect(BaseStation *st, TileArea ta)
686 {
687  assert(this->PtInExtendedRect(TileX(ta.tile), TileY(ta.tile)));
688  assert(this->PtInExtendedRect(TileX(ta.tile) + ta.w - 1, TileY(ta.tile) + ta.h - 1));
689 
690  bool empty = this->AfterRemoveTile(st, ta.tile);
691  if (ta.w != 1 || ta.h != 1) empty = empty || this->AfterRemoveTile(st, TileAddXY(ta.tile, ta.w - 1, ta.h - 1));
692  return empty;
693 }
694 
695 StationRect& StationRect::operator = (const Rect &src)
696 {
697  this->left = src.left;
698  this->top = src.top;
699  this->right = src.right;
700  this->bottom = src.bottom;
701  return *this;
702 }
703 
710 {
711  Money total_cost = 0;
712 
713  for (const Station *st : Station::Iterate()) {
714  if (st->owner == owner && (st->facilities & FACIL_AIRPORT)) {
715  total_cost += _price[PR_INFRASTRUCTURE_AIRPORT] * st->airport.GetSpec()->maintenance_cost;
716  }
717  }
718  /* 3 bits fraction for the maintenance cost factor. */
719  return total_cost >> 3;
720 }
721 
722 bool StationCompare::operator() (const Station *lhs, const Station *rhs) const
723 {
724  return lhs->index < rhs->index;
725 }
Base for aircraft.
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
Definition: cargo_type.h:74
void SetTile(TileIndex tile)
Add a tile as part of the tile area.
Definition: bitmap_type.h:79
void Initialize(const Rect &r)
Initialize the BitmapTileArea with the specified Rect.
Definition: bitmap_type.h:57
void Reset()
Reset and clear the BitmapTileArea.
Definition: bitmap_type.h:45
Iterator to iterate over all tiles belonging to a bitmaptilearea.
Definition: bitmap_type.h:106
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
StationIDStack DeleteFlows(StationID via)
Delete all flows at a station for specific cargo and destination.
K-dimensional tree, specialised for 2-dimensional space.
Definition: kdtree.hpp:35
void Build(It begin, It end)
Clear and rebuild the tree from a new sequence of elements,.
Definition: kdtree.hpp:362
void Remove(const T &element)
Remove a single element from the tree, if it exists.
Definition: kdtree.hpp:417
static LinkGraphSchedule instance
Static instance of LinkGraphSchedule.
void Unqueue(LinkGraph *lg)
Remove a link graph from the execution queue.
A connected component of a link graph.
Definition: linkgraph.h:37
NodeID Size() const
Get the current size of the component.
Definition: linkgraph.h:230
void RemoveNode(NodeID id)
Remove a node from the link graph by overwriting it with the last node.
Definition: linkgraph.cpp:116
static Date date
Current date in days (day counter).
static constexpr TimerGame< struct Economy >::Date INVALID_DATE
Representation of an invalid date.
Functions related to commands.
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ OWNER_NONE
The tile has no ownership.
Definition: company_type.h:25
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_END
Used for iterations.
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition: station.cpp:243
void MarkDirty(ZoomLevel maxzoom=ZOOM_LVL_MAX) const
Mark the sign dirty in all viewports.
Definition: viewport.cpp:1491
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:2057
Base of all industries.
IndustryID GetIndustryIndex(Tile t)
Get the industry ID of the given tile.
Definition: industry_map.h:63
Declaration of link graph classes used for cargo distribution.
Declaration of link graph schedule used for cargo distribution.
uint DistanceMax(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles.
Definition: map.cpp:178
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition: map_func.h:467
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition: map_func.h:373
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition: map_func.h:552
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
int32_t TileIndexDiff
An offset value between two tiles.
Definition: map_type.h:23
Functions related to news.
void DeleteStationNews(StationID sid)
Remove news regarding given station so there are no 'unknown station now accepts Mail' or 'First trai...
Definition: news_gui.cpp:942
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition: order_cmd.cpp:1787
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:237
Pseudo random number generator.
bool HasTileAnyRoadType(Tile t, RoadTypes rts)
Check if a tile has one of the specified road types.
Definition: road_map.h:222
Base class for roadstops.
Road vehicle states.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
StationPool _station_pool("Station")
The pool of stations.
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition: station.cpp:709
static uint GetTileCatchmentRadius(TileIndex tile, const Station *st)
Get the catchment size of an individual station tile.
Definition: station.cpp:307
Base classes/functions for stations.
void RerouteCargo(Station *st, CargoID c, StationID avoid, StationID avoid2)
Reroute cargo of type c at station st or in any vehicles unloading there.
Declarations for accessing the k-d tree of stations.
StationType GetStationType(Tile t)
Get the station type of this tile.
Definition: station_map.h:44
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition: station_map.h:266
bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile)
Check if a tile is a valid continuation to a railstation tile.
Definition: station_map.h:544
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
Axis GetRailStationAxis(Tile t)
Get the rail direction of a rail station.
Definition: station_map.h:503
static constexpr uint CA_TRAIN
Catchment for train stations with "modified catchment" enabled.
Definition: station_type.h:80
@ ROADSTOP_BUS
A standard stop for buses.
Definition: station_type.h:46
@ ROADSTOP_TRUCK
A standard stop for trucks.
Definition: station_type.h:47
StationFacility
The facilities a station might be having.
Definition: station_type.h:52
@ FACIL_AIRPORT
Station with an airport.
Definition: station_type.h:57
@ FACIL_NONE
The station has no facilities at all.
Definition: station_type.h:53
static constexpr uint CA_NONE
Catchment when the station has no facilities.
Definition: station_type.h:77
static constexpr uint CA_DOCK
Catchment for docks with "modified catchment" enabled.
Definition: station_type.h:81
static constexpr uint CA_BUS
Catchment for bus stops with "modified catchment" enabled.
Definition: station_type.h:78
static constexpr uint CA_UNMODIFIED
Catchment for all stations with "modified catchment" disabled.
Definition: station_type.h:83
static constexpr uint CA_TRUCK
Catchment for truck stops with "modified catchment" enabled.
Definition: station_type.h:79
Definition of base types and functions in a cross-platform compatible way.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:72
uint8_t catchment
catchment area of this airport
PersistentStorage * psa
Persistent storage for NewGRF airports.
Definition: station_base.h:298
const AirportSpec * GetSpec() const
Get the AirportSpec that from the airport type of this airport.
Definition: station_base.h:305
Base class for all station-ish types.
StationFacility facilities
The facilities that this station has.
TileIndex xy
Base tile of the station.
std::vector< SpecMapping< StationSpec > > speclist
List of rail station specs of this station.
TileArea train_station
Tile area the train 'station' part covers.
Owner owner
The owner of this station.
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
static void PostDestructor(size_t index)
Invalidating of the JoinStation window has to be done after removing item from the pool.
Definition: station.cpp:166
uint16_t random_bits
Random bits assigned to this station.
TrackedViewportSign sign
NOSAVE: Dimensions of sign.
std::vector< RoadStopTileData > custom_roadstop_tile_data
List of custom road stop tile data.
TimerGameCalendar::Date build_date
Date of construction.
static void InvalidateAllFrom(SourceType src_type, SourceID src)
Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source.
StationSettings station
settings related to station management
Stores station stats for a single cargo.
Definition: station_base.h:166
FlowStatMap flows
Planned flows through this station.
Definition: station_base.h:211
Defines the internal data of a functional industry.
Definition: industry.h:66
bool IsCargoAccepted() const
Test if this industry accepts any cargo.
Definition: industry.h:210
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition: industry.h:238
TileArea location
Location of the industry.
Definition: industry.h:94
Station * neutral_station
Associated neutral station.
Definition: industry.h:96
StationList stations_near
NOSAVE: List of nearby stations.
Definition: industry.h:110
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:306
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:297
Represents the covered area of e.g.
Definition: tilearea_type.h:18
uint16_t w
The width of the area.
Definition: tilearea_type.h:20
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
uint16_t h
The height of the area.
Definition: tilearea_type.h:21
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Definition: tilearea.cpp:123
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition: pool_type.hpp:318
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
int Height() const
Get height of Rect.
A Stop for a Road Vehicle.
Definition: roadstop_base.h:22
RoadStop * next
Next stop of the given type at this station.
Definition: roadstop_base.h:70
TileIndex xy
Position on the map.
Definition: roadstop_base.h:69
Buses, trucks and trams belong to this class.
Definition: roadveh.h:98
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition: roadveh.h:110
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:82
Class defining several overloaded accessors so we don't have to cast base stations that often.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static Station * Get(size_t index)
Gets station with given index.
static Pool::IterateWrapper< Aircraft > Iterate(size_t from=0)
Returns an iterable ensemble of all valid vehicles of type T.
StationRect - used to track station spread out rectangle - cheaper than scanning whole map.
static bool ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
Check whether station tiles of the given station id exist in the given rectangle.
Definition: station.cpp:625
bool PtInExtendedRect(int x, int y, int distance=0) const
Determines whether a given point (x, y) is within a certain distance of the station rectangle.
Definition: station.cpp:560
uint8_t station_spread
amount a station may spread
bool modified_catchment
different-size catchment areas
bool serve_neutral_industries
company stations can serve industries with attached neutral stations
Station data structure.
Definition: station_base.h:439
~Station()
Clean up a station by clearing vehicle orders, invalidating windows and removing link stats.
Definition: station.cpp:83
uint GetPlatformLength(TileIndex tile, DiagDirection dir) const override
Determines the REMAINING length of a platform, starting at (and including) the given tile.
Definition: station.cpp:285
RoadStop * bus_stops
All the road stops.
Definition: station_base.h:448
bool CatchmentCoversTown(TownID t) const
Test if the given town ID is covered by our catchment area.
Definition: station.cpp:448
TileArea ship_station
Tile area the ship 'station' part covers.
Definition: station_base.h:454
IndustryList industries_near
Cached list of industries near the station that can accept cargo,.
Definition: station_base.h:471
Rect GetCatchmentRect() const
Determines catchment rectangle of this station.
Definition: station.cpp:362
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:468
Industry * industry
NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
Definition: station_base.h:472
void MoveSign(TileIndex new_xy) override
Move the station main coordinate somewhere else.
static void RecomputeCatchmentForAll()
Recomputes catchment of all stations.
Definition: station.cpp:530
void RemoveFromAllNearbyLists()
Remove this station from the nearby stations lists of nearby towns and industries.
Definition: station.cpp:423
bool TileBelongsToRailStation(TileIndex tile) const override
Check whether a specific tile belongs to this station.
Definition: station_base.h:504
BitmapTileArea catchment_tiles
NOSAVE: Set of individual tiles covered by catchment area.
Definition: station_base.h:459
void RecomputeCatchment(bool no_clear_nearby_lists=false)
Recompute tiles covered in our catchment area.
Definition: station.cpp:462
uint GetCatchmentRadius() const
Determines the catchment radius of the station.
Definition: station.cpp:339
Airport airport
Tile area the airport covers.
Definition: station_base.h:453
void AddIndustryToDeliver(Industry *ind, TileIndex tile)
Add nearby industry to station's industries_near list if it accepts cargo.
Definition: station.cpp:385
void RemoveIndustryToDeliver(Industry *ind)
Remove nearby industry from station's industries_near list.
Definition: station.cpp:411
RoadStop * truck_stops
All the truck stops.
Definition: station_base.h:450
void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
Called when new facility is built on the station.
Definition: station.cpp:226
Town data structure.
Definition: town.h:54
StationList stations_near
NOSAVE: List of nearby stations.
Definition: town.h:91
bool kdtree_valid
Are the sign data valid for use with the _viewport_sign_kdtree?
Definition: viewport_type.h:52
The information about a vehicle list.
Definition: vehiclelist.h:28
Vehicle data structure.
Definition: vehicle_base.h:244
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:963
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
TileType
The different types of tiles.
Definition: tile_type.h:47
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
@ MP_HOUSE
A house by a town.
Definition: tile_type.h:51
@ MP_INDUSTRY
Part of an industry.
Definition: tile_type.h:56
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Base of the town class.
TownID GetTownIndex(Tile t)
Get the index of which town this house/street is attached to.
Definition: town_map.h:23
@ VEH_INVALID
Non-existing type of vehicle.
Definition: vehicle_type.h:35
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
Functions and type for generating vehicle lists.
Functions related to (drawing on) viewports.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1140
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3119
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3211
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3228
@ WC_STATION_LIST
Station list; Window numbers:
Definition: window_type.h:302
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
Definition: window_type.h:314
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
Definition: window_type.h:212
@ WC_SELECT_STATION
Select station (when joining stations); Window numbers:
Definition: window_type.h:242
@ WC_SHIPS_LIST
Ships list; Window numbers:
Definition: window_type.h:320
@ WC_STATION_VIEW
Station view; Window numbers:
Definition: window_type.h:345
@ WC_TRAINS_LIST
Trains list; Window numbers:
Definition: window_type.h:308
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers:
Definition: window_type.h:326