OpenTTD Source 20250205-master-gfd85ab1e2c
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).ToWindowNumber());
56 CloseWindowById(WC_ROADVEH_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_ROAD, this->owner, this->index).ToWindowNumber());
57 CloseWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).ToWindowNumber());
58 CloseWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).ToWindowNumber());
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 if (!ge.HasData()) continue;
88 ge.GetData().cargo.OnCleanPool();
89 }
90 return;
91 }
92
93 while (!this->loading_vehicles.empty()) {
94 this->loading_vehicles.front()->LeaveStation();
95 }
96
97 for (Aircraft *a : Aircraft::Iterate()) {
98 if (!a->IsNormalAircraft()) continue;
99 if (a->targetairport == this->index) a->targetairport = INVALID_STATION;
100 }
101
102 for (CargoType c = 0; c < NUM_CARGO; ++c) {
103 LinkGraph *lg = LinkGraph::GetIfValid(this->goods[c].link_graph);
104 if (lg == nullptr) continue;
105
106 for (NodeID node = 0; node < lg->Size(); ++node) {
107 Station *st = Station::Get((*lg)[node].station);
108 if (!st->goods[c].HasData()) continue;
109 st->goods[c].GetData().flows.erase(this->index);
110 if ((*lg)[node].HasEdgeTo(this->goods[c].node) && (*lg)[node][this->goods[c].node].LastUpdate() != EconomyTime::INVALID_DATE) {
111 st->goods[c].GetData().flows.DeleteFlows(this->index);
112 RerouteCargo(st, c, this->index, st->index);
113 }
114 }
115 lg->RemoveNode(this->goods[c].node);
116 if (lg->Size() == 0) {
118 delete lg;
119 }
120 }
121
122 for (Vehicle *v : Vehicle::Iterate()) {
123 /* Forget about this station if this station is removed */
124 if (v->last_station_visited == this->index) {
125 v->last_station_visited = INVALID_STATION;
126 }
127 if (v->last_loading_station == this->index) {
128 v->last_loading_station = INVALID_STATION;
129 }
130 }
131
132 /* Remove station from industries and towns that reference it. */
134
135 /* Clear the persistent storage. */
136 delete this->airport.psa;
137
138 if (this->owner == OWNER_NONE) {
139 /* Invalidate all in case of oil rigs. */
141 } else {
143 }
144
146
147 /* Now delete all orders that go to the station */
148 RemoveOrderFromAllVehicles(OT_GOTO_STATION, this->index);
149
150 /* Remove all news items */
152
153 for (GoodsEntry &ge : this->goods) {
154 if (!ge.HasData()) continue;
155 ge.GetData().cargo.Truncate();
156 }
157
159
160 _station_kdtree.Remove(this->index);
161 if (this->sign.kdtree_valid) _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeStation(this->index));
162}
163
164
173
174bool BaseStation::SetRoadStopTileData(TileIndex tile, uint8_t data, bool animation)
175{
176 for (RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
177 if (tile_data.tile == tile) {
178 uint8_t &v = animation ? tile_data.animation_frame : tile_data.random_bits;
179 if (v == data) return false;
180 v = data;
181 return true;
182 }
183 }
184 RoadStopTileData tile_data;
185 tile_data.tile = tile;
186 tile_data.animation_frame = animation ? data : 0;
187 tile_data.random_bits = animation ? 0 : data;
188 this->custom_roadstop_tile_data.push_back(tile_data);
189 return data != 0;
190}
191
192void BaseStation::RemoveRoadStopTileData(TileIndex tile)
193{
194 for (RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
195 if (tile_data.tile == tile) {
196 tile_data = this->custom_roadstop_tile_data.back();
197 this->custom_roadstop_tile_data.pop_back();
198 return;
199 }
200 }
201}
202
208RoadStop *Station::GetPrimaryRoadStop(const RoadVehicle *v) const
209{
210 RoadStop *rs = this->GetPrimaryRoadStop(v->IsBus() ? RoadStopType::Bus : RoadStopType::Truck);
211
212 for (; rs != nullptr; rs = rs->next) {
213 /* The vehicle cannot go to this roadstop (different roadtype) */
214 if (!HasTileAnyRoadType(rs->xy, v->compatible_roadtypes)) continue;
215 /* The vehicle is articulated and can therefore not go to a standard road stop. */
216 if (IsBayRoadStopTile(rs->xy) && v->HasArticulatedPart()) continue;
217
218 /* The vehicle can actually go to this road stop. So, return it! */
219 break;
220 }
221
222 return rs;
223}
224
229void Station::AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
230{
231 if (this->facilities == FACIL_NONE) {
232 this->MoveSign(facil_xy);
233 this->random_bits = Random();
234 }
235 this->facilities |= new_facility_bit;
236 this->owner = _current_company;
239}
240
246void Station::MarkTilesDirty(bool cargo_change) const
247{
248 if (this->train_station.tile == INVALID_TILE) return;
249
250 /* cargo_change is set if we're refreshing the tiles due to cargo moving
251 * around. */
252 if (cargo_change) {
253 /* Don't waste time updating if there are no custom station graphics
254 * that might change. Even if there are custom graphics, they might
255 * not change. Unfortunately we have no way of telling. */
256 if (this->speclist.empty()) return;
257 }
258
259 for (TileIndex tile : this->train_station) {
260 if (this->TileBelongsToRailStation(tile)) {
262 }
263 }
264}
265
266/* virtual */ uint Station::GetPlatformLength(TileIndex tile) const
267{
268 assert(this->TileBelongsToRailStation(tile));
269
271
272 TileIndex t = tile;
273 uint len = 0;
274 do {
275 t -= delta;
276 len++;
277 } while (IsCompatibleTrainStationTile(t, tile));
278
279 t = tile;
280 do {
281 t += delta;
282 len++;
283 } while (IsCompatibleTrainStationTile(t, tile));
284
285 return len - 1;
286}
287
288/* virtual */ uint Station::GetPlatformLength(TileIndex tile, DiagDirection dir) const
289{
290 TileIndex start_tile = tile;
291 uint length = 0;
292 assert(IsRailStationTile(tile));
293 assert(dir < DIAGDIR_END);
294
295 do {
296 length++;
297 tile += TileOffsByDiagDir(dir);
298 } while (IsCompatibleTrainStationTile(tile, start_tile));
299
300 return length;
301}
302
310static uint GetTileCatchmentRadius(TileIndex tile, const Station *st)
311{
312 assert(IsTileType(tile, MP_STATION));
313
315 switch (GetStationType(tile)) {
316 case StationType::Rail: return CA_TRAIN;
317 case StationType::Oilrig: return CA_UNMODIFIED;
318 case StationType::Airport: return st->airport.GetSpec()->catchment;
319 case StationType::Truck: return CA_TRUCK;
320 case StationType::Bus: return CA_BUS;
321 case StationType::Dock: return CA_DOCK;
322
323 default: NOT_REACHED();
324 case StationType::Buoy:
325 case StationType::RailWaypoint:
326 case StationType::RoadWaypoint: return CA_NONE;
327 }
328 } else {
329 switch (GetStationType(tile)) {
330 default: return CA_UNMODIFIED;
331 case StationType::Buoy:
332 case StationType::RailWaypoint:
333 case StationType::RoadWaypoint: return CA_NONE;
334 }
335 }
336}
337
343{
344 uint ret = CA_NONE;
345
347 if (this->bus_stops != nullptr) ret = std::max<uint>(ret, CA_BUS);
348 if (this->truck_stops != nullptr) ret = std::max<uint>(ret, CA_TRUCK);
349 if (this->train_station.tile != INVALID_TILE) ret = std::max<uint>(ret, CA_TRAIN);
350 if (this->ship_station.tile != INVALID_TILE) ret = std::max<uint>(ret, CA_DOCK);
351 if (this->airport.tile != INVALID_TILE) ret = std::max<uint>(ret, this->airport.GetSpec()->catchment);
352 } else {
353 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) {
354 ret = CA_UNMODIFIED;
355 }
356 }
357
358 return ret;
359}
360
366{
367 assert(!this->rect.IsEmpty());
368
369 /* Compute acceptance rectangle */
370 int catchment_radius = this->GetCatchmentRadius();
371
372 Rect ret = {
373 std::max<int>(this->rect.left - catchment_radius, 0),
374 std::max<int>(this->rect.top - catchment_radius, 0),
375 std::min<int>(this->rect.right + catchment_radius, Map::MaxX()),
376 std::min<int>(this->rect.bottom + catchment_radius, Map::MaxY())
377 };
378
379 return ret;
380}
381
389{
390 /* Using DistanceMax to get about the same order as with previously used CircularTileSearch. */
391 uint distance = DistanceMax(this->xy, tile);
392
393 /* Don't check further if this industry is already in the list but update the distance if it's closer */
394 auto pos = std::ranges::find(this->industries_near, ind, &IndustryListEntry::industry);
395 if (pos != this->industries_near.end()) {
396 if (pos->distance > distance) {
397 auto node = this->industries_near.extract(pos);
398 node.value().distance = distance;
399 this->industries_near.insert(std::move(node));
400 }
401 return;
402 }
403
404 /* Include only industries that can accept cargo */
405 if (!ind->IsCargoAccepted()) return;
406
407 this->industries_near.insert(IndustryListEntry{distance, ind});
408}
409
415{
416 auto pos = std::ranges::find(this->industries_near, ind, &IndustryListEntry::industry);
417 if (pos != this->industries_near.end()) {
418 this->industries_near.erase(pos);
419 }
420}
421
422
427{
428 std::set<TownID> towns;
429 std::set<IndustryID> industries;
430
431 for (const auto &tile : this->catchment_tiles) {
432 TileType type = GetTileType(tile);
433 if (type == MP_HOUSE) {
434 towns.insert(GetTownIndex(tile));
435 } else if (type == MP_INDUSTRY) {
436 industries.insert(GetIndustryIndex(tile));
437 }
438 }
439
440 for (const TownID &townid : towns) { Town::Get(townid)->stations_near.erase(this); }
441 for (const IndustryID &industryid : industries) { Industry::Get(industryid)->stations_near.erase(this); }
442}
443
452{
454 for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
455 if (IsTileType(tile, MP_HOUSE) && GetTownIndex(tile) == t) return true;
456 }
457 return false;
458}
459
465void Station::RecomputeCatchment(bool no_clear_nearby_lists)
466{
467 this->industries_near.clear();
468 if (!no_clear_nearby_lists) this->RemoveFromAllNearbyLists();
469
470 if (this->rect.IsEmpty()) {
471 this->catchment_tiles.Reset();
472 return;
473 }
474
475 if (!_settings_game.station.serve_neutral_industries && this->industry != nullptr) {
476 /* Station is associated with an industry, so we only need to deliver to that industry. */
478 for (TileIndex tile : this->industry->location) {
479 if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == this->industry->index) {
480 this->catchment_tiles.SetTile(tile);
481 }
482 }
483 /* The industry's stations_near may have been computed before its neutral station was built so clear and re-add here. */
484 for (Station *st : this->industry->stations_near) {
485 st->RemoveIndustryToDeliver(this->industry);
486 }
487 this->industry->stations_near.clear();
488 this->industry->stations_near.insert(this);
489 this->industries_near.insert(IndustryListEntry{0, this->industry});
490 return;
491 }
492
494
495 /* Loop finding all station tiles */
496 TileArea ta(TileXY(this->rect.left, this->rect.top), TileXY(this->rect.right, this->rect.bottom));
497 for (TileIndex tile : ta) {
498 if (!IsTileType(tile, MP_STATION) || GetStationIndex(tile) != this->index) continue;
499
500 uint r = GetTileCatchmentRadius(tile, this);
501 if (r == CA_NONE) continue;
502
503 /* This tile sub-loop doesn't need to test any tiles, they are simply added to the catchment set. */
504 TileArea ta2 = TileArea(tile, 1, 1).Expand(r);
505 for (TileIndex tile2 : ta2) this->catchment_tiles.SetTile(tile2);
506 }
507
508 /* Search catchment tiles for towns and industries */
510 for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
511 if (IsTileType(tile, MP_HOUSE)) {
512 Town *t = Town::GetByTile(tile);
513 t->stations_near.insert(this);
514 }
515 if (IsTileType(tile, MP_INDUSTRY)) {
516 Industry *i = Industry::GetByTile(tile);
517
518 /* Ignore industry if it has a neutral station. It already can't be this station. */
519 if (!_settings_game.station.serve_neutral_industries && i->neutral_station != nullptr) continue;
520
521 i->stations_near.insert(this);
522
523 /* Add if we can deliver to this industry as well */
524 this->AddIndustryToDeliver(i, tile);
525 }
526 }
527}
528
534{
535 for (Town *t : Town::Iterate()) { t->stations_near.clear(); }
536 for (Industry *i : Industry::Iterate()) { i->stations_near.clear(); }
537 for (Station *st : Station::Iterate()) { st->RecomputeCatchment(true); }
538}
539
540/************************************************************************/
541/* StationRect implementation */
542/************************************************************************/
543
544StationRect::StationRect()
545{
546 this->MakeEmpty();
547}
548
549void StationRect::MakeEmpty()
550{
551 this->left = this->top = this->right = this->bottom = 0;
552}
553
563bool StationRect::PtInExtendedRect(int x, int y, int distance) const
564{
565 return this->left - distance <= x && x <= this->right + distance &&
566 this->top - distance <= y && y <= this->bottom + distance;
567}
568
569bool StationRect::IsEmpty() const
570{
571 return this->left == 0 || this->left > this->right || this->top > this->bottom;
572}
573
574CommandCost StationRect::BeforeAddTile(TileIndex tile, StationRectMode mode)
575{
576 int x = TileX(tile);
577 int y = TileY(tile);
578 if (this->IsEmpty()) {
579 /* we are adding the first station tile */
580 if (mode != ADD_TEST) {
581 this->left = this->right = x;
582 this->top = this->bottom = y;
583 }
584 } else if (!this->PtInExtendedRect(x, y)) {
585 /* current rect is not empty and new point is outside this rect
586 * make new spread-out rectangle */
587 Rect new_rect = {std::min(x, this->left), std::min(y, this->top), std::max(x, this->right), std::max(y, this->bottom)};
588
589 /* check new rect dimensions against preset max */
590 int w = new_rect.Width();
591 int h = new_rect.Height();
592 if (mode != ADD_FORCE && (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread)) {
593 assert(mode != ADD_TRY);
594 return CommandCost(STR_ERROR_STATION_TOO_SPREAD_OUT);
595 }
596
597 /* spread-out ok, return true */
598 if (mode != ADD_TEST) {
599 /* we should update the station rect */
600 *this = new_rect;
601 }
602 } else {
603 ; // new point is inside the rect, we don't need to do anything
604 }
605 return CommandCost();
606}
607
608CommandCost StationRect::BeforeAddRect(TileIndex tile, int w, int h, StationRectMode mode)
609{
610 if (mode == ADD_FORCE || (w <= _settings_game.station.station_spread && h <= _settings_game.station.station_spread)) {
611 /* Important when the old rect is completely inside the new rect, resp. the old one was empty. */
612 CommandCost ret = this->BeforeAddTile(tile, mode);
613 if (ret.Succeeded()) ret = this->BeforeAddTile(TileAddXY(tile, w - 1, h - 1), mode);
614 return ret;
615 }
616 return CommandCost();
617}
618
628/* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
629{
630 TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a));
631 for (TileIndex tile : ta) {
632 if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
633 }
634
635 return false;
636}
637
638bool StationRect::AfterRemoveTile(BaseStation *st, TileIndex tile)
639{
640 int x = TileX(tile);
641 int y = TileY(tile);
642
643 /* look if removed tile was on the bounding rect edge
644 * and try to reduce the rect by this edge
645 * do it until we have empty rect or nothing to do */
646 for (;;) {
647 /* check if removed tile is on rect edge */
648 bool left_edge = (x == this->left);
649 bool right_edge = (x == this->right);
650 bool top_edge = (y == this->top);
651 bool bottom_edge = (y == this->bottom);
652
653 /* can we reduce the rect in either direction? */
654 bool reduce_x = ((left_edge || right_edge) && !ScanForStationTiles(st->index, x, this->top, x, this->bottom));
655 bool reduce_y = ((top_edge || bottom_edge) && !ScanForStationTiles(st->index, this->left, y, this->right, y));
656 if (!(reduce_x || reduce_y)) break; // nothing to do (can't reduce)
657
658 if (reduce_x) {
659 /* reduce horizontally */
660 if (left_edge) {
661 /* move left edge right */
662 this->left = x = x + 1;
663 } else {
664 /* move right edge left */
665 this->right = x = x - 1;
666 }
667 }
668 if (reduce_y) {
669 /* reduce vertically */
670 if (top_edge) {
671 /* move top edge down */
672 this->top = y = y + 1;
673 } else {
674 /* move bottom edge up */
675 this->bottom = y = y - 1;
676 }
677 }
678
679 if (left > right || top > bottom) {
680 /* can't continue, if the remaining rectangle is empty */
681 this->MakeEmpty();
682 return true; // empty remaining rect
683 }
684 }
685 return false; // non-empty remaining rect
686}
687
688bool StationRect::AfterRemoveRect(BaseStation *st, TileArea ta)
689{
690 assert(this->PtInExtendedRect(TileX(ta.tile), TileY(ta.tile)));
691 assert(this->PtInExtendedRect(TileX(ta.tile) + ta.w - 1, TileY(ta.tile) + ta.h - 1));
692
693 bool empty = this->AfterRemoveTile(st, ta.tile);
694 if (ta.w != 1 || ta.h != 1) empty = empty || this->AfterRemoveTile(st, TileAddXY(ta.tile, ta.w - 1, ta.h - 1));
695 return empty;
696}
697
698StationRect& StationRect::operator = (const Rect &src)
699{
700 this->left = src.left;
701 this->top = src.top;
702 this->right = src.right;
703 this->bottom = src.bottom;
704 return *this;
705}
706
713{
714 Money total_cost = 0;
715
716 for (const Station *st : Station::Iterate()) {
717 if (st->owner == owner && (st->facilities & FACIL_AIRPORT)) {
718 total_cost += _price[PR_INFRASTRUCTURE_AIRPORT] * st->airport.GetSpec()->maintenance_cost;
719 }
720 }
721 /* 3 bits fraction for the maintenance cost factor. */
722 return total_cost >> 3;
723}
724
725bool StationCompare::operator() (const Station *lhs, const Station *rhs) const
726{
727 return lhs->index < rhs->index;
728}
Base for aircraft.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
static const CargoType 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:246
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.
@ Random
Randomise borders.
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:175
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:470
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:555
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:570
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:712
static uint GetTileCatchmentRadius(TileIndex tile, const Station *st)
Get the catchment size of an individual station tile.
Definition station.cpp:310
Base classes/functions for stations.
void RerouteCargo(Station *st, CargoType 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.
RoadStopType
Types of RoadStops.
@ Bus
A standard stop for buses.
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:169
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
FlowStatMap flows
Planned flows through this station.
Stores station stats for a single cargo.
debug_inline const GoodsEntryData & GetData() const
Get optional cargo packet/flow data.
debug_inline bool HasData() const
Test if this goods entry has optional cargo packet/flow data.
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:79
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:628
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:563
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:288
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:451
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:365
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:533
void RemoveFromAllNearbyLists()
Remove this station from the nearby stations lists of nearby towns and industries.
Definition station.cpp:426
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:465
uint GetCatchmentRadius() const
Determines the catchment radius of the station.
Definition station.cpp:342
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:388
void RemoveIndustryToDeliver(Industry *ind)
Remove nearby industry from station's industries_near list.
Definition station.cpp:414
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:229
Town data structure.
Definition town.h:52
StationList stations_near
NOSAVE: List of nearby stations.
Definition town.h:89
bool kdtree_valid
Are the sign data valid for use with the _viewport_sign_kdtree?
The information about a vehicle list.
Definition vehiclelist.h:29
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:1137
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3125
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:3217
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:3234
@ 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: