OpenTTD Source 20241222-master-gc72542431a
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
39StationKdtree _station_kdtree{};
40
41void 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
51BaseStation::~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
63Station::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. */
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 */
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
170
171bool 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
189void 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
205RoadStop *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
226void 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
243void 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)) {
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
307static 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::ranges::find(this->industries_near, ind, &IndustryListEntry::industry);
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::ranges::find(this->industries_near, ind, &IndustryListEntry::industry);
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
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
462void 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) {
482 st->RemoveIndustryToDeliver(this->industry);
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
541StationRect::StationRect()
542{
543 this->MakeEmpty();
544}
545
546void StationRect::MakeEmpty()
547{
548 this->left = this->top = this->right = this->bottom = 0;
549}
550
560bool 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
566bool StationRect::IsEmpty() const
567{
568 return this->left == 0 || this->left > this->right || this->top > this->bottom;
569}
570
571CommandCost 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 CommandCost(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
605CommandCost 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
635bool 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
685bool 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
695StationRect& 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
722bool 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.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
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.
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.
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
Owner
Enum for all companies/owners.
@ OWNER_NONE
The tile has no ownership.
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.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Base of all industries.
IndustryID GetIndustryIndex(Tile t)
Get the industry ID of the given tile.
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...
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
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.
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?
bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile)
Check if a tile is a valid continuation to a railstation tile.
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
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.
static constexpr uint CA_TRAIN
Catchment for train stations with "modified catchment" enabled.
@ ROADSTOP_BUS
A standard stop for buses.
@ ROADSTOP_TRUCK
A standard stop for trucks.
StationFacility
The facilities a station might be having.
@ FACIL_AIRPORT
Station with an airport.
@ FACIL_NONE
The station has no facilities at all.
static constexpr uint CA_NONE
Catchment when the station has no facilities.
static constexpr uint CA_DOCK
Catchment for docks with "modified catchment" enabled.
static constexpr uint CA_BUS
Catchment for bus stops with "modified catchment" enabled.
static constexpr uint CA_UNMODIFIED
Catchment for all stations with "modified catchment" disabled.
static constexpr uint CA_TRUCK
Catchment for truck stops with "modified catchment" enabled.
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.
const AirportSpec * GetSpec() const
Get the AirportSpec that from the airport type of this airport.
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.
FlowStatMap flows
Planned flows through this station.
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.
uint16_t w
The width of the area.
TileIndex tile
The base tile of the area.
uint16_t h
The height of the area.
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.
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static Titem * Get(size_t index)
Returns Titem with given index.
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.
RoadStop * next
Next stop of the given type at this station.
TileIndex xy
Position on the map.
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.
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.
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.
~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.
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.
IndustryList industries_near
Cached list of industries near the station that can accept cargo,.
Rect GetCatchmentRect() const
Determines catchment rectangle of this station.
Definition station.cpp:362
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Industry * industry
NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
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.
BitmapTileArea catchment_tiles
NOSAVE: Set of individual tiles covered by catchment area.
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.
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.
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?
The information about a vehicle list.
Definition vehiclelist.h:28
Vehicle data structure.
bool HasArticulatedPart() const
Check if an engine has an articulated part.
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.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
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:3127
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:3219
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:3236
@ WC_STATION_LIST
Station list; Window numbers:
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
@ WC_SELECT_STATION
Select station (when joining stations); Window numbers:
@ WC_SHIPS_LIST
Ships list; Window numbers:
@ WC_STATION_VIEW
Station view; Window numbers:
@ WC_TRAINS_LIST
Trains list; Window numbers:
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers: