OpenTTD Source  1.10.2
station_cmd.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 "aircraft.h"
12 #include "bridge_map.h"
13 #include "cmd_helper.h"
14 #include "viewport_func.h"
15 #include "viewport_kdtree.h"
16 #include "command_func.h"
17 #include "town.h"
18 #include "news_func.h"
19 #include "train.h"
20 #include "ship.h"
21 #include "roadveh.h"
22 #include "industry.h"
23 #include "newgrf_cargo.h"
24 #include "newgrf_debug.h"
25 #include "newgrf_station.h"
26 #include "newgrf_canal.h" /* For the buoy */
28 #include "road_internal.h" /* For drawing catenary/checking road removal */
29 #include "autoslope.h"
30 #include "water.h"
31 #include "strings_func.h"
32 #include "clear_func.h"
33 #include "date_func.h"
34 #include "vehicle_func.h"
35 #include "string_func.h"
36 #include "animated_tile_func.h"
37 #include "elrail_func.h"
38 #include "station_base.h"
39 #include "station_func.h"
40 #include "station_kdtree.h"
41 #include "roadstop_base.h"
42 #include "newgrf_railtype.h"
43 #include "newgrf_roadtype.h"
44 #include "waypoint_base.h"
45 #include "waypoint_func.h"
46 #include "pbs.h"
47 #include "debug.h"
48 #include "core/random_func.hpp"
49 #include "company_base.h"
50 #include "table/airporttile_ids.h"
51 #include "newgrf_airporttiles.h"
52 #include "order_backup.h"
53 #include "newgrf_house.h"
54 #include "company_gui.h"
56 #include "linkgraph/refresh.h"
57 #include "widgets/station_widget.h"
58 #include "tunnelbridge_map.h"
59 
60 #include "table/strings.h"
61 
62 #include "safeguards.h"
63 
69 /* static */ const FlowStat::SharesMap FlowStat::empty_sharesmap;
70 
78 {
79  assert(IsTileType(t, MP_STATION));
80 
81  /* If the tile isn't an airport there's no chance it's a hangar. */
82  if (!IsAirport(t)) return false;
83 
84  const Station *st = Station::GetByTile(t);
85  const AirportSpec *as = st->airport.GetSpec();
86 
87  for (uint i = 0; i < as->nof_depots; i++) {
88  if (st->airport.GetHangarTile(i) == t) return true;
89  }
90 
91  return false;
92 }
93 
102 template <class T>
103 CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
104 {
105  ta.Expand(1);
106 
107  /* check around to see if there are any stations there owned by the company */
108  TILE_AREA_LOOP(tile_cur, ta) {
109  if (IsTileType(tile_cur, MP_STATION)) {
110  StationID t = GetStationIndex(tile_cur);
111  if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
112  if (closest_station == INVALID_STATION) {
113  closest_station = t;
114  } else if (closest_station != t) {
115  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
116  }
117  }
118  }
119  *st = (closest_station == INVALID_STATION) ? nullptr : T::Get(closest_station);
120  return CommandCost();
121 }
122 
128 typedef bool (*CMSAMatcher)(TileIndex tile);
129 
137 {
138  int num = 0;
139 
140  for (int dx = -3; dx <= 3; dx++) {
141  for (int dy = -3; dy <= 3; dy++) {
142  TileIndex t = TileAddWrap(tile, dx, dy);
143  if (t != INVALID_TILE && cmp(t)) num++;
144  }
145  }
146 
147  return num;
148 }
149 
155 static bool CMSAMine(TileIndex tile)
156 {
157  /* No industry */
158  if (!IsTileType(tile, MP_INDUSTRY)) return false;
159 
160  const Industry *ind = Industry::GetByTile(tile);
161 
162  /* No extractive industry */
163  if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false;
164 
165  for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
166  /* The industry extracts something non-liquid, i.e. no oil or plastic, so it is a mine.
167  * Also the production of passengers and mail is ignored. */
168  if (ind->produced_cargo[i] != CT_INVALID &&
170  return true;
171  }
172  }
173 
174  return false;
175 }
176 
182 static bool CMSAWater(TileIndex tile)
183 {
184  return IsTileType(tile, MP_WATER) && IsWater(tile);
185 }
186 
192 static bool CMSATree(TileIndex tile)
193 {
194  return IsTileType(tile, MP_TREES);
195 }
196 
197 #define M(x) ((x) - STR_SV_STNAME)
198 
199 enum StationNaming {
200  STATIONNAMING_RAIL,
201  STATIONNAMING_ROAD,
202  STATIONNAMING_AIRPORT,
203  STATIONNAMING_OILRIG,
204  STATIONNAMING_DOCK,
205  STATIONNAMING_HELIPORT,
206 };
207 
210  uint32 free_names;
211  bool *indtypes;
212 };
213 
222 static bool FindNearIndustryName(TileIndex tile, void *user_data)
223 {
224  /* All already found industry types */
226  if (!IsTileType(tile, MP_INDUSTRY)) return false;
227 
228  /* If the station name is undefined it means that it doesn't name a station */
229  IndustryType indtype = GetIndustryType(tile);
230  if (GetIndustrySpec(indtype)->station_name == STR_UNDEFINED) return false;
231 
232  /* In all cases if an industry that provides a name is found two of
233  * the standard names will be disabled. */
234  sni->free_names &= ~(1 << M(STR_SV_STNAME_OILFIELD) | 1 << M(STR_SV_STNAME_MINES));
235  return !sni->indtypes[indtype];
236 }
237 
238 static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming name_class)
239 {
240  static const uint32 _gen_station_name_bits[] = {
241  0, // STATIONNAMING_RAIL
242  0, // STATIONNAMING_ROAD
243  1U << M(STR_SV_STNAME_AIRPORT), // STATIONNAMING_AIRPORT
244  1U << M(STR_SV_STNAME_OILFIELD), // STATIONNAMING_OILRIG
245  1U << M(STR_SV_STNAME_DOCKS), // STATIONNAMING_DOCK
246  1U << M(STR_SV_STNAME_HELIPORT), // STATIONNAMING_HELIPORT
247  };
248 
249  const Town *t = st->town;
250  uint32 free_names = UINT32_MAX;
251 
253  memset(indtypes, 0, sizeof(indtypes));
254 
255  for (const Station *s : Station::Iterate()) {
256  if (s != st && s->town == t) {
257  if (s->indtype != IT_INVALID) {
258  indtypes[s->indtype] = true;
259  StringID name = GetIndustrySpec(s->indtype)->station_name;
260  if (name != STR_UNDEFINED) {
261  /* Filter for other industrytypes with the same name */
262  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
263  const IndustrySpec *indsp = GetIndustrySpec(it);
264  if (indsp->enabled && indsp->station_name == name) indtypes[it] = true;
265  }
266  }
267  continue;
268  }
269  uint str = M(s->string_id);
270  if (str <= 0x20) {
271  if (str == M(STR_SV_STNAME_FOREST)) {
272  str = M(STR_SV_STNAME_WOODS);
273  }
274  ClrBit(free_names, str);
275  }
276  }
277  }
278 
279  TileIndex indtile = tile;
280  StationNameInformation sni = { free_names, indtypes };
281  if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) {
282  /* An industry has been found nearby */
283  IndustryType indtype = GetIndustryType(indtile);
284  const IndustrySpec *indsp = GetIndustrySpec(indtype);
285  /* STR_NULL means it only disables oil rig/mines */
286  if (indsp->station_name != STR_NULL) {
287  st->indtype = indtype;
288  return STR_SV_STNAME_FALLBACK;
289  }
290  }
291 
292  /* Oil rigs/mines name could be marked not free by looking for a near by industry. */
293  free_names = sni.free_names;
294 
295  /* check default names */
296  uint32 tmp = free_names & _gen_station_name_bits[name_class];
297  if (tmp != 0) return STR_SV_STNAME + FindFirstBit(tmp);
298 
299  /* check mine? */
300  if (HasBit(free_names, M(STR_SV_STNAME_MINES))) {
301  if (CountMapSquareAround(tile, CMSAMine) >= 2) {
302  return STR_SV_STNAME_MINES;
303  }
304  }
305 
306  /* check close enough to town to get central as name? */
307  if (DistanceMax(tile, t->xy) < 8) {
308  if (HasBit(free_names, M(STR_SV_STNAME))) return STR_SV_STNAME;
309 
310  if (HasBit(free_names, M(STR_SV_STNAME_CENTRAL))) return STR_SV_STNAME_CENTRAL;
311  }
312 
313  /* Check lakeside */
314  if (HasBit(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
315  DistanceFromEdge(tile) < 20 &&
316  CountMapSquareAround(tile, CMSAWater) >= 5) {
317  return STR_SV_STNAME_LAKESIDE;
318  }
319 
320  /* Check woods */
321  if (HasBit(free_names, M(STR_SV_STNAME_WOODS)) && (
322  CountMapSquareAround(tile, CMSATree) >= 8 ||
324  ) {
325  return _settings_game.game_creation.landscape == LT_TROPIC ? STR_SV_STNAME_FOREST : STR_SV_STNAME_WOODS;
326  }
327 
328  /* check elevation compared to town */
329  int z = GetTileZ(tile);
330  int z2 = GetTileZ(t->xy);
331  if (z < z2) {
332  if (HasBit(free_names, M(STR_SV_STNAME_VALLEY))) return STR_SV_STNAME_VALLEY;
333  } else if (z > z2) {
334  if (HasBit(free_names, M(STR_SV_STNAME_HEIGHTS))) return STR_SV_STNAME_HEIGHTS;
335  }
336 
337  /* check direction compared to town */
338  static const int8 _direction_and_table[] = {
339  ~( (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_EAST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
340  ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
341  ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_EAST)) | (1 << M(STR_SV_STNAME_NORTH)) ),
342  ~( (1 << M(STR_SV_STNAME_SOUTH)) | (1 << M(STR_SV_STNAME_WEST)) | (1 << M(STR_SV_STNAME_EAST)) ),
343  };
344 
345  free_names &= _direction_and_table[
346  (TileX(tile) < TileX(t->xy)) +
347  (TileY(tile) < TileY(t->xy)) * 2];
348 
349  tmp = free_names & ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6) | (1 << 7) | (1 << 12) | (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30));
350  return (tmp == 0) ? STR_SV_STNAME_FALLBACK : (STR_SV_STNAME + FindFirstBit(tmp));
351 }
352 #undef M
353 
360 {
361  uint threshold = 8;
362 
363  Station *best_station = nullptr;
364  ForAllStationsRadius(tile, threshold, [&](Station *st) {
365  if (!st->IsInUse() && st->owner == _current_company) {
366  uint cur_dist = DistanceManhattan(tile, st->xy);
367 
368  if (cur_dist < threshold) {
369  threshold = cur_dist;
370  best_station = st;
371  } else if (cur_dist == threshold && best_station != nullptr) {
372  /* In case of a tie, lowest station ID wins */
373  if (st->index < best_station->index) best_station = st;
374  }
375  }
376  });
377 
378  return best_station;
379 }
380 
381 
383 {
384  switch (type) {
385  case STATION_RAIL:
386  *ta = this->train_station;
387  return;
388 
389  case STATION_AIRPORT:
390  *ta = this->airport;
391  return;
392 
393  case STATION_TRUCK:
394  *ta = this->truck_station;
395  return;
396 
397  case STATION_BUS:
398  *ta = this->bus_station;
399  return;
400 
401  case STATION_DOCK:
402  case STATION_OILRIG:
403  *ta = this->docking_station;
404  return;
405 
406  default: NOT_REACHED();
407  }
408 }
409 
414 {
415  Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
416 
417  pt.y -= 32 * ZOOM_LVL_BASE;
418  if ((this->facilities & FACIL_AIRPORT) && this->airport.type == AT_OILRIG) pt.y -= 16 * ZOOM_LVL_BASE;
419 
420  if (this->sign.kdtree_valid) _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeStation(this->index));
421 
422  SetDParam(0, this->index);
423  SetDParam(1, this->facilities);
424  this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_STATION);
425 
426  _viewport_sign_kdtree.Insert(ViewportSignKdtreeItem::MakeStation(this->index));
427 
428  SetWindowDirty(WC_STATION_VIEW, this->index);
429 }
430 
436 {
437  if (this->xy == new_xy) return;
438 
439  _station_kdtree.Remove(this->index);
440 
441  this->BaseStation::MoveSign(new_xy);
442 
443  _station_kdtree.Insert(this->index);
444 }
445 
448 {
449  for (BaseStation *st : BaseStation::Iterate()) {
450  st->UpdateVirtCoord();
451  }
452 }
453 
454 void BaseStation::FillCachedName() const
455 {
457  int64 args_array[] = { this->index };
458  StringParameters tmp_params(args_array);
459  char *end = GetStringWithArgs(buf, Waypoint::IsExpected(this) ? STR_WAYPOINT_NAME : STR_STATION_NAME, &tmp_params, lastof(buf));
460  this->cached_name.assign(buf, end);
461 }
462 
463 void ClearAllStationCachedNames()
464 {
465  for (BaseStation *st : BaseStation::Iterate()) {
466  st->cached_name.clear();
467  }
468 }
469 
475 static CargoTypes GetAcceptanceMask(const Station *st)
476 {
477  CargoTypes mask = 0;
478 
479  for (CargoID i = 0; i < NUM_CARGO; i++) {
480  if (HasBit(st->goods[i].status, GoodsEntry::GES_ACCEPTANCE)) SetBit(mask, i);
481  }
482  return mask;
483 }
484 
489 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
490 {
491  for (uint i = 0; i < num_items; i++) {
492  SetDParam(i + 1, CargoSpec::Get(cargo[i])->name);
493  }
494 
495  SetDParam(0, st->index);
497 }
498 
506 CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
507 {
508  CargoArray produced;
509  std::set<IndustryID> industries;
510  TileArea ta = TileArea(tile, w, h).Expand(rad);
511 
512  /* Loop over all tiles to get the produced cargo of
513  * everything except industries */
514  TILE_AREA_LOOP(tile, ta) {
515  if (IsTileType(tile, MP_INDUSTRY)) industries.insert(GetIndustryIndex(tile));
516  AddProducedCargo(tile, produced);
517  }
518 
519  /* Loop over the seen industries. They produce cargo for
520  * anything that is within 'rad' of any one of their tiles.
521  */
522  for (IndustryID industry : industries) {
523  const Industry *i = Industry::Get(industry);
524  /* Skip industry with neutral station */
525  if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue;
526 
527  for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
528  CargoID cargo = i->produced_cargo[j];
529  if (cargo != CT_INVALID) produced[cargo]++;
530  }
531  }
532 
533  return produced;
534 }
535 
545 CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted)
546 {
547  CargoArray acceptance;
548  if (always_accepted != nullptr) *always_accepted = 0;
549 
550  TileArea ta = TileArea(tile, w, h).Expand(rad);
551 
552  TILE_AREA_LOOP(tile, ta) {
553  /* Ignore industry if it has a neutral station. */
554  if (!_settings_game.station.serve_neutral_industries && IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != nullptr) continue;
555 
556  AddAcceptedCargo(tile, acceptance, always_accepted);
557  }
558 
559  return acceptance;
560 }
561 
567 static CargoArray GetAcceptanceAroundStation(const Station *st, CargoTypes *always_accepted)
568 {
569  CargoArray acceptance;
570  if (always_accepted != nullptr) *always_accepted = 0;
571 
573  for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
574  AddAcceptedCargo(tile, acceptance, always_accepted);
575  }
576 
577  return acceptance;
578 }
579 
585 void UpdateStationAcceptance(Station *st, bool show_msg)
586 {
587  /* old accepted goods types */
588  CargoTypes old_acc = GetAcceptanceMask(st);
589 
590  /* And retrieve the acceptance. */
591  CargoArray acceptance;
592  if (!st->rect.IsEmpty()) {
593  acceptance = GetAcceptanceAroundStation(st, &st->always_accepted);
594  }
595 
596  /* Adjust in case our station only accepts fewer kinds of goods */
597  for (CargoID i = 0; i < NUM_CARGO; i++) {
598  uint amt = acceptance[i];
599 
600  /* Make sure the station can accept the goods type. */
601  bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
602  if ((!is_passengers && !(st->facilities & ~FACIL_BUS_STOP)) ||
603  (is_passengers && !(st->facilities & ~FACIL_TRUCK_STOP))) {
604  amt = 0;
605  }
606 
607  GoodsEntry &ge = st->goods[i];
608  SB(ge.status, GoodsEntry::GES_ACCEPTANCE, 1, amt >= 8);
610  (*LinkGraph::Get(ge.link_graph))[ge.node].SetDemand(amt / 8);
611  }
612  }
613 
614  /* Only show a message in case the acceptance was actually changed. */
615  CargoTypes new_acc = GetAcceptanceMask(st);
616  if (old_acc == new_acc) return;
617 
618  /* show a message to report that the acceptance was changed? */
619  if (show_msg && st->owner == _local_company && st->IsInUse()) {
620  /* List of accept and reject strings for different number of
621  * cargo types */
622  static const StringID accept_msg[] = {
623  STR_NEWS_STATION_NOW_ACCEPTS_CARGO,
624  STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO,
625  };
626  static const StringID reject_msg[] = {
627  STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO,
628  STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO,
629  };
630 
631  /* Array of accepted and rejected cargo types */
632  CargoID accepts[2] = { CT_INVALID, CT_INVALID };
633  CargoID rejects[2] = { CT_INVALID, CT_INVALID };
634  uint num_acc = 0;
635  uint num_rej = 0;
636 
637  /* Test each cargo type to see if its acceptance has changed */
638  for (CargoID i = 0; i < NUM_CARGO; i++) {
639  if (HasBit(new_acc, i)) {
640  if (!HasBit(old_acc, i) && num_acc < lengthof(accepts)) {
641  /* New cargo is accepted */
642  accepts[num_acc++] = i;
643  }
644  } else {
645  if (HasBit(old_acc, i) && num_rej < lengthof(rejects)) {
646  /* Old cargo is no longer accepted */
647  rejects[num_rej++] = i;
648  }
649  }
650  }
651 
652  /* Show news message if there are any changes */
653  if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
654  if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
655  }
656 
657  /* redraw the station view since acceptance changed */
659 }
660 
661 static void UpdateStationSignCoord(BaseStation *st)
662 {
663  const StationRect *r = &st->rect;
664 
665  if (r->IsEmpty()) return; // no tiles belong to this station
666 
667  /* clamp sign coord to be inside the station rect */
668  TileIndex new_xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
669  st->MoveSign(new_xy);
670 
671  if (!Station::IsExpected(st)) return;
672  Station *full_station = Station::From(st);
673  for (CargoID c = 0; c < NUM_CARGO; ++c) {
674  LinkGraphID lg = full_station->goods[c].link_graph;
675  if (!LinkGraph::IsValidID(lg)) continue;
676  (*LinkGraph::Get(lg))[full_station->goods[c].node].UpdateLocation(st->xy);
677  }
678 }
679 
689 static CommandCost BuildStationPart(Station **st, DoCommandFlag flags, bool reuse, TileArea area, StationNaming name_class)
690 {
691  /* Find a deleted station close to us */
692  if (*st == nullptr && reuse) *st = GetClosestDeletedStation(area.tile);
693 
694  if (*st != nullptr) {
695  if ((*st)->owner != _current_company) {
697  }
698 
699  CommandCost ret = (*st)->rect.BeforeAddRect(area.tile, area.w, area.h, StationRect::ADD_TEST);
700  if (ret.Failed()) return ret;
701  } else {
702  /* allocate and initialize new station */
703  if (!Station::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
704 
705  if (flags & DC_EXEC) {
706  *st = new Station(area.tile);
707  _station_kdtree.Insert((*st)->index);
708 
709  (*st)->town = ClosestTownFromTile(area.tile, UINT_MAX);
710  (*st)->string_id = GenerateStationName(*st, area.tile, name_class);
711 
713  SetBit((*st)->town->have_ratings, _current_company);
714  }
715  }
716  }
717  return CommandCost();
718 }
719 
727 {
728  if (!st->IsInUse()) {
729  st->delete_ctr = 0;
731  }
732  /* station remains but it probably lost some parts - station sign should stay in the station boundaries */
733  UpdateStationSignCoord(st);
734 }
735 
742 {
743  this->UpdateVirtCoord();
744  this->RecomputeCatchment();
746  if (adding) InvalidateWindowData(WC_STATION_LIST, this->owner, 0);
747 
748  switch (type) {
749  case STATION_RAIL:
751  break;
752  case STATION_AIRPORT:
753  break;
754  case STATION_TRUCK:
755  case STATION_BUS:
757  break;
758  case STATION_DOCK:
760  break;
761  default: NOT_REACHED();
762  }
763 
764  if (adding) {
765  UpdateStationAcceptance(this, false);
767  } else {
768  DeleteStationIfEmpty(this);
769  }
770 
771 }
772 
774 
784 CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge = true)
785 {
786  if (check_bridge && IsBridgeAbove(tile)) {
787  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
788  }
789 
791  if (ret.Failed()) return ret;
792 
793  int z;
794  Slope tileh = GetTileSlope(tile, &z);
795 
796  /* Prohibit building if
797  * 1) The tile is "steep" (i.e. stretches two height levels).
798  * 2) The tile is non-flat and the build_on_slopes switch is disabled.
799  */
800  if ((!allow_steep && IsSteepSlope(tileh)) ||
802  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
803  }
804 
806  int flat_z = z + GetSlopeMaxZ(tileh);
807  if (tileh != SLOPE_FLAT) {
808  /* Forbid building if the tile faces a slope in a invalid direction. */
809  for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
810  if (HasBit(invalid_dirs, dir) && !CanBuildDepotByTileh(dir, tileh)) {
811  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
812  }
813  }
814  cost.AddCost(_price[PR_BUILD_FOUNDATION]);
815  }
816 
817  /* The level of this tile must be equal to allowed_z. */
818  if (allowed_z < 0) {
819  /* First tile. */
820  allowed_z = flat_z;
821  } else if (allowed_z != flat_z) {
822  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
823  }
824 
825  return cost;
826 }
827 
835 {
837  int allowed_z = -1;
838 
839  for (; tile_iter != INVALID_TILE; ++tile_iter) {
840  CommandCost ret = CheckBuildableTile(tile_iter, 0, allowed_z, true);
841  if (ret.Failed()) return ret;
842  cost.AddCost(ret);
843 
844  ret = DoCommand(tile_iter, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
845  if (ret.Failed()) return ret;
846  cost.AddCost(ret);
847  }
848 
849  return cost;
850 }
851 
866 static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, std::vector<Train *> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
867 {
869  int allowed_z = -1;
870  uint invalid_dirs = 5 << axis;
871 
872  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
873  bool slope_cb = statspec != nullptr && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
874 
875  TILE_AREA_LOOP(tile_cur, tile_area) {
876  CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false);
877  if (ret.Failed()) return ret;
878  cost.AddCost(ret);
879 
880  if (slope_cb) {
881  /* Do slope check if requested. */
882  ret = PerformStationTileSlopeCheck(tile_area.tile, tile_cur, statspec, axis, plat_len, numtracks);
883  if (ret.Failed()) return ret;
884  }
885 
886  /* if station is set, then we have special handling to allow building on top of already existing stations.
887  * so station points to INVALID_STATION if we can build on any station.
888  * Or it points to a station if we're only allowed to build on exactly that station. */
889  if (station != nullptr && IsTileType(tile_cur, MP_STATION)) {
890  if (!IsRailStation(tile_cur)) {
891  return ClearTile_Station(tile_cur, DC_AUTO); // get error message
892  } else {
893  StationID st = GetStationIndex(tile_cur);
894  if (*station == INVALID_STATION) {
895  *station = st;
896  } else if (*station != st) {
897  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
898  }
899  }
900  } else {
901  /* Rail type is only valid when building a railway station; if station to
902  * build isn't a rail station it's INVALID_RAILTYPE. */
903  if (rt != INVALID_RAILTYPE &&
904  IsPlainRailTile(tile_cur) && !HasSignals(tile_cur) &&
905  HasPowerOnRail(GetRailType(tile_cur), rt)) {
906  /* Allow overbuilding if the tile:
907  * - has rail, but no signals
908  * - it has exactly one track
909  * - the track is in line with the station
910  * - the current rail type has power on the to-be-built type (e.g. convert normal rail to el rail)
911  */
912  TrackBits tracks = GetTrackBits(tile_cur);
913  Track track = RemoveFirstTrack(&tracks);
914  Track expected_track = HasBit(invalid_dirs, DIAGDIR_NE) ? TRACK_X : TRACK_Y;
915 
916  if (tracks == TRACK_BIT_NONE && track == expected_track) {
917  /* Check for trains having a reservation for this tile. */
918  if (HasBit(GetRailReservationTrackBits(tile_cur), track)) {
919  Train *v = GetTrainForReservation(tile_cur, track);
920  if (v != nullptr) {
921  affected_vehicles.push_back(v);
922  }
923  }
924  CommandCost ret = DoCommand(tile_cur, 0, track, flags, CMD_REMOVE_SINGLE_RAIL);
925  if (ret.Failed()) return ret;
926  cost.AddCost(ret);
927  /* With flags & ~DC_EXEC CmdLandscapeClear would fail since the rail still exists */
928  continue;
929  }
930  }
931  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
932  if (ret.Failed()) return ret;
933  cost.AddCost(ret);
934  }
935  }
936 
937  return cost;
938 }
939 
952 static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
953 {
955  int allowed_z = -1;
956 
957  TILE_AREA_LOOP(cur_tile, tile_area) {
958  CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through);
959  if (ret.Failed()) return ret;
960  cost.AddCost(ret);
961 
962  /* If station is set, then we have special handling to allow building on top of already existing stations.
963  * Station points to INVALID_STATION if we can build on any station.
964  * Or it points to a station if we're only allowed to build on exactly that station. */
965  if (station != nullptr && IsTileType(cur_tile, MP_STATION)) {
966  if (!IsRoadStop(cur_tile)) {
967  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
968  } else {
969  if (is_truck_stop != IsTruckStop(cur_tile) ||
970  is_drive_through != IsDriveThroughStopTile(cur_tile)) {
971  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
972  }
973  /* Drive-through station in the wrong direction. */
974  if (is_drive_through && IsDriveThroughStopTile(cur_tile) && DiagDirToAxis(GetRoadStopDir(cur_tile)) != axis){
975  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
976  }
977  StationID st = GetStationIndex(cur_tile);
978  if (*station == INVALID_STATION) {
979  *station = st;
980  } else if (*station != st) {
981  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
982  }
983  }
984  } else {
985  bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
986  /* Road bits in the wrong direction. */
987  RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE;
988  if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) {
989  /* Someone was pedantic and *NEEDED* three fracking different error messages. */
990  switch (CountBits(rb)) {
991  case 1:
992  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
993 
994  case 2:
995  if (rb == ROAD_X || rb == ROAD_Y) return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
996  return_cmd_error(STR_ERROR_DRIVE_THROUGH_CORNER);
997 
998  default: // 3 or 4
999  return_cmd_error(STR_ERROR_DRIVE_THROUGH_JUNCTION);
1000  }
1001  }
1002 
1003  if (build_over_road) {
1004  /* There is a road, check if we can build road+tram stop over it. */
1005  RoadType road_rt = GetRoadType(cur_tile, RTT_ROAD);
1006  if (road_rt != INVALID_ROADTYPE) {
1007  Owner road_owner = GetRoadOwner(cur_tile, RTT_ROAD);
1008  if (road_owner == OWNER_TOWN) {
1009  if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
1010  } else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE) {
1011  CommandCost ret = CheckOwnership(road_owner);
1012  if (ret.Failed()) return ret;
1013  }
1014  uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD));
1015 
1016  if (RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
1017 
1018  if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE && road_owner != OWNER_TOWN) {
1019  CommandCost ret = CheckOwnership(road_owner);
1020  if (ret.Failed()) return ret;
1021  }
1022 
1023  cost.AddCost(RoadBuildCost(road_rt) * (2 - num_pieces));
1024  } else if (RoadTypeIsRoad(rt)) {
1025  cost.AddCost(RoadBuildCost(rt) * 2);
1026  }
1027 
1028  /* There is a tram, check if we can build road+tram stop over it. */
1029  RoadType tram_rt = GetRoadType(cur_tile, RTT_TRAM);
1030  if (tram_rt != INVALID_ROADTYPE) {
1031  Owner tram_owner = GetRoadOwner(cur_tile, RTT_TRAM);
1032  if (Company::IsValidID(tram_owner) &&
1034  /* Disallow breaking end-of-line of someone else
1035  * so trams can still reverse on this tile. */
1036  HasExactlyOneBit(GetRoadBits(cur_tile, RTT_TRAM)))) {
1037  CommandCost ret = CheckOwnership(tram_owner);
1038  if (ret.Failed()) return ret;
1039  }
1040  uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM));
1041 
1042  if (RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
1043 
1044  cost.AddCost(RoadBuildCost(tram_rt) * (2 - num_pieces));
1045  } else if (RoadTypeIsTram(rt)) {
1046  cost.AddCost(RoadBuildCost(rt) * 2);
1047  }
1048  } else {
1049  ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1050  if (ret.Failed()) return ret;
1051  cost.AddCost(ret);
1052  cost.AddCost(RoadBuildCost(rt) * 2);
1053  }
1054  }
1055  }
1056 
1057  return cost;
1058 }
1059 
1068 {
1069  TileArea cur_ta = st->train_station;
1070 
1071  /* determine new size of train station region.. */
1072  int x = min(TileX(cur_ta.tile), TileX(new_ta.tile));
1073  int y = min(TileY(cur_ta.tile), TileY(new_ta.tile));
1074  new_ta.w = max(TileX(cur_ta.tile) + cur_ta.w, TileX(new_ta.tile) + new_ta.w) - x;
1075  new_ta.h = max(TileY(cur_ta.tile) + cur_ta.h, TileY(new_ta.tile) + new_ta.h) - y;
1076  new_ta.tile = TileXY(x, y);
1077 
1078  /* make sure the final size is not too big. */
1080  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1081  }
1082 
1083  return CommandCost();
1084 }
1085 
1086 static inline byte *CreateSingle(byte *layout, int n)
1087 {
1088  int i = n;
1089  do *layout++ = 0; while (--i);
1090  layout[((n - 1) >> 1) - n] = 2;
1091  return layout;
1092 }
1093 
1094 static inline byte *CreateMulti(byte *layout, int n, byte b)
1095 {
1096  int i = n;
1097  do *layout++ = b; while (--i);
1098  if (n > 4) {
1099  layout[0 - n] = 0;
1100  layout[n - 1 - n] = 0;
1101  }
1102  return layout;
1103 }
1104 
1112 void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec)
1113 {
1114  if (statspec != nullptr && statspec->lengths >= plat_len &&
1115  statspec->platforms[plat_len - 1] >= numtracks &&
1116  statspec->layouts[plat_len - 1][numtracks - 1]) {
1117  /* Custom layout defined, follow it. */
1118  memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1],
1119  plat_len * numtracks);
1120  return;
1121  }
1122 
1123  if (plat_len == 1) {
1124  CreateSingle(layout, numtracks);
1125  } else {
1126  if (numtracks & 1) layout = CreateSingle(layout, plat_len);
1127  numtracks >>= 1;
1128 
1129  while (--numtracks >= 0) {
1130  layout = CreateMulti(layout, plat_len, 4);
1131  layout = CreateMulti(layout, plat_len, 6);
1132  }
1133  }
1134 }
1135 
1147 template <class T, StringID error_message>
1148 CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
1149 {
1150  assert(*st == nullptr);
1151  bool check_surrounding = true;
1152 
1154  if (existing_station != INVALID_STATION) {
1155  if (adjacent && existing_station != station_to_join) {
1156  /* You can't build an adjacent station over the top of one that
1157  * already exists. */
1158  return_cmd_error(error_message);
1159  } else {
1160  /* Extend the current station, and don't check whether it will
1161  * be near any other stations. */
1162  *st = T::GetIfValid(existing_station);
1163  check_surrounding = (*st == nullptr);
1164  }
1165  } else {
1166  /* There's no station here. Don't check the tiles surrounding this
1167  * one if the company wanted to build an adjacent station. */
1168  if (adjacent) check_surrounding = false;
1169  }
1170  }
1171 
1172  if (check_surrounding) {
1173  /* Make sure there is no more than one other station around us that is owned by us. */
1174  CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
1175  if (ret.Failed()) return ret;
1176  }
1177 
1178  /* Distant join */
1179  if (*st == nullptr && station_to_join != INVALID_STATION) *st = T::GetIfValid(station_to_join);
1180 
1181  return CommandCost();
1182 }
1183 
1193 static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1194 {
1195  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
1196 }
1197 
1207 CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
1208 {
1209  return FindJoiningBaseStation<Waypoint, STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST>(existing_waypoint, waypoint_to_join, adjacent, ta, wp);
1210 }
1211 
1217 {
1220  v = v->Last();
1222 }
1223 
1229 {
1231  TryPathReserve(v, true, true);
1232  v = v->Last();
1234 }
1235 
1253 CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1254 {
1255  /* Unpack parameters */
1256  RailType rt = Extract<RailType, 0, 6>(p1);
1257  Axis axis = Extract<Axis, 6, 1>(p1);
1258  byte numtracks = GB(p1, 8, 8);
1259  byte plat_len = GB(p1, 16, 8);
1260  bool adjacent = HasBit(p1, 24);
1261 
1262  StationClassID spec_class = Extract<StationClassID, 0, 8>(p2);
1263  byte spec_index = GB(p2, 8, 8);
1264  StationID station_to_join = GB(p2, 16, 16);
1265 
1266  /* Does the authority allow this? */
1267  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile_org, flags);
1268  if (ret.Failed()) return ret;
1269 
1270  if (!ValParamRailtype(rt)) return CMD_ERROR;
1271 
1272  /* Check if the given station class is valid */
1273  if ((uint)spec_class >= StationClass::GetClassCount() || spec_class == STAT_CLASS_WAYP) return CMD_ERROR;
1274  if (spec_index >= StationClass::Get(spec_class)->GetSpecCount()) return CMD_ERROR;
1275  if (plat_len == 0 || numtracks == 0) return CMD_ERROR;
1276 
1277  int w_org, h_org;
1278  if (axis == AXIS_X) {
1279  w_org = plat_len;
1280  h_org = numtracks;
1281  } else {
1282  h_org = plat_len;
1283  w_org = numtracks;
1284  }
1285 
1286  bool reuse = (station_to_join != NEW_STATION);
1287  if (!reuse) station_to_join = INVALID_STATION;
1288  bool distant_join = (station_to_join != INVALID_STATION);
1289 
1290  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1291 
1293 
1294  /* these values are those that will be stored in train_tile and station_platforms */
1295  TileArea new_location(tile_org, w_org, h_org);
1296 
1297  /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
1298  StationID est = INVALID_STATION;
1299  std::vector<Train *> affected_vehicles;
1300  /* Clear the land below the station. */
1301  CommandCost cost = CheckFlatLandRailStation(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
1302  if (cost.Failed()) return cost;
1303  /* Add construction expenses. */
1304  cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);
1305  cost.AddCost(numtracks * plat_len * RailBuildCost(rt));
1306 
1307  Station *st = nullptr;
1308  ret = FindJoiningStation(est, station_to_join, adjacent, new_location, &st);
1309  if (ret.Failed()) return ret;
1310 
1311  ret = BuildStationPart(&st, flags, reuse, new_location, STATIONNAMING_RAIL);
1312  if (ret.Failed()) return ret;
1313 
1314  if (st != nullptr && st->train_station.tile != INVALID_TILE) {
1315  CommandCost ret = CanExpandRailStation(st, new_location, axis);
1316  if (ret.Failed()) return ret;
1317  }
1318 
1319  /* Check if we can allocate a custom stationspec to this station */
1320  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
1321  int specindex = AllocateSpecToStation(statspec, st, (flags & DC_EXEC) != 0);
1322  if (specindex == -1) return_cmd_error(STR_ERROR_TOO_MANY_STATION_SPECS);
1323 
1324  if (statspec != nullptr) {
1325  /* Perform NewStation checks */
1326 
1327  /* Check if the station size is permitted */
1328  if (HasBit(statspec->disallowed_platforms, min(numtracks - 1, 7)) || HasBit(statspec->disallowed_lengths, min(plat_len - 1, 7))) {
1329  return CMD_ERROR;
1330  }
1331 
1332  /* Check if the station is buildable */
1333  if (HasBit(statspec->callback_mask, CBM_STATION_AVAIL)) {
1334  uint16 cb_res = GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, nullptr, INVALID_TILE);
1335  if (cb_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res)) return CMD_ERROR;
1336  }
1337  }
1338 
1339  if (flags & DC_EXEC) {
1340  TileIndexDiff tile_delta;
1341  byte *layout_ptr;
1342  byte numtracks_orig;
1343  Track track;
1344 
1345  st->train_station = new_location;
1346  st->AddFacility(FACIL_TRAIN, new_location.tile);
1347 
1348  st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
1349 
1350  if (statspec != nullptr) {
1351  /* Include this station spec's animation trigger bitmask
1352  * in the station's cached copy. */
1353  st->cached_anim_triggers |= statspec->animation.triggers;
1354  }
1355 
1356  tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1357  track = AxisToTrack(axis);
1358 
1359  layout_ptr = AllocaM(byte, numtracks * plat_len);
1360  GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
1361 
1362  numtracks_orig = numtracks;
1363 
1364  Company *c = Company::Get(st->owner);
1365  TileIndex tile_track = tile_org;
1366  do {
1367  TileIndex tile = tile_track;
1368  int w = plat_len;
1369  do {
1370  byte layout = *layout_ptr++;
1371  if (IsRailStationTile(tile) && HasStationReservation(tile)) {
1372  /* Check for trains having a reservation for this tile. */
1374  if (v != nullptr) {
1375  affected_vehicles.push_back(v);
1377  }
1378  }
1379 
1380  /* Railtype can change when overbuilding. */
1381  if (IsRailStationTile(tile)) {
1382  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]--;
1383  c->infrastructure.station--;
1384  }
1385 
1386  /* Remove animation if overbuilding */
1387  DeleteAnimatedTile(tile);
1388  byte old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0;
1389  MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, rt);
1390  /* Free the spec if we overbuild something */
1391  DeallocateSpecFromStation(st, old_specindex);
1392 
1393  SetCustomStationSpecIndex(tile, specindex);
1394  SetStationTileRandomBits(tile, GB(Random(), 0, 4));
1395  SetAnimationFrame(tile, 0);
1396 
1397  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++;
1398  c->infrastructure.station++;
1399 
1400  if (statspec != nullptr) {
1401  /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
1402  uint32 platinfo = GetPlatformInfo(AXIS_X, GetStationGfx(tile), plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
1403 
1404  /* As the station is not yet completely finished, the station does not yet exist. */
1405  uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, nullptr, tile);
1406  if (callback != CALLBACK_FAILED) {
1407  if (callback < 8) {
1408  SetStationGfx(tile, (callback & ~1) + axis);
1409  } else {
1411  }
1412  }
1413 
1414  /* Trigger station animation -- after building? */
1415  TriggerStationAnimation(st, tile, SAT_BUILT);
1416  }
1417 
1418  tile += tile_delta;
1419  } while (--w);
1420  AddTrackToSignalBuffer(tile_track, track, _current_company);
1421  YapfNotifyTrackLayoutChange(tile_track, track);
1422  tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
1423  } while (--numtracks);
1424 
1425  for (uint i = 0; i < affected_vehicles.size(); ++i) {
1426  /* Restore reservations of trains. */
1427  RestoreTrainReservation(affected_vehicles[i]);
1428  }
1429 
1430  /* Check whether we need to expand the reservation of trains already on the station. */
1431  TileArea update_reservation_area;
1432  if (axis == AXIS_X) {
1433  update_reservation_area = TileArea(tile_org, 1, numtracks_orig);
1434  } else {
1435  update_reservation_area = TileArea(tile_org, numtracks_orig, 1);
1436  }
1437 
1438  TILE_AREA_LOOP(tile, update_reservation_area) {
1439  /* Don't even try to make eye candy parts reserved. */
1440  if (IsStationTileBlocked(tile)) continue;
1441 
1442  DiagDirection dir = AxisToDiagDir(axis);
1443  TileIndexDiff tile_offset = TileOffsByDiagDir(dir);
1444  TileIndex platform_begin = tile;
1445  TileIndex platform_end = tile;
1446 
1447  /* We can only account for tiles that are reachable from this tile, so ignore primarily blocked tiles while finding the platform begin and end. */
1448  for (TileIndex next_tile = platform_begin - tile_offset; IsCompatibleTrainStationTile(next_tile, platform_begin); next_tile -= tile_offset) {
1449  platform_begin = next_tile;
1450  }
1451  for (TileIndex next_tile = platform_end + tile_offset; IsCompatibleTrainStationTile(next_tile, platform_end); next_tile += tile_offset) {
1452  platform_end = next_tile;
1453  }
1454 
1455  /* If there is at least on reservation on the platform, we reserve the whole platform. */
1456  bool reservation = false;
1457  for (TileIndex t = platform_begin; !reservation && t <= platform_end; t += tile_offset) {
1458  reservation = HasStationReservation(t);
1459  }
1460 
1461  if (reservation) {
1462  SetRailStationPlatformReservation(platform_begin, dir, true);
1463  }
1464  }
1465 
1466  st->MarkTilesDirty(false);
1467  st->AfterStationTileSetChange(true, STATION_RAIL);
1468  }
1469 
1470  return cost;
1471 }
1472 
1473 static TileArea MakeStationAreaSmaller(BaseStation *st, TileArea ta, bool (*func)(BaseStation *, TileIndex))
1474 {
1475 restart:
1476 
1477  /* too small? */
1478  if (ta.w != 0 && ta.h != 0) {
1479  /* check the left side, x = constant, y changes */
1480  for (uint i = 0; !func(st, ta.tile + TileDiffXY(0, i));) {
1481  /* the left side is unused? */
1482  if (++i == ta.h) {
1483  ta.tile += TileDiffXY(1, 0);
1484  ta.w--;
1485  goto restart;
1486  }
1487  }
1488 
1489  /* check the right side, x = constant, y changes */
1490  for (uint i = 0; !func(st, ta.tile + TileDiffXY(ta.w - 1, i));) {
1491  /* the right side is unused? */
1492  if (++i == ta.h) {
1493  ta.w--;
1494  goto restart;
1495  }
1496  }
1497 
1498  /* check the upper side, y = constant, x changes */
1499  for (uint i = 0; !func(st, ta.tile + TileDiffXY(i, 0));) {
1500  /* the left side is unused? */
1501  if (++i == ta.w) {
1502  ta.tile += TileDiffXY(0, 1);
1503  ta.h--;
1504  goto restart;
1505  }
1506  }
1507 
1508  /* check the lower side, y = constant, x changes */
1509  for (uint i = 0; !func(st, ta.tile + TileDiffXY(i, ta.h - 1));) {
1510  /* the left side is unused? */
1511  if (++i == ta.w) {
1512  ta.h--;
1513  goto restart;
1514  }
1515  }
1516  } else {
1517  ta.Clear();
1518  }
1519 
1520  return ta;
1521 }
1522 
1523 static bool TileBelongsToRailStation(BaseStation *st, TileIndex tile)
1524 {
1525  return st->TileBelongsToRailStation(tile);
1526 }
1527 
1528 static void MakeRailStationAreaSmaller(BaseStation *st)
1529 {
1530  st->train_station = MakeStationAreaSmaller(st, st->train_station, TileBelongsToRailStation);
1531 }
1532 
1533 static bool TileBelongsToShipStation(BaseStation *st, TileIndex tile)
1534 {
1535  return IsDockTile(tile) && GetStationIndex(tile) == st->index;
1536 }
1537 
1538 static void MakeShipStationAreaSmaller(Station *st)
1539 {
1540  st->ship_station = MakeStationAreaSmaller(st, st->ship_station, TileBelongsToShipStation);
1541  UpdateStationDockingTiles(st);
1542 }
1543 
1554 template <class T>
1555 CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
1556 {
1557  /* Count of the number of tiles removed */
1558  int quantity = 0;
1559  CommandCost total_cost(EXPENSES_CONSTRUCTION);
1560  /* Accumulator for the errors seen during clearing. If no errors happen,
1561  * and the quantity is 0 there is no station. Otherwise it will be one
1562  * of the other error that got accumulated. */
1564 
1565  /* Do the action for every tile into the area */
1566  TILE_AREA_LOOP(tile, ta) {
1567  /* Make sure the specified tile is a rail station */
1568  if (!HasStationTileRail(tile)) continue;
1569 
1570  /* If there is a vehicle on ground, do not allow to remove (flood) the tile */
1572  error.AddCost(ret);
1573  if (ret.Failed()) continue;
1574 
1575  /* Check ownership of station */
1576  T *st = T::GetByTile(tile);
1577  if (st == nullptr) continue;
1578 
1579  if (_current_company != OWNER_WATER) {
1580  CommandCost ret = CheckOwnership(st->owner);
1581  error.AddCost(ret);
1582  if (ret.Failed()) continue;
1583  }
1584 
1585  /* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
1586  quantity++;
1587 
1588  if (keep_rail || IsStationTileBlocked(tile)) {
1589  /* Don't refund the 'steel' of the track when we keep the
1590  * rail, or when the tile didn't have any rail at all. */
1591  total_cost.AddCost(-_price[PR_CLEAR_RAIL]);
1592  }
1593 
1594  if (flags & DC_EXEC) {
1595  /* read variables before the station tile is removed */
1596  uint specindex = GetCustomStationSpecIndex(tile);
1597  Track track = GetRailStationTrack(tile);
1598  Owner owner = GetTileOwner(tile);
1599  RailType rt = GetRailType(tile);
1600  Train *v = nullptr;
1601 
1602  if (HasStationReservation(tile)) {
1603  v = GetTrainForReservation(tile, track);
1604  if (v != nullptr) FreeTrainReservation(v);
1605  }
1606 
1607  bool build_rail = keep_rail && !IsStationTileBlocked(tile);
1608  if (!build_rail && !IsStationTileBlocked(tile)) Company::Get(owner)->infrastructure.rail[rt]--;
1609 
1610  DoClearSquare(tile);
1611  DeleteNewGRFInspectWindow(GSF_STATIONS, tile);
1612  if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt);
1613  Company::Get(owner)->infrastructure.station--;
1615 
1616  st->rect.AfterRemoveTile(st, tile);
1617  AddTrackToSignalBuffer(tile, track, owner);
1618  YapfNotifyTrackLayoutChange(tile, track);
1619 
1620  DeallocateSpecFromStation(st, specindex);
1621 
1622  include(affected_stations, st);
1623 
1624  if (v != nullptr) RestoreTrainReservation(v);
1625  }
1626  }
1627 
1628  if (quantity == 0) return error.Failed() ? error : CommandCost(STR_ERROR_THERE_IS_NO_STATION);
1629 
1630  for (T *st : affected_stations) {
1631 
1632  /* now we need to make the "spanned" area of the railway station smaller
1633  * if we deleted something at the edges.
1634  * we also need to adjust train_tile. */
1635  MakeRailStationAreaSmaller(st);
1636  UpdateStationSignCoord(st);
1637 
1638  /* if we deleted the whole station, delete the train facility. */
1639  if (st->train_station.tile == INVALID_TILE) {
1640  st->facilities &= ~FACIL_TRAIN;
1642  st->UpdateVirtCoord();
1644  }
1645  }
1646 
1647  total_cost.AddCost(quantity * removal_cost);
1648  return total_cost;
1649 }
1650 
1662 CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1663 {
1664  TileIndex end = p1 == 0 ? start : p1;
1665  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1666 
1667  TileArea ta(start, end);
1668  std::vector<Station *> affected_stations;
1669 
1670  CommandCost ret = RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_STATION_RAIL], HasBit(p2, 0));
1671  if (ret.Failed()) return ret;
1672 
1673  /* Do all station specific functions here. */
1674  for (Station *st : affected_stations) {
1675 
1677  st->MarkTilesDirty(false);
1678  st->RecomputeCatchment();
1679  }
1680 
1681  /* Now apply the rail cost to the number that we deleted */
1682  return ret;
1683 }
1684 
1696 CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1697 {
1698  TileIndex end = p1 == 0 ? start : p1;
1699  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1700 
1701  TileArea ta(start, end);
1702  std::vector<Waypoint *> affected_stations;
1703 
1704  return RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_WAYPOINT_RAIL], HasBit(p2, 0));
1705 }
1706 
1707 
1716 template <class T>
1718 {
1719  /* Current company owns the station? */
1720  if (_current_company != OWNER_WATER) {
1721  CommandCost ret = CheckOwnership(st->owner);
1722  if (ret.Failed()) return ret;
1723  }
1724 
1725  /* determine width and height of platforms */
1726  TileArea ta = st->train_station;
1727 
1728  assert(ta.w != 0 && ta.h != 0);
1729 
1731  /* clear all areas of the station */
1732  TILE_AREA_LOOP(tile, ta) {
1733  /* only remove tiles that are actually train station tiles */
1734  if (st->TileBelongsToRailStation(tile)) {
1735  std::vector<T*> affected_stations; // dummy
1736  CommandCost ret = RemoveFromRailBaseStation(TileArea(tile, 1, 1), affected_stations, flags, removal_cost, false);
1737  if (ret.Failed()) return ret;
1738  cost.AddCost(ret);
1739  }
1740  }
1741 
1742  return cost;
1743 }
1744 
1752 {
1753  /* if there is flooding, remove platforms tile by tile */
1754  if (_current_company == OWNER_WATER) {
1755  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_STATION);
1756  }
1757 
1758  Station *st = Station::GetByTile(tile);
1759  CommandCost cost = RemoveRailStation(st, flags, _price[PR_CLEAR_STATION_RAIL]);
1760 
1761  if (flags & DC_EXEC) st->RecomputeCatchment();
1762 
1763  return cost;
1764 }
1765 
1773 {
1774  /* if there is flooding, remove waypoints tile by tile */
1775  if (_current_company == OWNER_WATER) {
1776  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_WAYPOINT);
1777  }
1778 
1779  return RemoveRailStation(Waypoint::GetByTile(tile), flags, _price[PR_CLEAR_WAYPOINT_RAIL]);
1780 }
1781 
1782 
1788 static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
1789 {
1790  RoadStop **primary_stop = (truck_station) ? &st->truck_stops : &st->bus_stops;
1791 
1792  if (*primary_stop == nullptr) {
1793  /* we have no roadstop of the type yet, so write a "primary stop" */
1794  return primary_stop;
1795  } else {
1796  /* there are stops already, so append to the end of the list */
1797  RoadStop *stop = *primary_stop;
1798  while (stop->next != nullptr) stop = stop->next;
1799  return &stop->next;
1800  }
1801 }
1802 
1804 
1814 static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1815 {
1816  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST>(existing_stop, station_to_join, adjacent, ta, st);
1817 }
1818 
1835 CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1836 {
1837  bool type = HasBit(p2, 0);
1838  bool is_drive_through = HasBit(p2, 1);
1839  RoadType rt = Extract<RoadType, 5, 6>(p2);
1840  if (!ValParamRoadType(rt)) return CMD_ERROR;
1841  StationID station_to_join = GB(p2, 16, 16);
1842  bool reuse = (station_to_join != NEW_STATION);
1843  if (!reuse) station_to_join = INVALID_STATION;
1844  bool distant_join = (station_to_join != INVALID_STATION);
1845 
1846  uint8 width = (uint8)GB(p1, 0, 8);
1847  uint8 length = (uint8)GB(p1, 8, 8);
1848 
1849  /* Check if the requested road stop is too big */
1850  if (width > _settings_game.station.station_spread || length > _settings_game.station.station_spread) return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1851  /* Check for incorrect width / length. */
1852  if (width == 0 || length == 0) return CMD_ERROR;
1853  /* Check if the first tile and the last tile are valid */
1854  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, length - 1) == INVALID_TILE) return CMD_ERROR;
1855 
1856  TileArea roadstop_area(tile, width, length);
1857 
1858  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1859 
1860  /* Trams only have drive through stops */
1861  if (!is_drive_through && RoadTypeIsTram(rt)) return CMD_ERROR;
1862 
1863  DiagDirection ddir;
1864  Axis axis;
1865  if (is_drive_through) {
1866  /* By definition axis is valid, due to there being 2 axes and reading 1 bit. */
1867  axis = Extract<Axis, 3, 1>(p2);
1868  ddir = AxisToDiagDir(axis);
1869  } else {
1870  /* By definition ddir is valid, due to there being 4 diagonal directions and reading 2 bits. */
1871  ddir = Extract<DiagDirection, 3, 2>(p2);
1872  axis = DiagDirToAxis(ddir);
1873  }
1874 
1875  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
1876  if (ret.Failed()) return ret;
1877 
1878  /* Total road stop cost. */
1879  CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
1880  StationID est = INVALID_STATION;
1881  ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rt);
1882  if (ret.Failed()) return ret;
1883  cost.AddCost(ret);
1884 
1885  Station *st = nullptr;
1886  ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 2), roadstop_area, &st);
1887  if (ret.Failed()) return ret;
1888 
1889  /* Check if this number of road stops can be allocated. */
1890  if (!RoadStop::CanAllocateItem(roadstop_area.w * roadstop_area.h)) return_cmd_error(type ? STR_ERROR_TOO_MANY_TRUCK_STOPS : STR_ERROR_TOO_MANY_BUS_STOPS);
1891 
1892  ret = BuildStationPart(&st, flags, reuse, roadstop_area, STATIONNAMING_ROAD);
1893  if (ret.Failed()) return ret;
1894 
1895  if (flags & DC_EXEC) {
1896  /* Check every tile in the area. */
1897  TILE_AREA_LOOP(cur_tile, roadstop_area) {
1898  /* Get existing road types and owners before any tile clearing */
1899  RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE;
1900  RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE;
1901  Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company;
1902  Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company;
1903 
1904  if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
1905  RemoveRoadStop(cur_tile, flags);
1906  }
1907 
1908  RoadStop *road_stop = new RoadStop(cur_tile);
1909  /* Insert into linked list of RoadStops. */
1910  RoadStop **currstop = FindRoadStopSpot(type, st);
1911  *currstop = road_stop;
1912 
1913  if (type) {
1914  st->truck_station.Add(cur_tile);
1915  } else {
1916  st->bus_station.Add(cur_tile);
1917  }
1918 
1919  /* Initialize an empty station. */
1920  st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, cur_tile);
1921 
1922  st->rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
1923 
1924  RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
1925  if (is_drive_through) {
1926  /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old
1927  * bits first. */
1928  if (IsNormalRoadTile(cur_tile)) {
1929  UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD)));
1930  UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM)));
1931  }
1932 
1933  if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt;
1934  if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt;
1935 
1936  UpdateCompanyRoadInfrastructure(road_rt, road_owner, 2);
1937  UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, 2);
1938 
1939  MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, road_rt, tram_rt, axis);
1940  road_stop->MakeDriveThrough();
1941  } else {
1942  if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt;
1943  if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt;
1944  /* Non-drive-through stop never overbuild and always count as two road bits. */
1945  Company::Get(st->owner)->infrastructure.road[rt] += 2;
1946  MakeRoadStop(cur_tile, st->owner, st->index, rs_type, road_rt, tram_rt, ddir);
1947  }
1948  Company::Get(st->owner)->infrastructure.station++;
1949 
1950  MarkTileDirtyByTile(cur_tile);
1951  }
1952  }
1953 
1954  if (st != nullptr) {
1955  st->AfterStationTileSetChange(true, type ? STATION_TRUCK: STATION_BUS);
1956  }
1957  return cost;
1958 }
1959 
1960 
1961 static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
1962 {
1963  if (v->type == VEH_ROAD) {
1964  /* Okay... we are a road vehicle on a drive through road stop.
1965  * But that road stop has just been removed, so we need to make
1966  * sure we are in a valid state... however, vehicles can also
1967  * turn on road stop tiles, so only clear the 'road stop' state
1968  * bits and only when the state was 'in road stop', otherwise
1969  * we'll end up clearing the turn around bits. */
1970  RoadVehicle *rv = RoadVehicle::From(v);
1972  }
1973 
1974  return nullptr;
1975 }
1976 
1977 
1985 {
1986  Station *st = Station::GetByTile(tile);
1987 
1988  if (_current_company != OWNER_WATER) {
1989  CommandCost ret = CheckOwnership(st->owner);
1990  if (ret.Failed()) return ret;
1991  }
1992 
1993  bool is_truck = IsTruckStop(tile);
1994 
1995  RoadStop **primary_stop;
1996  RoadStop *cur_stop;
1997  if (is_truck) { // truck stop
1998  primary_stop = &st->truck_stops;
1999  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_TRUCK);
2000  } else {
2001  primary_stop = &st->bus_stops;
2002  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_BUS);
2003  }
2004 
2005  assert(cur_stop != nullptr);
2006 
2007  /* don't do the check for drive-through road stops when company bankrupts */
2008  if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
2009  /* remove the 'going through road stop' status from all vehicles on that tile */
2010  if (flags & DC_EXEC) FindVehicleOnPos(tile, nullptr, &ClearRoadStopStatusEnum);
2011  } else {
2013  if (ret.Failed()) return ret;
2014  }
2015 
2016  if (flags & DC_EXEC) {
2017  if (*primary_stop == cur_stop) {
2018  /* removed the first stop in the list */
2019  *primary_stop = cur_stop->next;
2020  /* removed the only stop? */
2021  if (*primary_stop == nullptr) {
2022  st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
2023  }
2024  } else {
2025  /* tell the predecessor in the list to skip this stop */
2026  RoadStop *pred = *primary_stop;
2027  while (pred->next != cur_stop) pred = pred->next;
2028  pred->next = cur_stop->next;
2029  }
2030 
2031  /* Update company infrastructure counts. */
2032  FOR_ALL_ROADTRAMTYPES(rtt) {
2033  RoadType rt = GetRoadType(tile, rtt);
2034  UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), -2);
2035  }
2036 
2037  Company::Get(st->owner)->infrastructure.station--;
2039 
2040  if (IsDriveThroughStopTile(tile)) {
2041  /* Clears the tile for us */
2042  cur_stop->ClearDriveThrough();
2043  } else {
2044  DoClearSquare(tile);
2045  }
2046 
2047  delete cur_stop;
2048 
2049  /* Make sure no vehicle is going to the old roadstop */
2050  for (RoadVehicle *v : RoadVehicle::Iterate()) {
2051  if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
2052  v->dest_tile == tile) {
2053  v->SetDestTile(v->GetOrderStationLocation(st->index));
2054  }
2055  }
2056 
2057  st->rect.AfterRemoveTile(st, tile);
2058 
2059  st->AfterStationTileSetChange(false, is_truck ? STATION_TRUCK: STATION_BUS);
2060 
2061  /* Update the tile area of the truck/bus stop */
2062  if (is_truck) {
2063  st->truck_station.Clear();
2064  for (const RoadStop *rs = st->truck_stops; rs != nullptr; rs = rs->next) st->truck_station.Add(rs->xy);
2065  } else {
2066  st->bus_station.Clear();
2067  for (const RoadStop *rs = st->bus_stops; rs != nullptr; rs = rs->next) st->bus_station.Add(rs->xy);
2068  }
2069  }
2070 
2071  return CommandCost(EXPENSES_CONSTRUCTION, _price[is_truck ? PR_CLEAR_STATION_TRUCK : PR_CLEAR_STATION_BUS]);
2072 }
2073 
2085 CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2086 {
2087  uint8 width = (uint8)GB(p1, 0, 8);
2088  uint8 height = (uint8)GB(p1, 8, 8);
2089  bool keep_drive_through_roads = !HasBit(p2, 1);
2090 
2091  /* Check for incorrect width / height. */
2092  if (width == 0 || height == 0) return CMD_ERROR;
2093  /* Check if the first tile and the last tile are valid */
2094  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, height - 1) == INVALID_TILE) return CMD_ERROR;
2095  /* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
2096  if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
2097 
2098  TileArea roadstop_area(tile, width, height);
2099 
2101  CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
2102  bool had_success = false;
2103 
2104  TILE_AREA_LOOP(cur_tile, roadstop_area) {
2105  /* Make sure the specified tile is a road stop of the correct type */
2106  if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
2107 
2108  /* Save information on to-be-restored roads before the stop is removed. */
2109  RoadBits road_bits = ROAD_NONE;
2110  RoadType road_type[] = { INVALID_ROADTYPE, INVALID_ROADTYPE };
2111  Owner road_owner[] = { OWNER_NONE, OWNER_NONE };
2112  if (IsDriveThroughStopTile(cur_tile)) {
2113  FOR_ALL_ROADTRAMTYPES(rtt) {
2114  road_type[rtt] = GetRoadType(cur_tile, rtt);
2115  if (road_type[rtt] == INVALID_ROADTYPE) continue;
2116  road_owner[rtt] = GetRoadOwner(cur_tile, rtt);
2117  /* If we don't want to preserve our roads then restore only roads of others. */
2118  if (!keep_drive_through_roads && road_owner[rtt] == _current_company) road_type[rtt] = INVALID_ROADTYPE;
2119  }
2120  road_bits = AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(cur_tile)));
2121  }
2122 
2123  CommandCost ret = RemoveRoadStop(cur_tile, flags);
2124  if (ret.Failed()) {
2125  last_error = ret;
2126  continue;
2127  }
2128  cost.AddCost(ret);
2129  had_success = true;
2130 
2131  /* Restore roads. */
2132  if ((flags & DC_EXEC) && (road_type[RTT_ROAD] != INVALID_ROADTYPE || road_type[RTT_TRAM] != INVALID_ROADTYPE)) {
2133  MakeRoadNormal(cur_tile, road_bits, road_type[RTT_ROAD], road_type[RTT_TRAM], ClosestTownFromTile(cur_tile, UINT_MAX)->index,
2134  road_owner[RTT_ROAD], road_owner[RTT_TRAM]);
2135 
2136  /* Update company infrastructure counts. */
2137  int count = CountBits(road_bits);
2138  UpdateCompanyRoadInfrastructure(road_type[RTT_ROAD], road_owner[RTT_ROAD], count);
2139  UpdateCompanyRoadInfrastructure(road_type[RTT_TRAM], road_owner[RTT_TRAM], count);
2140  }
2141  }
2142 
2143  return had_success ? cost : last_error;
2144 }
2145 
2154 uint8 GetAirportNoiseLevelForDistance(const AirportSpec *as, uint distance)
2155 {
2156  /* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
2157  * So no need to go any further*/
2158  if (as->noise_level < 2) return as->noise_level;
2159 
2160  /* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
2161  * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
2162  * Basically, it says that the less tolerant a town is, the bigger the distance before
2163  * an actual decrease can be granted */
2164  uint8 town_tolerance_distance = 8 + (_settings_game.difficulty.town_council_tolerance * 4);
2165 
2166  /* now, we want to have the distance segmented using the distance judged bareable by town
2167  * This will give us the coefficient of reduction the distance provides. */
2168  uint noise_reduction = distance / town_tolerance_distance;
2169 
2170  /* If the noise reduction equals the airport noise itself, don't give it for free.
2171  * Otherwise, simply reduce the airport's level. */
2172  return noise_reduction >= as->noise_level ? 1 : as->noise_level - noise_reduction;
2173 }
2174 
2183 Town *AirportGetNearestTown(const AirportSpec *as, const TileIterator &it, uint &mindist)
2184 {
2185  assert(Town::GetNumItems() > 0);
2186 
2187  Town *nearest = nullptr;
2188 
2189  uint perimeter_min_x = TileX(it);
2190  uint perimeter_min_y = TileY(it);
2191  uint perimeter_max_x = perimeter_min_x + as->size_x - 1;
2192  uint perimeter_max_y = perimeter_min_y + as->size_y - 1;
2193 
2194  mindist = UINT_MAX - 1; // prevent overflow
2195 
2196  std::unique_ptr<TileIterator> copy(it.Clone());
2197  for (TileIndex cur_tile = *copy; cur_tile != INVALID_TILE; cur_tile = ++*copy) {
2198  if (TileX(cur_tile) == perimeter_min_x || TileX(cur_tile) == perimeter_max_x || TileY(cur_tile) == perimeter_min_y || TileY(cur_tile) == perimeter_max_y) {
2199  Town *t = CalcClosestTownFromTile(cur_tile, mindist + 1);
2200  if (t == nullptr) continue;
2201 
2202  uint dist = DistanceManhattan(t->xy, cur_tile);
2203  if (dist == mindist && t->index < nearest->index) nearest = t;
2204  if (dist < mindist) {
2205  nearest = t;
2206  mindist = dist;
2207  }
2208  }
2209  }
2210 
2211  return nearest;
2212 }
2213 
2214 
2217 {
2218  for (Town *t : Town::Iterate()) t->noise_reached = 0;
2219 
2220  for (const Station *st : Station::Iterate()) {
2221  if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
2222  const AirportSpec *as = st->airport.GetSpec();
2223  AirportTileIterator it(st);
2224  uint dist;
2225  Town *nearest = AirportGetNearestTown(as, it, dist);
2226  nearest->noise_reached += GetAirportNoiseLevelForDistance(as, dist);
2227  }
2228  }
2229 }
2230 
2244 CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2245 {
2246  StationID station_to_join = GB(p2, 16, 16);
2247  bool reuse = (station_to_join != NEW_STATION);
2248  if (!reuse) station_to_join = INVALID_STATION;
2249  bool distant_join = (station_to_join != INVALID_STATION);
2250  byte airport_type = GB(p1, 0, 8);
2251  byte layout = GB(p1, 8, 8);
2252 
2253  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2254 
2255  if (airport_type >= NUM_AIRPORTS) return CMD_ERROR;
2256 
2257  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2258  if (ret.Failed()) return ret;
2259 
2260  /* Check if a valid, buildable airport was chosen for construction */
2261  const AirportSpec *as = AirportSpec::Get(airport_type);
2262  if (!as->IsAvailable() || layout >= as->num_table) return CMD_ERROR;
2263  if (!as->IsWithinMapBounds(layout, tile)) return CMD_ERROR;
2264 
2265  Direction rotation = as->rotation[layout];
2266  int w = as->size_x;
2267  int h = as->size_y;
2268  if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
2269  TileArea airport_area = TileArea(tile, w, h);
2270 
2272  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
2273  }
2274 
2275  AirportTileTableIterator iter(as->table[layout], tile);
2276  CommandCost cost = CheckFlatLandAirport(iter, flags);
2277  if (cost.Failed()) return cost;
2278 
2279  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
2280  uint dist;
2281  Town *nearest = AirportGetNearestTown(as, iter, dist);
2282  uint newnoise_level = GetAirportNoiseLevelForDistance(as, dist);
2283 
2284  /* Check if local auth would allow a new airport */
2285  StringID authority_refuse_message = STR_NULL;
2286  Town *authority_refuse_town = nullptr;
2287 
2289  /* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
2290  if ((nearest->noise_reached + newnoise_level) > nearest->MaxTownNoise()) {
2291  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE;
2292  authority_refuse_town = nearest;
2293  }
2294  } else {
2295  Town *t = ClosestTownFromTile(tile, UINT_MAX);
2296  uint num = 0;
2297  for (const Station *st : Station::Iterate()) {
2298  if (st->town == t && (st->facilities & FACIL_AIRPORT) && st->airport.type != AT_OILRIG) num++;
2299  }
2300  if (num >= 2) {
2301  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT;
2302  authority_refuse_town = t;
2303  }
2304  }
2305 
2306  if (authority_refuse_message != STR_NULL) {
2307  SetDParam(0, authority_refuse_town->index);
2308  return_cmd_error(authority_refuse_message);
2309  }
2310 
2311  Station *st = nullptr;
2312  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p2, 0), airport_area, &st);
2313  if (ret.Failed()) return ret;
2314 
2315  /* Distant join */
2316  if (st == nullptr && distant_join) st = Station::GetIfValid(station_to_join);
2317 
2318  ret = BuildStationPart(&st, flags, reuse, airport_area, (GetAirport(airport_type)->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_AIRPORT : STATIONNAMING_HELIPORT);
2319  if (ret.Failed()) return ret;
2320 
2321  if (st != nullptr && st->airport.tile != INVALID_TILE) {
2322  return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT);
2323  }
2324 
2325  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2326  cost.AddCost(_price[PR_BUILD_STATION_AIRPORT]);
2327  }
2328 
2329  if (flags & DC_EXEC) {
2330  /* Always add the noise, so there will be no need to recalculate when option toggles */
2331  nearest->noise_reached += newnoise_level;
2332 
2333  st->AddFacility(FACIL_AIRPORT, tile);
2334  st->airport.type = airport_type;
2335  st->airport.layout = layout;
2336  st->airport.flags = 0;
2337  st->airport.rotation = rotation;
2338 
2339  st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
2340 
2341  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2342  MakeAirport(iter, st->owner, st->index, iter.GetStationGfx(), WATER_CLASS_INVALID);
2343  SetStationTileRandomBits(iter, GB(Random(), 0, 4));
2344  st->airport.Add(iter);
2345 
2347  }
2348 
2349  /* Only call the animation trigger after all tiles have been built */
2350  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2351  AirportTileAnimationTrigger(st, iter, AAT_BUILT);
2352  }
2353 
2355 
2356  Company::Get(st->owner)->infrastructure.airport++;
2357 
2358  st->AfterStationTileSetChange(true, STATION_AIRPORT);
2360 
2363  }
2364  }
2365 
2366  return cost;
2367 }
2368 
2376 {
2377  Station *st = Station::GetByTile(tile);
2378 
2379  if (_current_company != OWNER_WATER) {
2380  CommandCost ret = CheckOwnership(st->owner);
2381  if (ret.Failed()) return ret;
2382  }
2383 
2384  tile = st->airport.tile;
2385 
2387 
2388  for (const Aircraft *a : Aircraft::Iterate()) {
2389  if (!a->IsNormalAircraft()) continue;
2390  if (a->targetairport == st->index && a->state != FLYING) {
2391  return_cmd_error(STR_ERROR_AIRCRAFT_IN_THE_WAY);
2392  }
2393  }
2394 
2395  if (flags & DC_EXEC) {
2396  const AirportSpec *as = st->airport.GetSpec();
2397  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
2398  * And as for construction, always remove it, even if the setting is not set, in order to avoid the
2399  * need of recalculation */
2400  AirportTileIterator it(st);
2401  uint dist;
2402  Town *nearest = AirportGetNearestTown(as, it, dist);
2403  nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist);
2404  }
2405 
2406  TILE_AREA_LOOP(tile_cur, st->airport) {
2407  if (!st->TileBelongsToAirport(tile_cur)) continue;
2408 
2409  CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
2410  if (ret.Failed()) return ret;
2411 
2412  cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
2413 
2414  if (flags & DC_EXEC) {
2415  if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
2416  DeleteAnimatedTile(tile_cur);
2417  DoClearSquare(tile_cur);
2418  DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
2419  }
2420  }
2421 
2422  if (flags & DC_EXEC) {
2423  /* Clear the persistent storage. */
2424  delete st->airport.psa;
2425 
2426  for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
2429  );
2430  }
2431 
2432  st->rect.AfterRemoveRect(st, st->airport);
2433 
2434  st->airport.Clear();
2435  st->facilities &= ~FACIL_AIRPORT;
2436 
2438 
2441  }
2442 
2443  Company::Get(st->owner)->infrastructure.airport--;
2444 
2445  st->AfterStationTileSetChange(false, STATION_AIRPORT);
2446 
2447  DeleteNewGRFInspectWindow(GSF_AIRPORTS, st->index);
2448  }
2449 
2450  return cost;
2451 }
2452 
2462 CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2463 {
2464  if (!Station::IsValidID(p1)) return CMD_ERROR;
2465  Station *st = Station::Get(p1);
2466 
2467  if (!(st->facilities & FACIL_AIRPORT) || st->owner == OWNER_NONE) return CMD_ERROR;
2468 
2469  CommandCost ret = CheckOwnership(st->owner);
2470  if (ret.Failed()) return ret;
2471 
2472  if (flags & DC_EXEC) {
2475  }
2476  return CommandCost();
2477 }
2478 
2485 bool HasStationInUse(StationID station, bool include_company, CompanyID company)
2486 {
2487  for (const Vehicle *v : Vehicle::Iterate()) {
2488  if ((v->owner == company) == include_company) {
2489  const Order *order;
2490  FOR_VEHICLE_ORDERS(v, order) {
2491  if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
2492  return true;
2493  }
2494  }
2495  }
2496  }
2497  return false;
2498 }
2499 
2500 static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
2501  {-1, 0},
2502  { 0, 0},
2503  { 0, 0},
2504  { 0, -1}
2505 };
2506 static const byte _dock_w_chk[4] = { 2, 1, 2, 1 };
2507 static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
2508 
2518 CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2519 {
2520  StationID station_to_join = GB(p2, 16, 16);
2521  bool reuse = (station_to_join != NEW_STATION);
2522  if (!reuse) station_to_join = INVALID_STATION;
2523  bool distant_join = (station_to_join != INVALID_STATION);
2524 
2525  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2526 
2528  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2529  direction = ReverseDiagDir(direction);
2530 
2531  /* Docks cannot be placed on rapids */
2532  if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2533 
2534  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2535  if (ret.Failed()) return ret;
2536 
2537  if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2538 
2539  ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2540  if (ret.Failed()) return ret;
2541 
2542  TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
2543 
2544  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2545  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2546  }
2547 
2548  if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2549 
2550  /* Get the water class of the water tile before it is cleared.*/
2551  WaterClass wc = GetWaterClass(tile_cur);
2552 
2553  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2554  if (ret.Failed()) return ret;
2555 
2556  tile_cur += TileOffsByDiagDir(direction);
2557  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2558  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2559  }
2560 
2561  TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
2562  _dock_w_chk[direction], _dock_h_chk[direction]);
2563 
2564  /* middle */
2565  Station *st = nullptr;
2566  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p1, 0), dock_area, &st);
2567  if (ret.Failed()) return ret;
2568 
2569  /* Distant join */
2570  if (st == nullptr && distant_join) st = Station::GetIfValid(station_to_join);
2571 
2572  ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK);
2573  if (ret.Failed()) return ret;
2574 
2575  if (flags & DC_EXEC) {
2576  st->ship_station.Add(tile);
2577  st->ship_station.Add(tile + TileOffsByDiagDir(direction));
2578  st->AddFacility(FACIL_DOCK, tile);
2579 
2580  st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY);
2581 
2582  /* If the water part of the dock is on a canal, update infrastructure counts.
2583  * This is needed as we've unconditionally cleared that tile before. */
2584  if (wc == WATER_CLASS_CANAL) {
2585  Company::Get(st->owner)->infrastructure.water++;
2586  }
2587  Company::Get(st->owner)->infrastructure.station += 2;
2588 
2589  MakeDock(tile, st->owner, st->index, direction, wc);
2590  UpdateStationDockingTiles(st);
2591 
2592  st->AfterStationTileSetChange(true, STATION_DOCK);
2593  }
2594 
2595  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
2596 }
2597 
2598 void RemoveDockingTile(TileIndex t)
2599 {
2600  for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
2601  TileIndex tile = t + TileOffsByDiagDir(d);
2602  if (!IsValidTile(tile)) continue;
2603 
2604  if (IsTileType(tile, MP_STATION)) {
2605  Station *st = Station::GetByTile(tile);
2606  if (st != nullptr) UpdateStationDockingTiles(st);
2607  } else if (IsTileType(tile, MP_INDUSTRY)) {
2608  Station *neutral = Industry::GetByTile(tile)->neutral_station;
2609  if (neutral != nullptr) UpdateStationDockingTiles(neutral);
2610  }
2611  }
2612 }
2613 
2620 {
2621  assert(IsValidTile(tile));
2622 
2623  /* Clear and maybe re-set docking tile */
2624  for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
2625  TileIndex docking_tile = tile + TileOffsByDiagDir(d);
2626  if (!IsValidTile(docking_tile)) continue;
2627 
2628  if (IsPossibleDockingTile(docking_tile)) {
2629  SetDockingTile(docking_tile, false);
2630  CheckForDockingTile(docking_tile);
2631  }
2632  }
2633 }
2634 
2642 {
2643  assert(IsDockTile(t));
2644 
2646  static const uint8 _valid_docking_tile[] = {
2647  0, 0, 0, 0, // No docking against the slope part.
2648  1 << DIAGDIR_NE | 1 << DIAGDIR_SW, // Docking permitted at the end
2649  1 << DIAGDIR_NW | 1 << DIAGDIR_SE, // of the flat piers.
2650  };
2651 
2652  StationGfx gfx = GetStationGfx(t);
2653  assert(gfx < lengthof(_valid_docking_tile));
2654  return HasBit(_valid_docking_tile[gfx], d);
2655 }
2656 
2663 {
2664  assert(IsDockTile(t));
2665 
2666  StationGfx gfx = GetStationGfx(t);
2667  if (gfx < GFX_DOCK_BASE_WATER_PART) return t;
2668 
2669  for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
2670  TileIndex tile = t + TileOffsByDiagDir(d);
2671  if (!IsValidTile(tile)) continue;
2672  if (!IsDockTile(tile)) continue;
2673  if (GetStationGfx(tile) < GFX_DOCK_BASE_WATER_PART && tile + TileOffsByDiagDir(GetDockDirection(tile)) == t) return tile;
2674  }
2675 
2676  return INVALID_TILE;
2677 }
2678 
2686 {
2687  Station *st = Station::GetByTile(tile);
2688  CommandCost ret = CheckOwnership(st->owner);
2689  if (ret.Failed()) return ret;
2690 
2691  if (!IsDockTile(tile)) return CMD_ERROR;
2692 
2693  TileIndex tile1 = FindDockLandPart(tile);
2694  if (tile1 == INVALID_TILE) return CMD_ERROR;
2695  TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
2696 
2697  ret = EnsureNoVehicleOnGround(tile1);
2698  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
2699  if (ret.Failed()) return ret;
2700 
2701  if (flags & DC_EXEC) {
2702  DoClearSquare(tile1);
2703  MarkTileDirtyByTile(tile1);
2704  MakeWaterKeepingClass(tile2, st->owner);
2705 
2706  st->rect.AfterRemoveTile(st, tile1);
2707  st->rect.AfterRemoveTile(st, tile2);
2708 
2709  MakeShipStationAreaSmaller(st);
2710  if (st->ship_station.tile == INVALID_TILE) {
2711  st->ship_station.Clear();
2712  st->docking_station.Clear();
2713  st->facilities &= ~FACIL_DOCK;
2714  }
2715 
2716  Company::Get(st->owner)->infrastructure.station -= 2;
2717 
2718  st->AfterStationTileSetChange(false, STATION_DOCK);
2719 
2722 
2723  /* All ships that were going to our station, can't go to it anymore.
2724  * Just clear the order, then automatically the next appropriate order
2725  * will be selected and in case of no appropriate order it will just
2726  * wander around the world. */
2727  if (!(st->facilities & FACIL_DOCK)) {
2728  for (Ship *s : Ship::Iterate()) {
2729  if (s->current_order.IsType(OT_LOADING) && s->current_order.GetDestination() == st->index) {
2730  s->LeaveStation();
2731  }
2732 
2733  if (s->current_order.IsType(OT_GOTO_STATION) && s->current_order.GetDestination() == st->index) {
2734  s->SetDestTile(s->GetOrderStationLocation(st->index));
2735  }
2736  }
2737  }
2738  }
2739 
2740  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_DOCK]);
2741 }
2742 
2743 #include "table/station_land.h"
2744 
2745 const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
2746 {
2747  return &_station_display_datas[st][gfx];
2748 }
2749 
2759 bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset)
2760 {
2761  bool snow_desert;
2762  switch (*ground) {
2763  case SPR_RAIL_TRACK_X:
2764  case SPR_MONO_TRACK_X:
2765  case SPR_MGLV_TRACK_X:
2766  snow_desert = false;
2767  *overlay_offset = RTO_X;
2768  break;
2769 
2770  case SPR_RAIL_TRACK_Y:
2771  case SPR_MONO_TRACK_Y:
2772  case SPR_MGLV_TRACK_Y:
2773  snow_desert = false;
2774  *overlay_offset = RTO_Y;
2775  break;
2776 
2777  case SPR_RAIL_TRACK_X_SNOW:
2778  case SPR_MONO_TRACK_X_SNOW:
2779  case SPR_MGLV_TRACK_X_SNOW:
2780  snow_desert = true;
2781  *overlay_offset = RTO_X;
2782  break;
2783 
2784  case SPR_RAIL_TRACK_Y_SNOW:
2785  case SPR_MONO_TRACK_Y_SNOW:
2786  case SPR_MGLV_TRACK_Y_SNOW:
2787  snow_desert = true;
2788  *overlay_offset = RTO_Y;
2789  break;
2790 
2791  default:
2792  return false;
2793  }
2794 
2795  if (ti != nullptr) {
2796  /* Decide snow/desert from tile */
2798  case LT_ARCTIC:
2799  snow_desert = (uint)ti->z > GetSnowLine() * TILE_HEIGHT;
2800  break;
2801 
2802  case LT_TROPIC:
2803  snow_desert = GetTropicZone(ti->tile) == TROPICZONE_DESERT;
2804  break;
2805 
2806  default:
2807  break;
2808  }
2809  }
2810 
2811  *ground = snow_desert ? SPR_FLAT_SNOW_DESERT_TILE : SPR_FLAT_GRASS_TILE;
2812  return true;
2813 }
2814 
2815 static void DrawTile_Station(TileInfo *ti)
2816 {
2817  const NewGRFSpriteLayout *layout = nullptr;
2818  DrawTileSprites tmp_rail_layout;
2819  const DrawTileSprites *t = nullptr;
2820  int32 total_offset;
2821  const RailtypeInfo *rti = nullptr;
2822  uint32 relocation = 0;
2823  uint32 ground_relocation = 0;
2824  BaseStation *st = nullptr;
2825  const StationSpec *statspec = nullptr;
2826  uint tile_layout = 0;
2827 
2828  if (HasStationRail(ti->tile)) {
2829  rti = GetRailTypeInfo(GetRailType(ti->tile));
2830  total_offset = rti->GetRailtypeSpriteOffset();
2831 
2832  if (IsCustomStationSpecIndex(ti->tile)) {
2833  /* look for customization */
2834  st = BaseStation::GetByTile(ti->tile);
2835  statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
2836 
2837  if (statspec != nullptr) {
2838  tile_layout = GetStationGfx(ti->tile);
2839 
2841  uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
2842  if (callback != CALLBACK_FAILED) tile_layout = (callback & ~1) + GetRailStationAxis(ti->tile);
2843  }
2844 
2845  /* Ensure the chosen tile layout is valid for this custom station */
2846  if (statspec->renderdata != nullptr) {
2847  layout = &statspec->renderdata[tile_layout < statspec->tiles ? tile_layout : (uint)GetRailStationAxis(ti->tile)];
2848  if (!layout->NeedsPreprocessing()) {
2849  t = layout;
2850  layout = nullptr;
2851  }
2852  }
2853  }
2854  }
2855  } else {
2856  total_offset = 0;
2857  }
2858 
2859  StationGfx gfx = GetStationGfx(ti->tile);
2860  if (IsAirport(ti->tile)) {
2861  gfx = GetAirportGfx(ti->tile);
2862  if (gfx >= NEW_AIRPORTTILE_OFFSET) {
2863  const AirportTileSpec *ats = AirportTileSpec::Get(gfx);
2864  if (ats->grf_prop.spritegroup[0] != nullptr && DrawNewAirportTile(ti, Station::GetByTile(ti->tile), gfx, ats)) {
2865  return;
2866  }
2867  /* No sprite group (or no valid one) found, meaning no graphics associated.
2868  * Use the substitute one instead */
2869  assert(ats->grf_prop.subst_id != INVALID_AIRPORTTILE);
2870  gfx = ats->grf_prop.subst_id;
2871  }
2872  switch (gfx) {
2873  case APT_RADAR_GRASS_FENCE_SW:
2874  t = &_station_display_datas_airport_radar_grass_fence_sw[GetAnimationFrame(ti->tile)];
2875  break;
2876  case APT_GRASS_FENCE_NE_FLAG:
2877  t = &_station_display_datas_airport_flag_grass_fence_ne[GetAnimationFrame(ti->tile)];
2878  break;
2879  case APT_RADAR_FENCE_SW:
2880  t = &_station_display_datas_airport_radar_fence_sw[GetAnimationFrame(ti->tile)];
2881  break;
2882  case APT_RADAR_FENCE_NE:
2883  t = &_station_display_datas_airport_radar_fence_ne[GetAnimationFrame(ti->tile)];
2884  break;
2885  case APT_GRASS_FENCE_NE_FLAG_2:
2886  t = &_station_display_datas_airport_flag_grass_fence_ne_2[GetAnimationFrame(ti->tile)];
2887  break;
2888  }
2889  }
2890 
2891  Owner owner = GetTileOwner(ti->tile);
2892 
2893  PaletteID palette;
2894  if (Company::IsValidID(owner)) {
2895  palette = COMPANY_SPRITE_COLOUR(owner);
2896  } else {
2897  /* Some stations are not owner by a company, namely oil rigs */
2898  palette = PALETTE_TO_GREY;
2899  }
2900 
2901  if (layout == nullptr && (t == nullptr || t->seq == nullptr)) t = GetStationTileLayout(GetStationType(ti->tile), gfx);
2902 
2903  /* don't show foundation for docks */
2904  if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) {
2905  if (statspec != nullptr && HasBit(statspec->flags, SSF_CUSTOM_FOUNDATIONS)) {
2906  /* Station has custom foundations.
2907  * Check whether the foundation continues beyond the tile's upper sides. */
2908  uint edge_info = 0;
2909  int z;
2910  Slope slope = GetFoundationPixelSlope(ti->tile, &z);
2911  if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0);
2912  if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1);
2913  SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, tile_layout, edge_info);
2914  if (image == 0) goto draw_default_foundation;
2915 
2916  if (HasBit(statspec->flags, SSF_EXTENDED_FOUNDATIONS)) {
2917  /* Station provides extended foundations. */
2918 
2919  static const uint8 foundation_parts[] = {
2920  0, 0, 0, 0, // Invalid, Invalid, Invalid, SLOPE_SW
2921  0, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
2922  0, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
2923  7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
2924  };
2925 
2926  AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2927  } else {
2928  /* Draw simple foundations, built up from 8 possible foundation sprites. */
2929 
2930  /* Each set bit represents one of the eight composite sprites to be drawn.
2931  * 'Invalid' entries will not drawn but are included for completeness. */
2932  static const uint8 composite_foundation_parts[] = {
2933  /* Invalid (00000000), Invalid (11010001), Invalid (11100100), SLOPE_SW (11100000) */
2934  0x00, 0xD1, 0xE4, 0xE0,
2935  /* Invalid (11001010), SLOPE_EW (11001001), SLOPE_SE (11000100), SLOPE_WSE (11000000) */
2936  0xCA, 0xC9, 0xC4, 0xC0,
2937  /* Invalid (11010010), SLOPE_NW (10010001), SLOPE_NS (11100100), SLOPE_NWS (10100000) */
2938  0xD2, 0x91, 0xE4, 0xA0,
2939  /* SLOPE_NE (01001010), SLOPE_ENW (00001001), SLOPE_SEN (01000100) */
2940  0x4A, 0x09, 0x44
2941  };
2942 
2943  uint8 parts = composite_foundation_parts[ti->tileh];
2944 
2945  /* If foundations continue beyond the tile's upper sides then
2946  * mask out the last two pieces. */
2947  if (HasBit(edge_info, 0)) ClrBit(parts, 6);
2948  if (HasBit(edge_info, 1)) ClrBit(parts, 7);
2949 
2950  if (parts == 0) {
2951  /* We always have to draw at least one sprite to make sure there is a boundingbox and a sprite with the
2952  * correct offset for the childsprites.
2953  * So, draw the (completely empty) sprite of the default foundations. */
2954  goto draw_default_foundation;
2955  }
2956 
2958  for (int i = 0; i < 8; i++) {
2959  if (HasBit(parts, i)) {
2960  AddSortableSpriteToDraw(image + i, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2961  }
2962  }
2963  EndSpriteCombine();
2964  }
2965 
2966  OffsetGroundSprite(31, 1);
2968  } else {
2969 draw_default_foundation:
2971  }
2972  }
2973 
2974  if (IsBuoy(ti->tile)) {
2975  DrawWaterClassGround(ti);
2976  SpriteID sprite = GetCanalSprite(CF_BUOY, ti->tile);
2977  if (sprite != 0) total_offset = sprite - SPR_IMG_BUOY;
2978  } else if (IsDock(ti->tile) || (IsOilRig(ti->tile) && IsTileOnWater(ti->tile))) {
2979  if (ti->tileh == SLOPE_FLAT) {
2980  DrawWaterClassGround(ti);
2981  } else {
2982  assert(IsDock(ti->tile));
2983  TileIndex water_tile = ti->tile + TileOffsByDiagDir(GetDockDirection(ti->tile));
2984  WaterClass wc = HasTileWaterClass(water_tile) ? GetWaterClass(water_tile) : WATER_CLASS_INVALID;
2985  if (wc == WATER_CLASS_SEA) {
2986  DrawShoreTile(ti->tileh);
2987  } else {
2988  DrawClearLandTile(ti, 3);
2989  }
2990  }
2991  } else {
2992  if (layout != nullptr) {
2993  /* Sprite layout which needs preprocessing */
2994  bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
2995  uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
2996  uint8 var10;
2997  FOR_EACH_SET_BIT(var10, var10_values) {
2998  uint32 var10_relocation = GetCustomStationRelocation(statspec, st, ti->tile, var10);
2999  layout->ProcessRegisters(var10, var10_relocation, separate_ground);
3000  }
3001  tmp_rail_layout.seq = layout->GetLayout(&tmp_rail_layout.ground);
3002  t = &tmp_rail_layout;
3003  total_offset = 0;
3004  } else if (statspec != nullptr) {
3005  /* Simple sprite layout */
3006  ground_relocation = relocation = GetCustomStationRelocation(statspec, st, ti->tile, 0);
3007  if (HasBit(statspec->flags, SSF_SEPARATE_GROUND)) {
3008  ground_relocation = GetCustomStationRelocation(statspec, st, ti->tile, 1);
3009  }
3010  ground_relocation += rti->fallback_railtype;
3011  }
3012 
3013  SpriteID image = t->ground.sprite;
3014  PaletteID pal = t->ground.pal;
3015  RailTrackOffset overlay_offset;
3016  if (rti != nullptr && rti->UsesOverlay() && SplitGroundSpriteForOverlay(ti, &image, &overlay_offset)) {
3017  SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND);
3018  DrawGroundSprite(image, PAL_NONE);
3019  DrawGroundSprite(ground + overlay_offset, PAL_NONE);
3020 
3021  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationReservation(ti->tile)) {
3022  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
3023  DrawGroundSprite(overlay + overlay_offset, PALETTE_CRASH);
3024  }
3025  } else {
3026  image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset;
3027  if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation;
3028  DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
3029 
3030  /* PBS debugging, draw reserved tracks darker */
3031  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationRail(ti->tile) && HasStationReservation(ti->tile)) {
3032  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
3034  }
3035  }
3036  }
3037 
3039 
3040  if (IsRoadStop(ti->tile)) {
3041  RoadType road_rt = GetRoadTypeRoad(ti->tile);
3042  RoadType tram_rt = GetRoadTypeTram(ti->tile);
3043  const RoadTypeInfo* road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
3044  const RoadTypeInfo* tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
3045 
3046  if (IsDriveThroughStopTile(ti->tile)) {
3047  Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
3048  uint sprite_offset = axis == AXIS_X ? 1 : 0;
3049 
3050  DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset);
3051  } else {
3052  /* Non-drivethrough road stops are only valid for roads. */
3053  assert(road_rt != INVALID_ROADTYPE && tram_rt == INVALID_ROADTYPE);
3054 
3055  if (road_rti->UsesOverlay()) {
3056  DiagDirection dir = GetRoadStopDir(ti->tile);
3057  SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ROADSTOP);
3058  DrawGroundSprite(ground + dir, PAL_NONE);
3059  }
3060  }
3061 
3062  /* Draw road, tram catenary */
3063  DrawRoadCatenary(ti);
3064  }
3065 
3066  if (IsRailWaypoint(ti->tile)) {
3067  /* Don't offset the waypoint graphics; they're always the same. */
3068  total_offset = 0;
3069  }
3070 
3071  DrawRailTileSeq(ti, t, TO_BUILDINGS, total_offset, relocation, palette);
3072 }
3073 
3074 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
3075 {
3076  int32 total_offset = 0;
3077  PaletteID pal = COMPANY_SPRITE_COLOUR(_local_company);
3078  const DrawTileSprites *t = GetStationTileLayout(st, image);
3079  const RailtypeInfo *rti = nullptr;
3080 
3081  if (railtype != INVALID_RAILTYPE) {
3082  rti = GetRailTypeInfo(railtype);
3083  total_offset = rti->GetRailtypeSpriteOffset();
3084  }
3085 
3086  SpriteID img = t->ground.sprite;
3087  RailTrackOffset overlay_offset;
3088  if (rti != nullptr && rti->UsesOverlay() && SplitGroundSpriteForOverlay(nullptr, &img, &overlay_offset)) {
3090  DrawSprite(img, PAL_NONE, x, y);
3091  DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
3092  } else {
3093  DrawSprite(img + total_offset, HasBit(img, PALETTE_MODIFIER_COLOUR) ? pal : PAL_NONE, x, y);
3094  }
3095 
3096  if (roadtype != INVALID_ROADTYPE) {
3097  const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype);
3098  if (image >= 4) {
3099  /* Drive-through stop */
3100  uint sprite_offset = 5 - image;
3101 
3102  /* Road underlay takes precedence over tram */
3103  if (rti->UsesOverlay()) {
3105  DrawSprite(ground + sprite_offset, PAL_NONE, x, y);
3106 
3108  if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y);
3109  } else if (RoadTypeIsTram(roadtype)) {
3110  DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
3111  }
3112  } else {
3113  /* Drive-in stop */
3114  if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) {
3116  DrawSprite(ground + image, PAL_NONE, x, y);
3117  }
3118  }
3119  }
3120 
3121  /* Default waypoint has no railtype specific sprites */
3122  DrawRailTileSeqInGUI(x, y, t, st == STATION_WAYPOINT ? 0 : total_offset, 0, pal);
3123 }
3124 
3125 static int GetSlopePixelZ_Station(TileIndex tile, uint x, uint y)
3126 {
3127  return GetTileMaxPixelZ(tile);
3128 }
3129 
3130 static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
3131 {
3132  return FlatteningFoundation(tileh);
3133 }
3134 
3135 static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
3136 {
3137  td->owner[0] = GetTileOwner(tile);
3138 
3139  if (IsRoadStopTile(tile)) {
3140  RoadType road_rt = GetRoadTypeRoad(tile);
3141  RoadType tram_rt = GetRoadTypeTram(tile);
3142  Owner road_owner = INVALID_OWNER;
3143  Owner tram_owner = INVALID_OWNER;
3144  if (road_rt != INVALID_ROADTYPE) {
3145  const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
3146  td->roadtype = rti->strings.name;
3147  td->road_speed = rti->max_speed / 2;
3148  road_owner = GetRoadOwner(tile, RTT_ROAD);
3149  }
3150 
3151  if (tram_rt != INVALID_ROADTYPE) {
3152  const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
3153  td->tramtype = rti->strings.name;
3154  td->tram_speed = rti->max_speed / 2;
3155  tram_owner = GetRoadOwner(tile, RTT_TRAM);
3156  }
3157 
3158  if (IsDriveThroughStopTile(tile)) {
3159  /* Is there a mix of owners? */
3160  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
3161  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
3162  uint i = 1;
3163  if (road_owner != INVALID_OWNER) {
3164  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
3165  td->owner[i] = road_owner;
3166  i++;
3167  }
3168  if (tram_owner != INVALID_OWNER) {
3169  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
3170  td->owner[i] = tram_owner;
3171  }
3172  }
3173  }
3174  }
3175 
3177 
3178  if (HasStationTileRail(tile)) {
3179  const StationSpec *spec = GetStationSpec(tile);
3180 
3181  if (spec != nullptr) {
3183  td->station_name = spec->name;
3184 
3185  if (spec->grf_prop.grffile != nullptr) {
3186  const GRFConfig *gc = GetGRFConfig(spec->grf_prop.grffile->grfid);
3187  td->grf = gc->GetName();
3188  }
3189  }
3190 
3191  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
3192  td->rail_speed = rti->max_speed;
3193  td->railtype = rti->strings.name;
3194  }
3195 
3196  if (IsAirport(tile)) {
3197  const AirportSpec *as = Station::GetByTile(tile)->airport.GetSpec();
3199  td->airport_name = as->name;
3200 
3201  const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
3202  td->airport_tile_name = ats->name;
3203 
3204  if (as->grf_prop.grffile != nullptr) {
3205  const GRFConfig *gc = GetGRFConfig(as->grf_prop.grffile->grfid);
3206  td->grf = gc->GetName();
3207  } else if (ats->grf_prop.grffile != nullptr) {
3208  const GRFConfig *gc = GetGRFConfig(ats->grf_prop.grffile->grfid);
3209  td->grf = gc->GetName();
3210  }
3211  }
3212 
3213  StringID str;
3214  switch (GetStationType(tile)) {
3215  default: NOT_REACHED();
3216  case STATION_RAIL: str = STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION; break;
3217  case STATION_AIRPORT:
3218  str = (IsHangar(tile) ? STR_LAI_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_LAI_STATION_DESCRIPTION_AIRPORT);
3219  break;
3220  case STATION_TRUCK: str = STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
3221  case STATION_BUS: str = STR_LAI_STATION_DESCRIPTION_BUS_STATION; break;
3222  case STATION_OILRIG: {
3223  const Industry *i = Station::GetByTile(tile)->industry;
3224  const IndustrySpec *is = GetIndustrySpec(i->type);
3225  td->owner[0] = i->owner;
3226  str = is->name;
3227  if (is->grf_prop.grffile != nullptr) td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
3228  break;
3229  }
3230  case STATION_DOCK: str = STR_LAI_STATION_DESCRIPTION_SHIP_DOCK; break;
3231  case STATION_BUOY: str = STR_LAI_STATION_DESCRIPTION_BUOY; break;
3232  case STATION_WAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT; break;
3233  }
3234  td->str = str;
3235 }
3236 
3237 
3238 static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
3239 {
3240  TrackBits trackbits = TRACK_BIT_NONE;
3241 
3242  switch (mode) {
3243  case TRANSPORT_RAIL:
3244  if (HasStationRail(tile) && !IsStationTileBlocked(tile)) {
3245  trackbits = TrackToTrackBits(GetRailStationTrack(tile));
3246  }
3247  break;
3248 
3249  case TRANSPORT_WATER:
3250  /* buoy is coded as a station, it is always on open water */
3251  if (IsBuoy(tile)) {
3252  trackbits = TRACK_BIT_ALL;
3253  /* remove tracks that connect NE map edge */
3254  if (TileX(tile) == 0) trackbits &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
3255  /* remove tracks that connect NW map edge */
3256  if (TileY(tile) == 0) trackbits &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
3257  }
3258  break;
3259 
3260  case TRANSPORT_ROAD:
3261  if (IsRoadStop(tile)) {
3262  RoadTramType rtt = (RoadTramType)sub_mode;
3263  if (!HasTileRoadType(tile, rtt)) break;
3264 
3265  DiagDirection dir = GetRoadStopDir(tile);
3266  Axis axis = DiagDirToAxis(dir);
3267 
3268  if (side != INVALID_DIAGDIR) {
3269  if (axis != DiagDirToAxis(side) || (IsStandardRoadStopTile(tile) && dir != side)) break;
3270  }
3271 
3272  trackbits = AxisToTrackBits(axis);
3273  }
3274  break;
3275 
3276  default:
3277  break;
3278  }
3279 
3281 }
3282 
3283 
3284 static void TileLoop_Station(TileIndex tile)
3285 {
3286  /* FIXME -- GetTileTrackStatus_Station -> animated stationtiles
3287  * hardcoded.....not good */
3288  switch (GetStationType(tile)) {
3289  case STATION_AIRPORT:
3290  AirportTileAnimationTrigger(Station::GetByTile(tile), tile, AAT_TILELOOP);
3291  break;
3292 
3293  case STATION_DOCK:
3294  if (!IsTileFlat(tile)) break; // only handle water part
3295  FALLTHROUGH;
3296 
3297  case STATION_OILRIG: //(station part)
3298  case STATION_BUOY:
3299  TileLoop_Water(tile);
3300  break;
3301 
3302  default: break;
3303  }
3304 }
3305 
3306 
3307 static void AnimateTile_Station(TileIndex tile)
3308 {
3309  if (HasStationRail(tile)) {
3310  AnimateStationTile(tile);
3311  return;
3312  }
3313 
3314  if (IsAirport(tile)) {
3315  AnimateAirportTile(tile);
3316  }
3317 }
3318 
3319 
3320 static bool ClickTile_Station(TileIndex tile)
3321 {
3322  const BaseStation *bst = BaseStation::GetByTile(tile);
3323 
3324  if (bst->facilities & FACIL_WAYPOINT) {
3326  } else if (IsHangar(tile)) {
3327  const Station *st = Station::From(bst);
3329  } else {
3331  }
3332  return true;
3333 }
3334 
3335 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
3336 {
3337  if (v->type == VEH_TRAIN) {
3338  StationID station_id = GetStationIndex(tile);
3339  if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
3340  if (!IsRailStation(tile) || !v->IsFrontEngine()) return VETSB_CONTINUE;
3341 
3342  int station_ahead;
3343  int station_length;
3344  int stop = GetTrainStopLocation(station_id, tile, Train::From(v), &station_ahead, &station_length);
3345 
3346  /* Stop whenever that amount of station ahead + the distance from the
3347  * begin of the platform to the stop location is longer than the length
3348  * of the platform. Station ahead 'includes' the current tile where the
3349  * vehicle is on, so we need to subtract that. */
3350  if (stop + station_ahead - (int)TILE_SIZE >= station_length) return VETSB_CONTINUE;
3351 
3353 
3354  x &= 0xF;
3355  y &= 0xF;
3356 
3357  if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
3358  if (y == TILE_SIZE / 2) {
3359  if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
3360  stop &= TILE_SIZE - 1;
3361 
3362  if (x == stop) {
3363  return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); // enter station
3364  } else if (x < stop) {
3366  uint16 spd = max(0, (stop - x) * 20 - 15);
3367  if (spd < v->cur_speed) v->cur_speed = spd;
3368  }
3369  }
3370  } else if (v->type == VEH_ROAD) {
3371  RoadVehicle *rv = RoadVehicle::From(v);
3372  if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) {
3373  if (IsRoadStop(tile) && rv->IsFrontEngine()) {
3374  /* Attempt to allocate a parking bay in a road stop */
3376  }
3377  }
3378  }
3379 
3380  return VETSB_CONTINUE;
3381 }
3382 
3388 {
3389  /* Collect cargoes accepted since the last big tick. */
3390  CargoTypes cargoes = 0;
3391  for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
3392  if (HasBit(st->goods[cid].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cid);
3393  }
3394 
3395  /* Anything to do? */
3396  if (cargoes == 0) return;
3397 
3398  /* Loop over all houses in the catchment. */
3400  for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
3401  if (IsTileType(tile, MP_HOUSE)) {
3402  WatchedCargoCallback(tile, cargoes);
3403  }
3404  }
3405 }
3406 
3414 {
3415  if (!st->IsInUse()) {
3416  if (++st->delete_ctr >= 8) delete st;
3417  return false;
3418  }
3419 
3420  if (Station::IsExpected(st)) {
3422 
3423  for (CargoID i = 0; i < NUM_CARGO; i++) {
3424  ClrBit(Station::From(st)->goods[i].status, GoodsEntry::GES_ACCEPTED_BIGTICK);
3425  }
3426  }
3427 
3428 
3429  if ((st->facilities & FACIL_WAYPOINT) == 0) UpdateStationAcceptance(Station::From(st), true);
3430 
3431  return true;
3432 }
3433 
3434 static inline void byte_inc_sat(byte *p)
3435 {
3436  byte b = *p + 1;
3437  if (b != 0) *p = b;
3438 }
3439 
3446 static void TruncateCargo(const CargoSpec *cs, GoodsEntry *ge, uint amount = UINT_MAX)
3447 {
3448  /* If truncating also punish the source stations' ratings to
3449  * decrease the flow of incoming cargo. */
3450 
3451  StationCargoAmountMap waiting_per_source;
3452  ge->cargo.Truncate(amount, &waiting_per_source);
3453  for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
3454  Station *source_station = Station::GetIfValid(i->first);
3455  if (source_station == nullptr) continue;
3456 
3457  GoodsEntry &source_ge = source_station->goods[cs->Index()];
3458  source_ge.max_waiting_cargo = max(source_ge.max_waiting_cargo, i->second);
3459  }
3460 }
3461 
3462 static void UpdateStationRating(Station *st)
3463 {
3464  bool waiting_changed = false;
3465 
3466  byte_inc_sat(&st->time_since_load);
3467  byte_inc_sat(&st->time_since_unload);
3468 
3469  const CargoSpec *cs;
3470  FOR_ALL_CARGOSPECS(cs) {
3471  GoodsEntry *ge = &st->goods[cs->Index()];
3472  /* Slowly increase the rating back to his original level in the case we
3473  * didn't deliver cargo yet to this station. This happens when a bribe
3474  * failed while you didn't moved that cargo yet to a station. */
3475  if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) {
3476  ge->rating++;
3477  }
3478 
3479  /* Only change the rating if we are moving this cargo */
3480  if (ge->HasRating()) {
3481  byte_inc_sat(&ge->time_since_pickup);
3482  if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) {
3484  ge->last_speed = 0;
3485  TruncateCargo(cs, ge);
3486  waiting_changed = true;
3487  continue;
3488  }
3489 
3490  bool skip = false;
3491  int rating = 0;
3492  uint waiting = ge->cargo.AvailableCount();
3493 
3494  /* num_dests is at least 1 if there is any cargo as
3495  * INVALID_STATION is also a destination.
3496  */
3497  uint num_dests = (uint)ge->cargo.Packets()->MapSize();
3498 
3499  /* Average amount of cargo per next hop, but prefer solitary stations
3500  * with only one or two next hops. They are allowed to have more
3501  * cargo waiting per next hop.
3502  * With manual cargo distribution waiting_avg = waiting / 2 as then
3503  * INVALID_STATION is the only destination.
3504  */
3505  uint waiting_avg = waiting / (num_dests + 1);
3506 
3508  /* Perform custom station rating. If it succeeds the speed, days in transit and
3509  * waiting cargo ratings must not be executed. */
3510 
3511  /* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
3512  uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
3513 
3514  uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
3515  /* Convert to the 'old' vehicle types */
3516  uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
3517  uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
3518  if (callback != CALLBACK_FAILED) {
3519  skip = true;
3520  rating = GB(callback, 0, 14);
3521 
3522  /* Simulate a 15 bit signed value */
3523  if (HasBit(callback, 14)) rating -= 0x4000;
3524  }
3525  }
3526 
3527  if (!skip) {
3528  int b = ge->last_speed - 85;
3529  if (b >= 0) rating += b >> 2;
3530 
3531  byte waittime = ge->time_since_pickup;
3532  if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2;
3533  if (waittime <= 21) rating += 25;
3534  if (waittime <= 12) rating += 25;
3535  if (waittime <= 6) rating += 45;
3536  if (waittime <= 3) rating += 35;
3537 
3538  rating -= 90;
3539  if (ge->max_waiting_cargo <= 1500) rating += 55;
3540  if (ge->max_waiting_cargo <= 1000) rating += 35;
3541  if (ge->max_waiting_cargo <= 600) rating += 10;
3542  if (ge->max_waiting_cargo <= 300) rating += 20;
3543  if (ge->max_waiting_cargo <= 100) rating += 10;
3544  }
3545 
3546  if (Company::IsValidID(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
3547 
3548  byte age = ge->last_age;
3549  if (age < 3) rating += 10;
3550  if (age < 2) rating += 10;
3551  if (age < 1) rating += 13;
3552 
3553  {
3554  int or_ = ge->rating; // old rating
3555 
3556  /* only modify rating in steps of -2, -1, 0, 1 or 2 */
3557  ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
3558 
3559  /* if rating is <= 64 and more than 100 items waiting on average per destination,
3560  * remove some random amount of goods from the station */
3561  if (rating <= 64 && waiting_avg >= 100) {
3562  int dec = Random() & 0x1F;
3563  if (waiting_avg < 200) dec &= 7;
3564  waiting -= (dec + 1) * num_dests;
3565  waiting_changed = true;
3566  }
3567 
3568  /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
3569  if (rating <= 127 && waiting != 0) {
3570  uint32 r = Random();
3571  if (rating <= (int)GB(r, 0, 7)) {
3572  /* Need to have int, otherwise it will just overflow etc. */
3573  waiting = max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
3574  waiting_changed = true;
3575  }
3576  }
3577 
3578  /* At some point we really must cap the cargo. Previously this
3579  * was a strict 4095, but now we'll have a less strict, but
3580  * increasingly aggressive truncation of the amount of cargo. */
3581  static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
3582  static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
3583  static const uint MAX_WAITING_CARGO = 1 << 15;
3584 
3585  if (waiting > WAITING_CARGO_THRESHOLD) {
3586  uint difference = waiting - WAITING_CARGO_THRESHOLD;
3587  waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
3588 
3589  waiting = min(waiting, MAX_WAITING_CARGO);
3590  waiting_changed = true;
3591  }
3592 
3593  /* We can't truncate cargo that's already reserved for loading.
3594  * Thus StoredCount() here. */
3595  if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
3596  /* Feed back the exact own waiting cargo at this station for the
3597  * next rating calculation. */
3598  ge->max_waiting_cargo = 0;
3599 
3600  TruncateCargo(cs, ge, ge->cargo.AvailableCount() - waiting);
3601  } else {
3602  /* If the average number per next hop is low, be more forgiving. */
3603  ge->max_waiting_cargo = waiting_avg;
3604  }
3605  }
3606  }
3607  }
3608 
3609  StationID index = st->index;
3610  if (waiting_changed) {
3611  SetWindowDirty(WC_STATION_VIEW, index); // update whole window
3612  } else {
3613  SetWindowWidgetDirty(WC_STATION_VIEW, index, WID_SV_ACCEPT_RATING_LIST); // update only ratings list
3614  }
3615 }
3616 
3625 void RerouteCargo(Station *st, CargoID c, StationID avoid, StationID avoid2)
3626 {
3627  GoodsEntry &ge = st->goods[c];
3628 
3629  /* Reroute cargo in station. */
3630  ge.cargo.Reroute(UINT_MAX, &ge.cargo, avoid, avoid2, &ge);
3631 
3632  /* Reroute cargo staged to be transferred. */
3633  for (std::list<Vehicle *>::iterator it(st->loading_vehicles.begin()); it != st->loading_vehicles.end(); ++it) {
3634  for (Vehicle *v = *it; v != nullptr; v = v->Next()) {
3635  if (v->cargo_type != c) continue;
3636  v->cargo.Reroute(UINT_MAX, &v->cargo, avoid, avoid2, &ge);
3637  }
3638  }
3639 }
3640 
3650 {
3651  for (CargoID c = 0; c < NUM_CARGO; ++c) {
3652  const bool auto_distributed = (_settings_game.linkgraph.GetDistributionType(c) != DT_MANUAL);
3653  GoodsEntry &ge = from->goods[c];
3655  if (lg == nullptr) continue;
3656  Node node = (*lg)[ge.node];
3657  for (EdgeIterator it(node.Begin()); it != node.End();) {
3658  Edge edge = it->second;
3659  Station *to = Station::Get((*lg)[it->first].Station());
3660  assert(to->goods[c].node == it->first);
3661  ++it; // Do that before removing the edge. Anything else may crash.
3662  assert(_date >= edge.LastUpdate());
3663  uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3);
3664  if ((uint)(_date - edge.LastUpdate()) > timeout) {
3665  bool updated = false;
3666 
3667  if (auto_distributed) {
3668  /* Have all vehicles refresh their next hops before deciding to
3669  * remove the node. */
3670  std::vector<Vehicle *> vehicles;
3671  for (OrderList *l : OrderList::Iterate()) {
3672  bool found_from = false;
3673  bool found_to = false;
3674  for (Order *order = l->GetFirstOrder(); order != nullptr; order = order->next) {
3675  if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_IMPLICIT)) continue;
3676  if (order->GetDestination() == from->index) {
3677  found_from = true;
3678  if (found_to) break;
3679  } else if (order->GetDestination() == to->index) {
3680  found_to = true;
3681  if (found_from) break;
3682  }
3683  }
3684  if (!found_to || !found_from) continue;
3685  vehicles.push_back(l->GetFirstSharedVehicle());
3686  }
3687 
3688  auto iter = vehicles.begin();
3689  while (iter != vehicles.end()) {
3690  Vehicle *v = *iter;
3691 
3692  LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted.
3693  if (edge.LastUpdate() == _date) {
3694  updated = true;
3695  break;
3696  }
3697 
3698  Vehicle *next_shared = v->NextShared();
3699  if (next_shared) {
3700  *iter = next_shared;
3701  ++iter;
3702  } else {
3703  iter = vehicles.erase(iter);
3704  }
3705 
3706  if (iter == vehicles.end()) iter = vehicles.begin();
3707  }
3708  }
3709 
3710  if (!updated) {
3711  /* If it's still considered dead remove it. */
3712  node.RemoveEdge(to->goods[c].node);
3713  ge.flows.DeleteFlows(to->index);
3714  RerouteCargo(from, c, to->index, from->index);
3715  }
3716  } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) {
3717  edge.Restrict();
3718  ge.flows.RestrictFlows(to->index);
3719  RerouteCargo(from, c, to->index, from->index);
3720  } else if (edge.LastRestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastRestrictedUpdate()) > timeout) {
3721  edge.Release();
3722  }
3723  }
3724  assert(_date >= lg->LastCompression());
3725  if ((uint)(_date - lg->LastCompression()) > LinkGraph::COMPRESSION_INTERVAL) {
3726  lg->Compress();
3727  }
3728  }
3729 }
3730 
3740 void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, EdgeUpdateMode mode)
3741 {
3742  GoodsEntry &ge1 = st->goods[cargo];
3743  Station *st2 = Station::Get(next_station_id);
3744  GoodsEntry &ge2 = st2->goods[cargo];
3745  LinkGraph *lg = nullptr;
3746  if (ge1.link_graph == INVALID_LINK_GRAPH) {
3747  if (ge2.link_graph == INVALID_LINK_GRAPH) {
3749  lg = new LinkGraph(cargo);
3751  ge2.link_graph = lg->index;
3752  ge2.node = lg->AddNode(st2);
3753  } else {
3754  DEBUG(misc, 0, "Can't allocate link graph");
3755  }
3756  } else {
3757  lg = LinkGraph::Get(ge2.link_graph);
3758  }
3759  if (lg) {
3760  ge1.link_graph = lg->index;
3761  ge1.node = lg->AddNode(st);
3762  }
3763  } else if (ge2.link_graph == INVALID_LINK_GRAPH) {
3764  lg = LinkGraph::Get(ge1.link_graph);
3765  ge2.link_graph = lg->index;
3766  ge2.node = lg->AddNode(st2);
3767  } else {
3768  lg = LinkGraph::Get(ge1.link_graph);
3769  if (ge1.link_graph != ge2.link_graph) {
3770  LinkGraph *lg2 = LinkGraph::Get(ge2.link_graph);
3771  if (lg->Size() < lg2->Size()) {
3773  lg2->Merge(lg); // Updates GoodsEntries of lg
3774  lg = lg2;
3775  } else {
3777  lg->Merge(lg2); // Updates GoodsEntries of lg2
3778  }
3779  }
3780  }
3781  if (lg != nullptr) {
3782  (*lg)[ge1.node].UpdateEdge(ge2.node, capacity, usage, mode);
3783  }
3784 }
3785 
3792 void IncreaseStats(Station *st, const Vehicle *front, StationID next_station_id)
3793 {
3794  for (const Vehicle *v = front; v != nullptr; v = v->Next()) {
3795  if (v->refit_cap > 0) {
3796  /* The cargo count can indeed be higher than the refit_cap if
3797  * wagons have been auto-replaced and subsequently auto-
3798  * refitted to a higher capacity. The cargo gets redistributed
3799  * among the wagons in that case.
3800  * As usage is not such an important figure anyway we just
3801  * ignore the additional cargo then.*/
3802  IncreaseStats(st, v->cargo_type, next_station_id, v->refit_cap,
3804  }
3805  }
3806 }
3807 
3808 /* called for every station each tick */
3809 static void StationHandleSmallTick(BaseStation *st)
3810 {
3811  if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
3812 
3813  byte b = st->delete_ctr + 1;
3814  if (b >= STATION_RATING_TICKS) b = 0;
3815  st->delete_ctr = b;
3816 
3817  if (b == 0) UpdateStationRating(Station::From(st));
3818 }
3819 
3820 void OnTick_Station()
3821 {
3822  if (_game_mode == GM_EDITOR) return;
3823 
3824  for (BaseStation *st : BaseStation::Iterate()) {
3825  StationHandleSmallTick(st);
3826 
3827  /* Clean up the link graph about once a week. */
3828  if (Station::IsExpected(st) && (_tick_counter + st->index) % STATION_LINKGRAPH_TICKS == 0) {
3830  };
3831 
3832  /* Run STATION_ACCEPTANCE_TICKS = 250 tick interval trigger for station animation.
3833  * Station index is included so that triggers are not all done
3834  * at the same time. */
3835  if ((_tick_counter + st->index) % STATION_ACCEPTANCE_TICKS == 0) {
3836  /* Stop processing this station if it was deleted */
3837  if (!StationHandleBigTick(st)) continue;
3838  TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
3839  if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
3840  }
3841  }
3842 }
3843 
3846 {
3847  for (Station *st : Station::Iterate()) {
3848  for (CargoID i = 0; i < NUM_CARGO; i++) {
3849  GoodsEntry *ge = &st->goods[i];
3852  }
3853  }
3854 }
3855 
3856 
3857 void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
3858 {
3859  ForAllStationsRadius(tile, radius, [&](Station *st) {
3860  if (st->owner == owner && DistanceManhattan(tile, st->xy) <= radius) {
3861  for (CargoID i = 0; i < NUM_CARGO; i++) {
3862  GoodsEntry *ge = &st->goods[i];
3863 
3864  if (ge->status != 0) {
3865  ge->rating = Clamp(ge->rating + amount, 0, 255);
3866  }
3867  }
3868  }
3869  });
3870 }
3871 
3872 static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
3873 {
3874  /* We can't allocate a CargoPacket? Then don't do anything
3875  * at all; i.e. just discard the incoming cargo. */
3876  if (!CargoPacket::CanAllocateItem()) return 0;
3877 
3878  GoodsEntry &ge = st->goods[type];
3879  amount += ge.amount_fract;
3880  ge.amount_fract = GB(amount, 0, 8);
3881 
3882  amount >>= 8;
3883  /* No new "real" cargo item yet. */
3884  if (amount == 0) return 0;
3885 
3886  StationID next = ge.GetVia(st->index);
3887  ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id), next);
3888  LinkGraph *lg = nullptr;
3889  if (ge.link_graph == INVALID_LINK_GRAPH) {
3891  lg = new LinkGraph(type);
3893  ge.link_graph = lg->index;
3894  ge.node = lg->AddNode(st);
3895  } else {
3896  DEBUG(misc, 0, "Can't allocate link graph");
3897  }
3898  } else {
3899  lg = LinkGraph::Get(ge.link_graph);
3900  }
3901  if (lg != nullptr) (*lg)[ge.node].UpdateSupply(amount);
3902 
3903  if (!ge.HasRating()) {
3906  }
3907 
3909  TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
3910  AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
3911 
3913  st->MarkTilesDirty(true);
3914  return amount;
3915 }
3916 
3917 static bool IsUniqueStationName(const char *name)
3918 {
3919  for (const Station *st : Station::Iterate()) {
3920  if (st->name != nullptr && strcmp(st->name, name) == 0) return false;
3921  }
3922 
3923  return true;
3924 }
3925 
3935 CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
3936 {
3937  Station *st = Station::GetIfValid(p1);
3938  if (st == nullptr) return CMD_ERROR;
3939 
3940  CommandCost ret = CheckOwnership(st->owner);
3941  if (ret.Failed()) return ret;
3942 
3943  bool reset = StrEmpty(text);
3944 
3945  if (!reset) {
3947  if (!IsUniqueStationName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
3948  }
3949 
3950  if (flags & DC_EXEC) {
3951  st->cached_name.clear();
3952  free(st->name);
3953  st->name = reset ? nullptr : stredup(text);
3954 
3955  st->UpdateVirtCoord();
3957  }
3958 
3959  return CommandCost();
3960 }
3961 
3962 static void AddNearbyStationsByCatchment(TileIndex tile, StationList *stations, StationList &nearby)
3963 {
3964  for (Station *st : nearby) {
3965  if (st->TileIsInCatchment(tile)) stations->insert(st);
3966  }
3967 }
3968 
3974 {
3975  if (this->tile != INVALID_TILE) {
3976  if (IsTileType(this->tile, MP_HOUSE)) {
3977  /* Town nearby stations need to be filtered per tile. */
3978  assert(this->w == 1 && this->h == 1);
3979  AddNearbyStationsByCatchment(this->tile, &this->stations, Town::GetByTile(this->tile)->stations_near);
3980  } else {
3981  ForAllStationsAroundTiles(*this, [this](Station *st, TileIndex tile) {
3982  this->stations.insert(st);
3983  return true;
3984  });
3985  }
3986  this->tile = INVALID_TILE;
3987  }
3988  return &this->stations;
3989 }
3990 
3991 
3992 static bool CanMoveGoodsToStation(const Station *st, CargoID type)
3993 {
3994  /* Is the station reserved exclusively for somebody else? */
3995  if (st->owner != OWNER_NONE && st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) return false;
3996 
3997  /* Lowest possible rating, better not to give cargo anymore. */
3998  if (st->goods[type].rating == 0) return false;
3999 
4000  /* Selectively servicing stations, and not this one. */
4001  if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) return false;
4002 
4003  if (IsCargoInClass(type, CC_PASSENGERS)) {
4004  /* Passengers are never served by just a truck stop. */
4005  if (st->facilities == FACIL_TRUCK_STOP) return false;
4006  } else {
4007  /* Non-passengers are never served by just a bus stop. */
4008  if (st->facilities == FACIL_BUS_STOP) return false;
4009  }
4010  return true;
4011 }
4012 
4013 uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
4014 {
4015  /* Return if nothing to do. Also the rounding below fails for 0. */
4016  if (all_stations->empty()) return 0;
4017  if (amount == 0) return 0;
4018 
4019  Station *first_station = nullptr;
4020  typedef std::pair<Station *, uint> StationInfo;
4021  std::vector<StationInfo> used_stations;
4022 
4023  for (Station *st : *all_stations) {
4024  if (!CanMoveGoodsToStation(st, type)) continue;
4025 
4026  /* Avoid allocating a vector if there is only one station to significantly
4027  * improve performance in this common case. */
4028  if (first_station == nullptr) {
4029  first_station = st;
4030  continue;
4031  }
4032  if (used_stations.empty()) {
4033  used_stations.reserve(2);
4034  used_stations.emplace_back(std::make_pair(first_station, 0));
4035  }
4036  used_stations.emplace_back(std::make_pair(st, 0));
4037  }
4038 
4039  /* no stations around at all? */
4040  if (first_station == nullptr) return 0;
4041 
4042  if (used_stations.empty()) {
4043  /* only one station around */
4044  amount *= first_station->goods[type].rating + 1;
4045  return UpdateStationWaiting(first_station, type, amount, source_type, source_id);
4046  }
4047 
4048  uint company_best[OWNER_NONE + 1] = {}; // best rating for each company, including OWNER_NONE
4049  uint company_sum[OWNER_NONE + 1] = {}; // sum of ratings for each company
4050  uint best_rating = 0;
4051  uint best_sum = 0; // sum of best ratings for each company
4052 
4053  for (auto &p : used_stations) {
4054  auto owner = p.first->owner;
4055  auto rating = p.first->goods[type].rating;
4056  if (rating > company_best[owner]) {
4057  best_sum += rating - company_best[owner]; // it's usually faster than iterating companies later
4058  company_best[owner] = rating;
4059  if (rating > best_rating) best_rating = rating;
4060  }
4061  company_sum[owner] += rating;
4062  }
4063 
4064  /* From now we'll calculate with fractional cargo amounts.
4065  * First determine how much cargo we really have. */
4066  amount *= best_rating + 1;
4067 
4068  uint moving = 0;
4069  for (auto &p : used_stations) {
4070  uint owner = p.first->owner;
4071  /* Multiply the amount by (company best / sum of best for each company) to get cargo allocated to a company
4072  * and by (station rating / sum of ratings in a company) to get the result for a single station. */
4073  p.second = amount * company_best[owner] * p.first->goods[type].rating / best_sum / company_sum[owner];
4074  moving += p.second;
4075  }
4076 
4077  /* If there is some cargo left due to rounding issues distribute it among the best rated stations. */
4078  if (amount > moving) {
4079  std::sort(used_stations.begin(), used_stations.end(), [type] (const StationInfo &a, const StationInfo &b) {
4080  return b.first->goods[type].rating < a.first->goods[type].rating;
4081  });
4082 
4083  assert(amount - moving <= used_stations.size());
4084  for (uint i = 0; i < amount - moving; i++) {
4085  used_stations[i].second++;
4086  }
4087  }
4088 
4089  uint moved = 0;
4090  for (auto &p : used_stations) {
4091  moved += UpdateStationWaiting(p.first, type, p.second, source_type, source_id);
4092  }
4093 
4094  return moved;
4095 }
4096 
4097 void UpdateStationDockingTiles(Station *st)
4098 {
4099  st->docking_station.Clear();
4100 
4101  /* For neutral stations, start with the industry area instead of dock area */
4102  const TileArea *area = st->industry != nullptr ? &st->industry->location : &st->ship_station;
4103 
4104  if (area->tile == INVALID_TILE) return;
4105 
4106  int x = TileX(area->tile);
4107  int y = TileY(area->tile);
4108 
4109  /* Expand the area by a tile on each side while
4110  * making sure that we remain inside the map. */
4111  int x2 = min(x + area->w + 1, MapSizeX());
4112  int x1 = max(x - 1, 0);
4113 
4114  int y2 = min(y + area->h + 1, MapSizeY());
4115  int y1 = max(y - 1, 0);
4116 
4117  TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1));
4118  TILE_AREA_LOOP(tile, ta) {
4119  if (IsValidTile(tile) && IsPossibleDockingTile(tile)) CheckForDockingTile(tile);
4120  }
4121 }
4122 
4123 void BuildOilRig(TileIndex tile)
4124 {
4125  if (!Station::CanAllocateItem()) {
4126  DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
4127  return;
4128  }
4129 
4130  Station *st = new Station(tile);
4131  _station_kdtree.Insert(st->index);
4132  st->town = ClosestTownFromTile(tile, UINT_MAX);
4133 
4134  st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
4135 
4136  assert(IsTileType(tile, MP_INDUSTRY));
4137  /* Mark industry as associated both ways */
4138  st->industry = Industry::GetByTile(tile);
4139  st->industry->neutral_station = st;
4140  DeleteAnimatedTile(tile);
4141  MakeOilrig(tile, st->index, GetWaterClass(tile));
4142 
4143  st->owner = OWNER_NONE;
4144  st->airport.type = AT_OILRIG;
4145  st->airport.Add(tile);
4146  st->ship_station.Add(tile);
4148  st->build_date = _date;
4149  UpdateStationDockingTiles(st);
4150 
4151  st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
4152 
4153  st->UpdateVirtCoord();
4154  st->RecomputeCatchment();
4155  UpdateStationAcceptance(st, false);
4156 }
4157 
4158 void DeleteOilRig(TileIndex tile)
4159 {
4160  Station *st = Station::GetByTile(tile);
4161 
4162  MakeWaterKeepingClass(tile, OWNER_NONE);
4163 
4164  /* The oil rig station is not supposed to be shared with anything else */
4165  assert(st->facilities == (FACIL_AIRPORT | FACIL_DOCK) && st->airport.type == AT_OILRIG);
4166  if (st->industry != nullptr && st->industry->neutral_station == st) {
4167  /* Don't leave dangling neutral station pointer */
4168  st->industry->neutral_station = nullptr;
4169  }
4170  delete st;
4171 }
4172 
4173 static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
4174 {
4175  if (IsRoadStopTile(tile)) {
4176  FOR_ALL_ROADTRAMTYPES(rtt) {
4177  /* Update all roadtypes, no matter if they are present */
4178  if (GetRoadOwner(tile, rtt) == old_owner) {
4179  RoadType rt = GetRoadType(tile, rtt);
4180  if (rt != INVALID_ROADTYPE) {
4181  /* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
4182  Company::Get(old_owner)->infrastructure.road[rt] -= 2;
4183  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2;
4184  }
4185  SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
4186  }
4187  }
4188  }
4189 
4190  if (!IsTileOwner(tile, old_owner)) return;
4191 
4192  if (new_owner != INVALID_OWNER) {
4193  /* Update company infrastructure counts. Only do it here
4194  * if the new owner is valid as otherwise the clear
4195  * command will do it for us. No need to dirty windows
4196  * here, we'll redraw the whole screen anyway.*/
4197  Company *old_company = Company::Get(old_owner);
4198  Company *new_company = Company::Get(new_owner);
4199 
4200  /* Update counts for underlying infrastructure. */
4201  switch (GetStationType(tile)) {
4202  case STATION_RAIL:
4203  case STATION_WAYPOINT:
4204  if (!IsStationTileBlocked(tile)) {
4205  old_company->infrastructure.rail[GetRailType(tile)]--;
4206  new_company->infrastructure.rail[GetRailType(tile)]++;
4207  }
4208  break;
4209 
4210  case STATION_BUS:
4211  case STATION_TRUCK:
4212  /* Road stops were already handled above. */
4213  break;
4214 
4215  case STATION_BUOY:
4216  case STATION_DOCK:
4217  if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
4218  old_company->infrastructure.water--;
4219  new_company->infrastructure.water++;
4220  }
4221  break;
4222 
4223  default:
4224  break;
4225  }
4226 
4227  /* Update station tile count. */
4228  if (!IsBuoy(tile) && !IsAirport(tile)) {
4229  old_company->infrastructure.station--;
4230  new_company->infrastructure.station++;
4231  }
4232 
4233  /* for buoys, owner of tile is owner of water, st->owner == OWNER_NONE */
4234  SetTileOwner(tile, new_owner);
4236  } else {
4237  if (IsDriveThroughStopTile(tile)) {
4238  /* Remove the drive-through road stop */
4239  DoCommand(tile, 1 | 1 << 8, (GetStationType(tile) == STATION_TRUCK) ? ROADSTOP_TRUCK : ROADSTOP_BUS, DC_EXEC | DC_BANKRUPT, CMD_REMOVE_ROAD_STOP);
4240  assert(IsTileType(tile, MP_ROAD));
4241  /* Change owner of tile and all roadtypes */
4242  ChangeTileOwner(tile, old_owner, new_owner);
4243  } else {
4245  /* Set tile owner of water under (now removed) buoy and dock to OWNER_NONE.
4246  * Update owner of buoy if it was not removed (was in orders).
4247  * Do not update when owned by OWNER_WATER (sea and rivers). */
4248  if ((IsTileType(tile, MP_WATER) || IsBuoyTile(tile)) && IsTileOwner(tile, old_owner)) SetTileOwner(tile, OWNER_NONE);
4249  }
4250  }
4251 }
4252 
4262 {
4263  /* Yeah... water can always remove stops, right? */
4264  if (_current_company == OWNER_WATER) return true;
4265 
4266  if (GetRoadTypeTram(tile) != INVALID_ROADTYPE) {
4267  Owner tram_owner = GetRoadOwner(tile, RTT_TRAM);
4268  if (tram_owner != OWNER_NONE && CheckOwnership(tram_owner).Failed()) return false;
4269  }
4270  if (GetRoadTypeRoad(tile) != INVALID_ROADTYPE) {
4271  Owner road_owner = GetRoadOwner(tile, RTT_ROAD);
4272  if (road_owner != OWNER_TOWN) {
4273  if (road_owner != OWNER_NONE && CheckOwnership(road_owner).Failed()) return false;
4274  } else {
4275  if (CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, RTT_ROAD), OWNER_TOWN, RTT_ROAD, flags).Failed()) return false;
4276  }
4277  }
4278 
4279  return true;
4280 }
4281 
4289 {
4290  if (flags & DC_AUTO) {
4291  switch (GetStationType(tile)) {
4292  default: break;
4293  case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
4294  case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
4295  case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
4296  case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
4297  case STATION_BUS: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
4298  case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
4299  case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
4300  case STATION_OILRIG:
4301  SetDParam(1, STR_INDUSTRY_NAME_OIL_RIG);
4302  return_cmd_error(STR_ERROR_GENERIC_OBJECT_IN_THE_WAY);
4303  }
4304  }
4305 
4306  switch (GetStationType(tile)) {
4307  case STATION_RAIL: return RemoveRailStation(tile, flags);
4308  case STATION_WAYPOINT: return RemoveRailWaypoint(tile, flags);
4309  case STATION_AIRPORT: return RemoveAirport(tile, flags);
4310  case STATION_TRUCK:
4311  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4312  return_cmd_error(STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
4313  }
4314  return RemoveRoadStop(tile, flags);
4315  case STATION_BUS:
4316  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4317  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
4318  }
4319  return RemoveRoadStop(tile, flags);
4320  case STATION_BUOY: return RemoveBuoy(tile, flags);
4321  case STATION_DOCK: return RemoveDock(tile, flags);
4322  default: break;
4323  }
4324 
4325  return CMD_ERROR;
4326 }
4327 
4328 static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
4329 {
4331  /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
4332  * TTDP does not call it.
4333  */
4334  if (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) {
4335  switch (GetStationType(tile)) {
4336  case STATION_WAYPOINT:
4337  case STATION_RAIL: {
4338  DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
4339  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4340  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4341  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4342  }
4343 
4344  case STATION_AIRPORT:
4345  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4346 
4347  case STATION_TRUCK:
4348  case STATION_BUS: {
4349  DiagDirection direction = GetRoadStopDir(tile);
4350  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4351  if (IsDriveThroughStopTile(tile)) {
4352  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4353  }
4354  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4355  }
4356 
4357  default: break;
4358  }
4359  }
4360  }
4361  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
4362 }
4363 
4369 uint FlowStat::GetShare(StationID st) const
4370 {
4371  uint32 prev = 0;
4372  for (SharesMap::const_iterator it = this->shares.begin(); it != this->shares.end(); ++it) {
4373  if (it->second == st) {
4374  return it->first - prev;
4375  } else {
4376  prev = it->first;
4377  }
4378  }
4379  return 0;
4380 }
4381 
4388 StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const
4389 {
4390  if (this->unrestricted == 0) return INVALID_STATION;
4391  assert(!this->shares.empty());
4392  SharesMap::const_iterator it = this->shares.upper_bound(RandomRange(this->unrestricted));
4393  assert(it != this->shares.end() && it->first <= this->unrestricted);
4394  if (it->second != excluded && it->second != excluded2) return it->second;
4395 
4396  /* We've hit one of the excluded stations.
4397  * Draw another share, from outside its range. */
4398 
4399  uint end = it->first;
4400  uint begin = (it == this->shares.begin() ? 0 : (--it)->first);
4401  uint interval = end - begin;
4402  if (interval >= this->unrestricted) return INVALID_STATION; // Only one station in the map.
4403  uint new_max = this->unrestricted - interval;
4404  uint rand = RandomRange(new_max);
4405  SharesMap::const_iterator it2 = (rand < begin) ? this->shares.upper_bound(rand) :
4406  this->shares.upper_bound(rand + interval);
4407  assert(it2 != this->shares.end() && it2->first <= this->unrestricted);
4408  if (it2->second != excluded && it2->second != excluded2) return it2->second;
4409 
4410  /* We've hit the second excluded station.
4411  * Same as before, only a bit more complicated. */
4412 
4413  uint end2 = it2->first;
4414  uint begin2 = (it2 == this->shares.begin() ? 0 : (--it2)->first);
4415  uint interval2 = end2 - begin2;
4416  if (interval2 >= new_max) return INVALID_STATION; // Only the two excluded stations in the map.
4417  new_max -= interval2;
4418  if (begin > begin2) {
4419  Swap(begin, begin2);
4420  Swap(end, end2);
4421  Swap(interval, interval2);
4422  }
4423  rand = RandomRange(new_max);
4424  SharesMap::const_iterator it3 = this->shares.upper_bound(this->unrestricted);
4425  if (rand < begin) {
4426  it3 = this->shares.upper_bound(rand);
4427  } else if (rand < begin2 - interval) {
4428  it3 = this->shares.upper_bound(rand + interval);
4429  } else {
4430  it3 = this->shares.upper_bound(rand + interval + interval2);
4431  }
4432  assert(it3 != this->shares.end() && it3->first <= this->unrestricted);
4433  return it3->second;
4434 }
4435 
4442 {
4443  assert(!this->shares.empty());
4444  SharesMap new_shares;
4445  uint i = 0;
4446  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4447  new_shares[++i] = it->second;
4448  if (it->first == this->unrestricted) this->unrestricted = i;
4449  }
4450  this->shares.swap(new_shares);
4451  assert(!this->shares.empty() && this->unrestricted <= (--this->shares.end())->first);
4452 }
4453 
4460 void FlowStat::ChangeShare(StationID st, int flow)
4461 {
4462  /* We assert only before changing as afterwards the shares can actually
4463  * be empty. In that case the whole flow stat must be deleted then. */
4464  assert(!this->shares.empty());
4465 
4466  uint removed_shares = 0;
4467  uint added_shares = 0;
4468  uint last_share = 0;
4469  SharesMap new_shares;
4470  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4471  if (it->second == st) {
4472  if (flow < 0) {
4473  uint share = it->first - last_share;
4474  if (flow == INT_MIN || (uint)(-flow) >= share) {
4475  removed_shares += share;
4476  if (it->first <= this->unrestricted) this->unrestricted -= share;
4477  if (flow != INT_MIN) flow += share;
4478  last_share = it->first;
4479  continue; // remove the whole share
4480  }
4481  removed_shares += (uint)(-flow);
4482  } else {
4483  added_shares += (uint)(flow);
4484  }
4485  if (it->first <= this->unrestricted) this->unrestricted += flow;
4486 
4487  /* If we don't continue above the whole flow has been added or
4488  * removed. */
4489  flow = 0;
4490  }
4491  new_shares[it->first + added_shares - removed_shares] = it->second;
4492  last_share = it->first;
4493  }
4494  if (flow > 0) {
4495  new_shares[last_share + (uint)flow] = st;
4496  if (this->unrestricted < last_share) {
4497  this->ReleaseShare(st);
4498  } else {
4499  this->unrestricted += flow;
4500  }
4501  }
4502  this->shares.swap(new_shares);
4503 }
4504 
4510 void FlowStat::RestrictShare(StationID st)
4511 {
4512  assert(!this->shares.empty());
4513  uint flow = 0;
4514  uint last_share = 0;
4515  SharesMap new_shares;
4516  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4517  if (flow == 0) {
4518  if (it->first > this->unrestricted) return; // Not present or already restricted.
4519  if (it->second == st) {
4520  flow = it->first - last_share;
4521  this->unrestricted -= flow;
4522  } else {
4523  new_shares[it->first] = it->second;
4524  }
4525  } else {
4526  new_shares[it->first - flow] = it->second;
4527  }
4528  last_share = it->first;
4529  }
4530  if (flow == 0) return;
4531  new_shares[last_share + flow] = st;
4532  this->shares.swap(new_shares);
4533  assert(!this->shares.empty());
4534 }
4535 
4541 void FlowStat::ReleaseShare(StationID st)
4542 {
4543  assert(!this->shares.empty());
4544  uint flow = 0;
4545  uint next_share = 0;
4546  bool found = false;
4547  for (SharesMap::reverse_iterator it(this->shares.rbegin()); it != this->shares.rend(); ++it) {
4548  if (it->first < this->unrestricted) return; // Note: not <= as the share may hit the limit.
4549  if (found) {
4550  flow = next_share - it->first;
4551  this->unrestricted += flow;
4552  break;
4553  } else {
4554  if (it->first == this->unrestricted) return; // !found -> Limit not hit.
4555  if (it->second == st) found = true;
4556  }
4557  next_share = it->first;
4558  }
4559  if (flow == 0) return;
4560  SharesMap new_shares;
4561  new_shares[flow] = st;
4562  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4563  if (it->second != st) {
4564  new_shares[flow + it->first] = it->second;
4565  } else {
4566  flow = 0;
4567  }
4568  }
4569  this->shares.swap(new_shares);
4570  assert(!this->shares.empty());
4571 }
4572 
4578 void FlowStat::ScaleToMonthly(uint runtime)
4579 {
4580  assert(runtime > 0);
4581  SharesMap new_shares;
4582  uint share = 0;
4583  for (SharesMap::iterator i = this->shares.begin(); i != this->shares.end(); ++i) {
4584  share = max(share + 1, i->first * 30 / runtime);
4585  new_shares[share] = i->second;
4586  if (this->unrestricted == i->first) this->unrestricted = share;
4587  }
4588  this->shares.swap(new_shares);
4589 }
4590 
4597 void FlowStatMap::AddFlow(StationID origin, StationID via, uint flow)
4598 {
4599  FlowStatMap::iterator origin_it = this->find(origin);
4600  if (origin_it == this->end()) {
4601  this->insert(std::make_pair(origin, FlowStat(via, flow)));
4602  } else {
4603  origin_it->second.ChangeShare(via, flow);
4604  assert(!origin_it->second.GetShares()->empty());
4605  }
4606 }
4607 
4616 void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow)
4617 {
4618  FlowStatMap::iterator prev_it = this->find(origin);
4619  if (prev_it == this->end()) {
4620  FlowStat fs(via, flow);
4621  fs.AppendShare(INVALID_STATION, flow);
4622  this->insert(std::make_pair(origin, fs));
4623  } else {
4624  prev_it->second.ChangeShare(via, flow);
4625  prev_it->second.ChangeShare(INVALID_STATION, flow);
4626  assert(!prev_it->second.GetShares()->empty());
4627  }
4628 }
4629 
4635 {
4636  for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
4637  FlowStat &fs = i->second;
4638  uint local = fs.GetShare(INVALID_STATION);
4639  if (local > INT_MAX) { // make sure it fits in an int
4640  fs.ChangeShare(self, -INT_MAX);
4641  fs.ChangeShare(INVALID_STATION, -INT_MAX);
4642  local -= INT_MAX;
4643  }
4644  fs.ChangeShare(self, -(int)local);
4645  fs.ChangeShare(INVALID_STATION, -(int)local);
4646 
4647  /* If the local share is used up there must be a share for some
4648  * remote station. */
4649  assert(!fs.GetShares()->empty());
4650  }
4651 }
4652 
4660 {
4661  StationIDStack ret;
4662  for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
4663  FlowStat &s_flows = f_it->second;
4664  s_flows.ChangeShare(via, INT_MIN);
4665  if (s_flows.GetShares()->empty()) {
4666  ret.Push(f_it->first);
4667  this->erase(f_it++);
4668  } else {
4669  ++f_it;
4670  }
4671  }
4672  return ret;
4673 }
4674 
4679 void FlowStatMap::RestrictFlows(StationID via)
4680 {
4681  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4682  it->second.RestrictShare(via);
4683  }
4684 }
4685 
4690 void FlowStatMap::ReleaseFlows(StationID via)
4691 {
4692  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4693  it->second.ReleaseShare(via);
4694  }
4695 }
4696 
4702 {
4703  uint ret = 0;
4704  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4705  ret += (--(i->second.GetShares()->end()))->first;
4706  }
4707  return ret;
4708 }
4709 
4715 uint FlowStatMap::GetFlowVia(StationID via) const
4716 {
4717  uint ret = 0;
4718  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4719  ret += i->second.GetShare(via);
4720  }
4721  return ret;
4722 }
4723 
4729 uint FlowStatMap::GetFlowFrom(StationID from) const
4730 {
4731  FlowStatMap::const_iterator i = this->find(from);
4732  if (i == this->end()) return 0;
4733  return (--(i->second.GetShares()->end()))->first;
4734 }
4735 
4742 uint FlowStatMap::GetFlowFromVia(StationID from, StationID via) const
4743 {
4744  FlowStatMap::const_iterator i = this->find(from);
4745  if (i == this->end()) return 0;
4746  return i->second.GetShare(via);
4747 }
4748 
4749 extern const TileTypeProcs _tile_type_station_procs = {
4750  DrawTile_Station, // draw_tile_proc
4751  GetSlopePixelZ_Station, // get_slope_z_proc
4752  ClearTile_Station, // clear_tile_proc
4753  nullptr, // add_accepted_cargo_proc
4754  GetTileDesc_Station, // get_tile_desc_proc
4755  GetTileTrackStatus_Station, // get_tile_track_status_proc
4756  ClickTile_Station, // click_tile_proc
4757  AnimateTile_Station, // animate_tile_proc
4758  TileLoop_Station, // tile_loop_proc
4759  ChangeTileOwner_Station, // change_tile_owner_proc
4760  nullptr, // add_produced_cargo_proc
4761  VehicleEnter_Station, // vehicle_enter_tile_proc
4762  GetFoundation_Station, // get_foundation_proc
4763  TerraformTile_Station, // terraform_tile_proc
4764 };
Town * AirportGetNearestTown(const AirportSpec *as, const TileIterator &it, uint &mindist)
Finds the town nearest to given airport.
Functions related to OTTD&#39;s strings.
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
SourceType
Types of cargo source and destination.
Definition: cargo_type.h:146
Owner
Enum for all companies/owners.
Definition: company_type.h:18
List of scheduled road vehs button.
Road vehicle states.
don&#39;t allow building on structures
Definition: command_type.h:347
Iterator to iterate over all tiles belonging to a bitmaptilearea.
Definition: bitmap_type.h:107
static void MakeRailStation(TileIndex t, Owner o, StationID sid, Axis a, byte section, RailType rt)
Make the given tile a rail station tile.
Definition: station_map.h:557
EdgeIterator Begin()
Get an iterator pointing to the start of the edges array.
Definition: linkgraph.h:395
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
Definition: landscape.cpp:600
static bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition: rail.h:332
Functions/types related to NewGRF debugging.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:275
byte type
Type of this airport,.
Definition: station_base.h:309
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
StationFacility facilities
The facilities that this station has.
static void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d, WaterClass wc)
Make the given tile a dock tile.
Definition: station_map.h:653
void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
Add track to signal update buffer.
Definition: signal.cpp:580
struct RailtypeInfo::@36 base_sprites
Struct containing the main sprites.
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:307
static uint MapSizeX()
Get the size of the map along the X.
Definition: map_func.h:72
byte state
Definition: roadveh.h:109
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:80
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge=true)
Checks if the given tile is buildable, flat and has a certain height.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:340
NodeID AddNode(const Station *st)
Add a node to the component and create empty edges associated with it.
Definition: linkgraph.cpp:158
void ShowWaypointWindow(const Waypoint *wp)
Show the window for the given waypoint.
Use callback to select a sprite layout to use.
Increase capacity.
static void SetCustomStationSpecIndex(TileIndex t, byte specindex)
Set the custom station spec for this tile.
Definition: station_map.h:481
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition: industrytype.h:139
bool IsAvailable() const
Check whether this airport is available to build.
static bool FindNearIndustryName(TileIndex tile, void *user_data)
Find a station action 0 property 24 station name, or reduce the free_names if needed.
NewGRF handling of rail types.
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:304
static TropicZone GetTropicZone(TileIndex tile)
Get the tropic zone.
Definition: tile_map.h:238
Select station (when joining stations); Window numbers:
Definition: window_type.h:235
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
No track build.
Definition: track_type.h:102
static void SetAnimationFrame(TileIndex t, byte frame)
Set a new animation frame.
Definition: tile_map.h:262
A standard stop for trucks.
Definition: station_type.h:46
static const uint COMPRESSION_INTERVAL
Minimum number of days between subsequent compressions of a LG.
Definition: linkgraph.h:443
static uint MapSizeY()
Get the size of the map along the Y.
Definition: map_func.h:82
static bool IsCustomStationSpecIndex(TileIndex t)
Is there a custom rail station spec on this tile?
Definition: station_map.h:469
void ClearDockingTilesCheckingNeighbours(TileIndex tile)
Clear docking tile status from tiles around a removed dock, if the tile has no neighbours which would...
Direction direction
facing
Definition: vehicle_base.h:269
Non-existing type of vehicle.
Definition: vehicle_type.h:35
const AirportSpec * GetSpec() const
Get the AirportSpec that from the airport type of this airport.
Definition: station_base.h:320
static void SetTileOwner(TileIndex tile, Owner owner)
Sets the owner of a tile.
Definition: tile_map.h:198
Tile information, used while rendering the tile.
Definition: tile_cmd.h:42
TileArea bus_station
Tile area the bus &#39;station&#39; part covers.
Definition: station_base.h:460
void ForAllStationsAroundTiles(const TileArea &ta, Func func)
Call a function on all stations that have any part of the requested area within their catchment...
Definition: station_base.h:569
CompanyMask statues
which companies have a statue?
Definition: town.h:69
Definition of link refreshing utility.
Waypoint class.
Direction rotation
How this airport is rotated.
Definition: station_base.h:311
Minimal stack that uses a pool to avoid pointers.
void DeallocateSpecFromStation(BaseStation *st, byte specindex)
Deallocate a StationSpec from a Station.
Some typedefs for the main game.
const AirportFTAClass * GetAirport(const byte airport_type)
Get the finite state machine of an airport type.
Definition: airport.cpp:207
void TileLoop_Water(TileIndex tile)
Let a water tile floods its diagonal adjoining tiles called from tunnelbridge_cmd, and by TileLoop_Industry() and TileLoop_Track()
Definition: water_cmd.cpp:1210
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3218
TileArea ship_station
Tile area the ship &#39;station&#39; part covers.
Definition: station_base.h:465
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
byte landscape
the landscape we&#39;re currently in
Reference station. Scroll to station when clicking on the news. Delete news when station is deleted...
Definition: news_type.h:53
void AddAnimatedTile(TileIndex tile)
Add the given tile to the animated tile table (if it does not exist on that table yet)...
byte size_y
size of airport in y direction
Iterator to iterate over all tiles belonging to an airport.
Definition: station_base.h:530
company buildings - depots, stations, HQ, ...
Definition: transparency.h:27
Base class for roadstops.
static bool IsReversingRoadTrackdir(Trackdir dir)
Checks whether the trackdir means that we are reversing.
Definition: track_func.h:681
Tile is desert.
Definition: tile_type.h:71
Track along the x-axis (north-east to south-west)
Definition: track_type.h:21
void Queue(LinkGraph *lg)
Queue a link graph for execution.
Date LastUnrestrictedUpdate() const
Get the date of the last update to the edge&#39;s unrestricted capacity.
Definition: linkgraph.h:103
bool HasVehicleEverTriedLoading() const
Reports whether a vehicle has ever tried to load the cargo at this station.
Definition: station_base.h:267
All possible tracks.
Definition: track_type.h:53
An invalid owner.
Definition: company_type.h:29
uint16 triggers
The triggers that trigger animation.
uint GetNumHangars() const
Get the number of hangars on this airport.
Definition: station_base.h:410
static CommandCost CheckFlatLandAirport(AirportTileTableIterator tile_iter, DoCommandFlag flags)
Checks if an airport can be built at the given location and clear the area.
static bool IsRailStation(TileIndex t)
Is this station tile a rail station?
Definition: station_map.h:92
Part of an industry.
Definition: tile_type.h:49
RoadBits GetAnyRoadBits(TileIndex tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition: road_map.cpp:33
EconomySettings economy
settings to change the economy
static RoadBits GetAllRoadBits(TileIndex tile)
Get all set RoadBits on the given tile.
Definition: road_map.h:140
static RoadStopType GetRoadStopType(TileIndex t)
Get the road stop type of this tile.
Definition: station_map.h:56
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition: vehicle.cpp:537
int32 TileIndexDiff
An offset value between to tiles.
Definition: map_func.h:154
static bool IsWater(TileIndex t)
Is it a plain water tile?
Definition: water_map.h:141
Train vehicle type.
Definition: vehicle_type.h:24
virtual TileIterator * Clone() const =0
Allocate a new iterator that is a copy of this one.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:329
static Station * GetClosestDeletedStation(TileIndex tile)
Find the closest deleted station of the current company.
static RoadStop ** FindRoadStopSpot(bool truck_station, Station *st)
void Unqueue(LinkGraph *lg)
Remove a link graph from the execution queue.
Functions related to dates.
static WaterClass GetWaterClass(TileIndex t)
Get the water class at a tile.
Definition: water_map.h:106
const char * grf
newGRF used for the tile contents
Definition: tile_cmd.h:61
uint GetSpecCount() const
Get the number of allocated specs within the class.
Definition: newgrf_class.h:44
Northwest.
static const AirportTileSpec * GetByTile(TileIndex tile)
Retrieve airport tile spec for the given airport tile.
West.
static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
Remove an airport.
Base for the train class.
The vehicle is in a drive-through road stop.
Definition: roadveh.h:47
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted)
Get the acceptance of cargoes around the tile in 1/8.
static byte GetAnimationFrame(TileIndex t)
Get the current animation frame.
Definition: tile_map.h:250
static bool HasTileRoadType(TileIndex t, RoadTramType rtt)
Check if a tile has a road or a tram road type.
Definition: road_map.h:210
uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
Routes packets with station "avoid" as next hop to a different place.
Left track.
Definition: track_type.h:44
Used for iterations.
Functions related to debugging.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:70
void DrawRoadCatenary(const TileInfo *ti)
Draws the catenary for the given tile.
Definition: road_cmd.cpp:1433
bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset)
Check whether a sprite is a track sprite, which can be replaced by a non-track ground sprite and a ra...
Can planes land on this airport type?
Definition: airport.h:147
uint16 cur_speed
current speed
Definition: vehicle_base.h:291
A tile with road (or tram tracks)
Definition: tile_type.h:43
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
bool distant_join_stations
allow to join non-adjacent stations
Ship vehicle type.
Definition: vehicle_type.h:26
static TrackBits AxisToTrackBits(Axis a)
Maps an Axis to the corresponding TrackBits value.
Definition: track_func.h:96
Depot view; Window numbers:
Definition: window_type.h:344
Slope tileh
Slope of the tile.
Definition: tile_cmd.h:45
Maximal number of cargo types in a game.
Definition: cargo_type.h:64
Full road along the x-axis (south-west + north-east)
Definition: road_type.h:56
Set when cargo was delivered for final delivery during the current STATION_ACCEPTANCE_TICKS interval...
Definition: station_base.h:211
Functions used internally by the roads.
A town owns the tile, or a town is expanding.
Definition: company_type.h:24
Flag for invalid railtype.
Definition: rail_type.h:34
Specification of a cargo type.
Definition: cargotype.h:55
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
Lookup the base sprite to use for a canal.
Station specification.
bool IsInUse() const
Check whether the base station currently is in use; in use means that it is not scheduled for deletio...
IndustryLifeType life_type
This is also known as Industry production flag, in newgrf specs.
Definition: industrytype.h:122
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:235
bool ValParamRailtype(const RailType rail)
Validate functions for rail building.
Definition: rail.cpp:206
void MakeDriveThrough()
Join this road stop to another &#39;base&#39; road stop if possible; fill all necessary data to become an act...
Definition: roadstop.cpp:62
static bool IsRoadStop(TileIndex t)
Is the station at t a road station?
Definition: station_map.h:202
Transport over water.
StringID tramtype
Type of tram on the tile.
Definition: tile_cmd.h:67
X-axis track.
Definition: track_type.h:40
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Definition: tilearea.cpp:123
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
Set when cargo was delivered for final delivery this month.
Definition: station_base.h:205
static const uint INVALID_AIRPORTTILE
id for an invalid airport tile
Definition: airport.h:25
static bool HasTileWaterGround(TileIndex t)
Checks whether the tile has water at the ground.
Definition: water_map.h:344
static DiagDirection GetDockDirection(TileIndex t)
Get the direction of a dock.
Definition: station_map.h:429
Trigger tile when built.
Information to handle station action 0 property 24 correctly.
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:205
A standard stop for buses.
Definition: station_type.h:45
TileArea train_station
Tile area the train &#39;station&#39; part covers.
static bool CMSATree(TileIndex tile)
Check whether the tile is a tree.
Vehicle data structure.
Definition: vehicle_base.h:210
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
static void MakeOilrig(TileIndex t, StationID sid, WaterClass wc)
Make the given tile an oilrig tile.
Definition: station_map.h:665
byte station_spread
amount a station may spread
static int GetSlopeMaxZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height) ...
Definition: slope_func.h:160
StationIDStack DeleteFlows(StationID via)
Delete all flows at a station for specific cargo and destination.
uint8 GetAirportNoiseLevelForDistance(const AirportSpec *as, uint distance)
Get a possible noise reduction factor based on distance from town center.
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
Iterator to iterate over all tiles belonging to an airport spec.
uint GetFlowVia(StationID via) const
Get the sum of flows via a specific station from this FlowStatMap.
Defines the internal data of a functional industry.
Definition: industry.h:40
Tile description for the &#39;land area information&#39; tool.
Definition: tile_cmd.h:51
demolish a tile
Definition: command_type.h:180
DifficultySettings difficulty
settings related to the difficulty
Stores station stats for a single cargo.
Definition: station_base.h:170
Tindex index
Index of this pool item.
Definition: pool_type.hpp:227
Vehicle is flying in the air.
Definition: airport.h:75
flag for invalid roadtype
Definition: road_type.h:27
static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
Remove a dock.
static StationGfx GetAirportGfx(TileIndex t)
Get the station graphics of this airport tile.
Definition: station_map.h:244
Manual distribution. No link graph calculations are run.
Draw custom foundations.
void ReleaseFlows(StationID via)
Release all flows at a station for specific cargo and destination.
static bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition: slope_func.h:36
Declarations for accessing the k-d tree of stations.
static void FreeTrainReservation(Train *v)
Clear platform reservation during station building/removing.
void RecomputeCatchment()
Recompute tiles covered in our catchment area.
Definition: station.cpp:407
Helper functions to extract data from command parameters.
void PassOnFlow(StationID origin, StationID via, uint amount)
Pass on some flow, remembering it as invalid, for later subtraction from locally consumed flow...
const DrawTileSeqStruct * GetLayout(PalSpriteID *ground) const
Returns the result spritelayout after preprocessing.
static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
Find a nearby station that joins this road stop.
Base for aircraft.
void FinalizeLocalConsumption(StationID self)
Subtract invalid flows from locally consumed flow.
Representation of a waypoint.
Definition: waypoint_base.h:16
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
void MoveSign(TileIndex new_xy) override
Move the station main coordinate somewhere else.
Required: Drive-in stop surface.
Definition: road.h:68
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition: station.cpp:218
static Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track AXIS_X -> TRACK_X AXIS_Y -> TRACK_Y Uses the fact that the...
Definition: track_func.h:74
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static Track GetRailStationTrack(TileIndex t)
Get the rail track of a rail station tile.
Definition: station_map.h:349
CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
Find a nearby station that joins this station.
Construction costs.
Definition: economy_type.h:149
uint32 station
Count of company owned station tiles.
Definition: company_base.h:34
#define FOR_EACH_SET_BIT(bitpos_var, bitset_value)
Do an operation for each set set bit in a value.
Flag for an invalid DiagDirection.
#define AllocaM(T, num_elements)
alloca() has to be called in the parent function, so define AllocaM() as a macro
Definition: alloc_func.hpp:132
Common return value for all commands.
Definition: command_type.h:23
static bool IsStandardRoadStopTile(TileIndex t)
Is tile t a standard (non-drive through) road stop station?
Definition: station_map.h:223
static bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition: viewport.cpp:757
RoadType
The different roadtypes we support.
Definition: road_type.h:22
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:255
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
uint16 classes
Classes of this cargo type.
Definition: cargotype.h:78
static bool IsDriveThroughStopTile(TileIndex t)
Is tile t a drive through road stop station?
Definition: station_map.h:233
Town * town
The town this station is associated with.
void ForAllStationsRadius(TileIndex center, uint radius, Func func)
Call a function on all stations whose sign is within a radius of a center tile.
bool HasRating() const
Does this cargo have a rating at this station?
Definition: station_base.h:273
byte vehstatus
Status.
Definition: vehicle_base.h:315
uint8 status
Status; 0: no looping, 1: looping, 0xFF: no animation.
static DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition: track_func.h:447
uint GetFlowFrom(StationID from) const
Get the sum of flows from a specific station from this FlowStatMap.
struct RailtypeInfo::@39 strings
Strings associated with the rail type.
uint tiles
Number of tile layouts.
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:351
uint16 w
The width of the area.
Definition: tilearea_type.h:18
static RoadVehicle * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Mail.
Definition: cargotype.h:40
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition: tile_map.cpp:100
void Clear()
Clears the &#39;tile area&#39;, i.e.
Definition: tilearea_type.h:38
Determine whether a newstation should be made available to build.
The vehicle entered a station.
Definition: tile_cmd.h:35
static Slope GetFoundationPixelSlope(TileIndex tile, int *z)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation, the function returns the same as GetTilePixelSlope.
Definition: landscape.h:66
std::set< Station *, StationCompare > StationList
List of stations.
Definition: station_type.h:94
uint16 noise_reached
level of noise that all the airports are generating
Definition: town.h:67
a flat tile
Definition: slope_type.h:49
uint16 rail_speed
Speed limit of rail (bridges and track)
Definition: tile_cmd.h:64
byte nof_depots
the number of hangar tiles in this airport
int z
Height.
Definition: tile_cmd.h:47
static StationType GetStationType(TileIndex t)
Get the station type of this tile.
Definition: station_map.h:44
StationSettings station
settings related to station management
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:479
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:13
static CommandCost RemoveRailWaypoint(TileIndex tile, DoCommandFlag flags)
Remove a rail waypoint.
static uint32 RandomRange(uint32 limit)
Pick a random number between 0 and limit - 1, inclusive.
Definition: random_func.hpp:81
RoadStopType
Types of RoadStops.
Definition: station_type.h:44
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition: landscape.cpp:470
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:62
Owner owner[4]
Name of the owner(s)
Definition: tile_cmd.h:53
StringID name
Displayed name of the industry.
Definition: industrytype.h:126
void UpdateStationAcceptance(Station *st, bool show_msg)
Update the acceptance for a station.
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
static uint GetCustomStationSpecIndex(TileIndex t)
Get the custom station spec for this tile.
Definition: station_map.h:493
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition: sprite.h:60
const AirportTileTable *const * table
list of the tiles composing the airport
CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Build a bus or truck stop.
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
Definition: yapf_rail.cpp:642
CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector< T *> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
Remove a number of tiles from any rail station within the area.
static Station * From(BaseStation *st)
Converts a BaseStation to SpecializedStation with type checking.
char * GetStringWithArgs(char *buffr, StringID string, StringParameters *args, const char *last, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition: strings.cpp:216
static uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Definition: math_func.hpp:182
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:124
CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
Clear a single tile of a station.
static CargoArray GetAcceptanceAroundStation(const Station *st, CargoTypes *always_accepted)
Get the acceptance of cargoes around the station in.
uint32 free_names
Current bitset of free names (we can remove names).
byte delete_ctr
Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is ...
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:49
Right track.
Definition: track_type.h:45
bool selectgoods
only send the goods to station if a train has been there
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:121
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:352
Functions related to (drawing on) viewports.
Pseudo random number generator.
void TriggerWatchedCargoCallbacks(Station *st)
Run the watched cargo callback for all houses in the catchment area.
A connected component of a link graph.
Definition: linkgraph.h:38
static bool HasStationRail(TileIndex t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint...
Definition: station_map.h:135
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
Get the stop location of (the center) of the front vehicle of a train at a platform of a station...
Definition: train_cmd.cpp:256
CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis axis)
Check whether we can expand the rail part of the given station.
Invalid cargo type.
Definition: cargo_type.h:68
Set when cargo was delivered for final delivery last month.
Definition: station_base.h:199
Slope GetTileSlope(TileIndex tile, int *h)
Return the slope of a given tile inside the map.
Definition: tile_map.cpp:59
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:161
SpriteID single_y
single piece of rail in Y direction, without ground
Definition: rail.h:135
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:767
void ScaleToMonthly(uint runtime)
Scale all shares from link graph&#39;s runtime to monthly values.
Triggered in the periodic tile loop.
static bool IsBridgeAbove(TileIndex t)
checks if a bridge is set above the ground of this tile
Definition: bridge_map.h:45
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:3337
static bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile)
Check if a tile is a valid continuation to a railstation tile.
Definition: station_map.h:378
TileArea docking_station
Tile area the docking tiles cover.
Definition: station_base.h:466
Buses, trucks and trams belong to this class.
Definition: roadveh.h:107
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
Definition: order_cmd.cpp:2241
static bool IsTileOwner(TileIndex tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:214
void UpdateAirportsNoise()
Recalculate the noise generated by the airports of each town.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:250
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold...
Definition: town_cmd.cpp:3544
static void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32 total_offset, uint32 newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition: sprite.h:99
Maximal number of airports in total.
Definition: airport.h:41
Tile animation!
StringID name
Name of this rail type.
Definition: road.h:100
byte noise_level
noise that this airport generates
static const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:224
uint GetShare(StationID st) const
Get flow for a station.
static bool CanRemoveRoadWithStop(TileIndex tile, DoCommandFlag flags)
Check if a drive-through road stop tile can be cleared.
void RestrictFlows(StationID via)
Restrict all flows at a station for specific cargo and destination.
Functions related to low-level strings.
byte amount_fract
Fractional part of the amount in the cargo list.
Definition: station_base.h:254
SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Definition: strings_type.h:18
uint x
X position of the tile in unit coordinates.
Definition: tile_cmd.h:43
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10)
Resolve sprites for drawing a station tile.
uint Size() const
Get the current size of the component.
Definition: linkgraph.h:497
None of the directions are disallowed.
Definition: road_map.h:286
byte rating
Station rating for this cargo.
Definition: station_base.h:235
The tile has no ownership.
Definition: company_type.h:25
static TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:341
bool ValParamRoadType(RoadType roadtype)
Validate functions for rail building.
Definition: road.cpp:142
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition: tilearea_type.h:96
EdgeIterator End()
Get an iterator pointing beyond the end of the edges array.
Definition: linkgraph.h:401
Foundation
Enumeration for Foundations.
Definition: slope_type.h:93
TileIndex xy
town center tile
Definition: town.h:54
static void SetStationTileRandomBits(TileIndex t, byte random_bits)
Set the random bits for a station tile.
Definition: station_map.h:505
static bool IsBuoy(TileIndex t)
Is tile t a buoy tile?
Definition: station_map.h:306
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
Triggered when the airport is built (for all tiles at the same time).
Southeast.
static void MakeAirport(TileIndex t, Owner o, StationID sid, byte section, WaterClass wc)
Make the given tile an airport tile.
Definition: station_map.h:626
TileIndex tile
Tile index.
Definition: tile_cmd.h:46
AirportClassID cls_id
the class to which this airport type belongs
Updatable node class.
Definition: linkgraph.h:372
static uint ApplyPixelFoundationToSlope(Foundation f, Slope *s)
Applies a foundation to a slope.
Definition: landscape.h:129
static const int GFX_DOCK_BASE_WATER_PART
The offset for the water parts.
Definition: station_map.h:35
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:445
The y axis.
uint32 PrepareLayout(uint32 orig_offset, uint32 newgrf_ground_offset, uint32 newgrf_offset, uint constr_stage, bool separate_ground) const
Prepares a sprite layout before resolving action-1-2-3 chains.
RoadStop * truck_stops
All the truck stops.
Definition: station_base.h:461
This indicates whether a cargo has a rating at the station.
Definition: station_base.h:187
StationID GetVia(StationID source) const
Get the best next hop for a cargo packet from station source.
Definition: station_base.h:283
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition: tilearea.cpp:43
static int CountMapSquareAround(TileIndex tile, CMSAMatcher cmp)
Counts the numbers of tiles matching a specific type in the area around.
bool serve_neutral_industries
company stations can serve industries with attached neutral stations
StringID owner_type[4]
Type of each owner.
Definition: tile_cmd.h:54
static RoadBits GetRoadBits(TileIndex t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition: road_map.h:127
void ClearDriveThrough()
Prepare for removal of this stop; update other neighbouring stops if needed.
Definition: roadstop.cpp:130
The tile is leveled up to a flat slope.
Definition: slope_type.h:95
LinkGraphID link_graph
Link graph this station belongs to.
Definition: station_base.h:257
Information about GRF, used in the game and (part of it) in savegames.
static bool HasStationReservation(TileIndex t)
Get the reservation state of the rail station.
Definition: station_map.h:393
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:58
bool road_stop_on_competitor_road
allow building of drive-through road stops on roads owned by competitors
static void SetStationGfx(TileIndex t, StationGfx gfx)
Set the station graphics of this tile.
Definition: station_map.h:80
bool IsTileForestIndustry(TileIndex tile)
Check whether the tile is a forest.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
static LinkGraphSchedule instance
Static instance of LinkGraphSchedule.
CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove bus or truck stops.
WaterClass
classes of water (for WATER_TILE_CLEAR water tile type).
Definition: water_map.h:47
Images for overlaying track.
Definition: rail.h:48
static bool StationHandleBigTick(BaseStation *st)
This function is called for each station once every 250 ticks.
static bool IsTruckStop(TileIndex t)
Is the station at t a truck stop?
Definition: station_map.h:180
East.
const Direction * rotation
the rotation of each tiletable
static void TruncateCargo(const CargoSpec *cs, GoodsEntry *ge, uint amount=UINT_MAX)
Truncate the cargo by a specific amount.
uint DistanceMax(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles.
Definition: map.cpp:189
StationID GetVia() const
Get a station a package can be routed to.
Definition: station_base.h:134
static DiagDirection GetRoadStopDir(TileIndex t)
Gets the direction the road stop entrance points towards.
Definition: station_map.h:257
Entry point for OpenTTD to YAPF&#39;s cache.
List of accepted cargoes / rating of cargoes.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:61
TileArea truck_station
Tile area the truck &#39;station&#39; part covers.
Definition: station_base.h:462
const StationList * GetStations()
Run a tile loop to find stations around a tile, on demand.
Functions related to NewGRF houses.
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:178
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:344
uint16 tram_speed
Speed limit of tram (bridges and track)
Definition: tile_cmd.h:68
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
byte status
Status of this cargo, see GoodsEntryStatus.
Definition: station_base.h:226
Piece of rail in X direction.
Definition: rail.h:68
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:150
&#39;Close airport&#39; button.
Container for cargo from the same location and time.
Definition: cargopacket.h:42
static bool HasStationTileRail(TileIndex t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint...
Definition: station_map.h:146
void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, EdgeUpdateMode mode)
Increase capacity for a link stat given by station cargo and next hop.
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
byte layout
Airport layout number.
Definition: station_base.h:310
void DeleteAnimatedTile(TileIndex tile)
Removes the given tile from the animated tile table.
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec)
Allocate a StationSpec to a Station.
#define TILE_AREA_LOOP(var, ta)
A loop which iterates over the tiles of a TileArea.
Definition of base types and functions in a cross-platform compatible way.
static const Date INVALID_DATE
Representation of an invalid date.
Definition: date_type.h:110
Shift the VehicleEnterTileStatus this many bits to the right to get the station ID when VETS_ENTERED_...
Definition: tile_cmd.h:30
static TrackBits GetRailReservationTrackBits(TileIndex t)
Returns the reserved track bits of the tile.
Definition: rail_map.h:194
uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
Routes packets with station "avoid" as next hop to a different place.
A number of safeguards to prevent using unsafe methods.
static void Run(Vehicle *v, bool allow_merge=true, bool is_full_loading=false)
Refresh all links the given vehicle will visit.
Definition: refresh.cpp:26
Trigger station every 250 ticks.
void WatchedCargoCallback(TileIndex tile, CargoTypes trigger_cargoes)
Run watched cargo accepted callback for a house.
bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data)
Function performing a search around a center tile and going outward, thus in circle.
Definition: map.cpp:258
IndustryType GetIndustryType(TileIndex tile)
Retrieve the type for this industry.
static const uint64 AIRPORT_CLOSED_block
Dummy block for indicating a closed airport.
Definition: airport.h:128
Direction
Defines the 8 directions on the map.
IndustryType type
type of industry.
Definition: industry.h:57
static PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition: sprite.h:168
static bool IsDockTile(TileIndex t)
Is tile t a dock tile?
Definition: station_map.h:295
Base of waypoints.
static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
Remove a bus station/truck stop.
The vehicle cannot enter the tile.
Definition: tile_cmd.h:37
Water tile.
Definition: tile_type.h:47
static Axis GetRailStationAxis(TileIndex t)
Get the rail direction of a rail station.
Definition: station_map.h:337
uint y
Y position of the tile in unit coordinates.
Definition: tile_cmd.h:44
struct RoadStop * next
Next stop of the given type at this station.
Definition: roadstop_base.h:69
bool HasStationInUse(StationID station, bool include_company, CompanyID company)
Tests whether the company&#39;s vehicles have this station in orders.
Liquids (Oil, Water, Rubber)
Definition: cargotype.h:45
RoadBits
Enumeration for the road parts on a tile.
Definition: road_type.h:50
uint8 callback_mask
Bitmask of cargo callbacks that have to be called.
Definition: cargotype.h:68
void ProcessRegisters(uint8 resolved_var10, uint32 resolved_sprite, bool separate_ground) const
Evaluates the register modifiers and integrates them into the preprocessed sprite layout...
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
Definition: depot_gui.cpp:1096
void GetTileArea(TileArea *ta, StationType type) const override
Get the tile area for a given station type.
static const uint MIN_TIMEOUT_DISTANCE
Minimum effective distance for timeout calculation.
Definition: linkgraph.h:440
TileArea location
Location of the industry.
Definition: industry.h:41
byte num_table
number of elements in the table
NodeID node
ID of node in link graph referring to this goods entry.
Definition: station_base.h:258
void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec)
Create the station layout for the given number of tracks and platform length.
static bool CMSAMine(TileIndex tile)
Check whether the tile is a mine.
bool IsHangar(TileIndex t)
Check whether the given tile is a hangar.
Definition: station_cmd.cpp:77
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:303
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:16
Train * GetTrainForReservation(TileIndex tile, Track track)
Find the train which has reserved a specific path.
Definition: pbs.cpp:331
No road-part is build.
Definition: road_type.h:51
static bool IsBuoyTile(TileIndex t)
Is tile t a buoy tile?
Definition: station_map.h:316
NewGRF handling of road types.
Represents the covered area of e.g.
Definition: tilearea_type.h:16
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:136
GUI Functions related to companies.
CargoID produced_cargo[INDUSTRY_NUM_OUTPUTS]
16 production cargo slots
Definition: industry.h:44
PBS support routines.
static bool IsAirport(TileIndex t)
Is this station tile an airport?
Definition: station_map.h:157
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:38
CommandCost RemoveRailStation(T *st, DoCommandFlag flags, Money removal_cost)
Remove a rail station/waypoint.
StringID name
Tile Subname string, land information on this tile will give you "AirportName (TileSubname)".
Functions related to order backups.
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:881
bool road_stop_on_town_road
allow building of drive-through road stops on town owned roads
Trigger station on new cargo arrival.
void UpdateVirtCoord() override
Update the virtual coords needed to draw the station sign.
uint16 max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:228
Map accessor functions for bridges.
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:496
Set when a sprite originates from an Action 1.
Definition: sprites.h:1524
TileIndex tile
Current tile index.
Definition: vehicle_base.h:228
uint16 max_speed
Maximum speed for vehicles travelling on this road type.
Definition: road.h:139
Owner owner
owner of the industry. Which SHOULD always be (imho) OWNER_NONE
Definition: industry.h:58
Defines the data structure for constructing industry.
Definition: industrytype.h:106
StationSpecList * speclist
List of station specs of this station.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
static Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition: road.h:249
void Push(const Titem &item)
Pushes a new item onto the stack if there is still space in the underlying pool.
Base class for tile iterators.
Definition: tilearea_type.h:99
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition: road_cmd.cpp:194
bool * indtypes
Array of bools telling whether an industry type has been found.
static const int STATION_RATING_TICKS
cycle duration for updating station rating
Definition: date_type.h:32
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:1938
static const AirportSpec * Get(byte type)
Retrieve airport spec for the given airport.
PersistentStorage * psa
Persistent storage for NewGRF airports.
Definition: station_base.h:313
static const AirportTileSpec * Get(StationGfx gfx)
Retrieve airport tile spec for the given airport tile.
Station view; Window numbers:
Definition: window_type.h:338
CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Build a dock/haven.
static void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, DiagDirection d)
Make the given tile a roadstop tile.
Definition: station_map.h:590
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlag flags, bool town_check)
Is it allowed to remove the given road bits from the given tile?
Definition: road_cmd.cpp:266
Date LastRestrictedUpdate() const
Get the date of the last update to the edge&#39;s restricted capacity.
Definition: linkgraph.h:109
StationRect - used to track station spread out rectangle - cheaper than scanning whole map...
Bit value for coloured news.
Definition: news_type.h:71
SpriteID single_x
single piece of rail in X direction, without ground
Definition: rail.h:134
struct RoadTypeInfo::@42 strings
Strings associated with the rail type.
Called when building a station to customize the tile layout.
virtual TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
Definition: vehicle_base.h:738
Functions related to stations.
static const uint8 ANIM_STATUS_NO_ANIMATION
There is no animation.
void RestrictShare(StationID st)
Restrict a flow by moving it to the end of the map and decreasing the amount of unrestricted flow...
void AddFlow(StationID origin, StationID via, uint amount)
Add some flow from "origin", going via "via".
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:271
uint64 flags
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition: station_base.h:308
CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Rename a station.
static const SharesMap empty_sharesmap
Static instance of FlowStat::SharesMap.
Definition: station_base.h:40
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
byte last_speed
Maximum speed (up to 255) of the last vehicle that tried to load this cargo.
Definition: station_base.h:246
uint8 cached_anim_triggers
NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen...
GRFFileProps grf_prop
properties related to the grf file
Definition: industrytype.h:140
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
Types related to the station widgets.
static Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition: slope_func.h:369
static void DrawRailTileSeq(const struct TileInfo *ti, const DrawTileSprites *dts, TransparencyOption to, int32 total_offset, uint32 newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence on tile with railroad specifics.
Definition: sprite.h:89
StringID railtype
Type of rail on the tile.
Definition: tile_cmd.h:63
static bool MayHaveRoad(TileIndex t)
Test whether a tile can have road/tram types.
Definition: road_map.h:32
StringID airport_tile_name
Name of the airport tile.
Definition: tile_cmd.h:60
static bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:148
Piece of rail in Y direction.
Definition: rail.h:69
uint16 refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:306
static DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition: slope_func.h:239
Functions related to autoslope.
NewGRF supplied spritelayout.
static bool IsPlainRailTile(TileIndex t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition: rail_map.h:60
An updatable edge class.
Definition: linkgraph.h:291
bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16 cbid, uint16 cb_res)
Converts a callback result into a boolean.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition: autoslope.h:44
uint DistanceFromEdge(TileIndex tile)
Param the minimum distance to an edge.
Definition: map.cpp:217
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:592
static TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition: track_func.h:396
bool build_on_slopes
allow building on slopes
Date LastCompression() const
Get date of last compression.
Definition: linkgraph.h:503
bool Failed() const
Did this command fail?
Definition: command_type.h:159
StringID station_name
Type of station within the class.
Definition: tile_cmd.h:57
byte last_age
Age in years (up to 255) of the last vehicle that tried to load this cargo.
Definition: station_base.h:252
const struct SpriteGroup * spritegroup[Tcnt]
pointer to the different sprites of the entity
TileIndex GetHangarTile(uint hangar_num) const
Get the first tile of the given hangar.
Definition: station_base.h:373
static StationGfx GetStationGfx(TileIndex t)
Get the station graphics of this tile.
Definition: station_map.h:68
static void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, Axis a)
Make the given tile a drivethrough roadstop tile.
Definition: station_map.h:610
All ships have this type.
Definition: ship.h:26
Date LastUpdate() const
Get the date of the last update to any part of the edge&#39;s capacity.
Definition: linkgraph.h:115
RoadStop * bus_stops
All the road stops.
Definition: station_base.h:459
uint16 MaxTownNoise() const
Calculate the max town noise.
Definition: town.h:124
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition: viewport.cpp:659
static Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition: track_func.h:255
NewGRF handling of airport tiles.
void ShowStationViewWindow(StationID station)
Opens StationViewWindow for given station.
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:33
static void SetRoadOwner(TileIndex t, RoadTramType rtt, Owner o)
Set the owner of a specific road type.
Definition: road_map.h:250
Station list; Window numbers:
Definition: window_type.h:295
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
static bool HasSignals(TileIndex t)
Checks if a rail tile has signals.
Definition: rail_map.h:72
FlowStatMap flows
Planned flows through this station.
Definition: station_base.h:259
TileIndex TileAddWrap(TileIndex tile, int addx, int addy)
This function checks if we add addx/addy to tile, if we do wrap around the edges. ...
Definition: map.cpp:114
CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
Find a nearby waypoint that joins this waypoint.
uint Truncate(uint max_move=UINT_MAX, StationCargoAmountMap *cargo_per_source=nullptr)
Truncates where each destination loses roughly the same percentage of its cargo.
bool Enter(RoadVehicle *rv)
Enter the road stop.
Definition: roadstop.cpp:233
static void Reset(TileIndex tile=INVALID_TILE, bool from_gui=true)
Reset the OrderBackups from GUI/game logic.
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:85
uint8 FindFirstBit(uint32 x)
Search the first set bit in a 32 bit variable.
void ChangeShare(StationID st, int flow)
Change share for specified station.
Functions related to clear (MP_CLEAR) land.
EdgeUpdateMode
Special modes for updating links.
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:17
byte flags
Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size...
uint16 _tick_counter
Ever incrementing (and sometimes wrapping) tick counter for setting off various events.
Definition: date.cpp:29
StationGfx GetStationGfx() const
Get the StationGfx for the current tile.
SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
Resolve the sprites for custom station foundations.
A pair-construct of a TileIndexDiff.
Definition: map_type.h:57
static TrackBits GetTrackBits(TileIndex tile)
Gets the track bits of the given tile.
Definition: rail_map.h:136
bool(* CMSAMatcher)(TileIndex tile)
Function to check whether the given tile matches some criterion.
void UpdateAllStationVirtCoords()
Update the virtual coords needed to draw the station sign for all stations.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:131
The X axis.
uint32 rail[RAILTYPE_END]
Count of company owned track bits for each rail type.
Definition: company_base.h:32
bool IsValidDockingDirectionForDock(TileIndex t, DiagDirection d)
Check if a dock tile can be docked from the given direction.
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1165
void ReleaseShare(StationID st)
Release ("unrestrict") a flow by moving it to the begin of the map and increasing the amount of unres...
static Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
static TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
Return the offset between to tiles from a TileIndexDiffC struct.
Definition: map_func.h:230
Town * CalcClosestTownFromTile(TileIndex tile, uint threshold=UINT_MAX)
Return the town closest to the given tile within threshold.
Definition: town_cmd.cpp:3526
Handling of NewGRF canals.
byte StationGfx
Copy from station_map.h.
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
Get the cargo types being produced around the tile (in a rectangle).
Transport by train.
execute the given command
Definition: command_type.h:346
Station with an airport.
Definition: station_type.h:55
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
static TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition: track_func.h:85
The tile/execution is done by "water".
Definition: company_type.h:26
uint GetHangarNum(TileIndex tile) const
Get the hangar number of the hangar at a specific tile.
Definition: station_base.h:403
static bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype)
Checks if an engine of the given RoadType got power on a tile with a given RoadType.
Definition: road.h:239
Station with a dock.
Definition: station_type.h:56
CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags)
Checks whether the local authority allows construction of a new station (rail, road, airport, dock) on the given tile.
Definition: town_cmd.cpp:3505
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:28
Tile got trees.
Definition: tile_type.h:45
List of scheduled ships button.
No track.
Definition: track_type.h:39
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:59
GRFConfig * GetGRFConfig(uint32 grfid, uint32 mask)
Retrieve a NewGRF from the current config by its grfid.
static CommandCost BuildStationPart(Station **st, DoCommandFlag flags, bool reuse, TileArea area, StationNaming name_class)
Common part of building various station parts and possibly attaching them to an existing one...
static uint MapSize()
Get the size of the map.
Definition: map_func.h:92
StationType
Station types.
Definition: station_type.h:32
this bit is set when a recolouring process is in action
Definition: sprites.h:1527
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Class for storing amounts of cargo.
Definition: cargo_type.h:81
static Owner GetRoadOwner(TileIndex t, RoadTramType rtt)
Get the owner of a specific road type.
Definition: road_map.h:233
static bool IsNormalRoadTile(TileIndex t)
Return whether a tile is a normal road tile.
Definition: road_map.h:73
static bool CanBuildDepotByTileh(DiagDirection direction, Slope tileh)
Find out if the slope of the tile is suitable to build a depot of given direction.
Definition: depot_func.h:26
Header file for NewGRF stations.
Track along the y-axis (north-west to south-east)
Definition: track_type.h:22
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Open/close an airport to incoming aircraft.
Trackdir GetVehicleTrackdir() const
Get the tracks of the train vehicle.
Definition: train_cmd.cpp:4005
CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
Look for a station owned by the given company around the given tile area.
bool IsStationTileBlocked(TileIndex tile)
Check whether a rail station tile is NOT traversable.
CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, byte plat_len, byte numtracks)
Check the slope of a tile of a new station.
GUISettings gui
settings related to the GUI
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:94
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:378
Only bits 0 and 3 are used to encode the trackdir for road stops.
Definition: roadveh.h:58
static Track RemoveFirstTrack(TrackBits *tracks)
Removes first Track from TrackBits and returns it.
Definition: track_func.h:139
static TileIndex FindDockLandPart(TileIndex t)
Find the part of a dock that is land-based.
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3232
bool station_noise_level
build new airports when the town noise level is still within accepted limits
uint max_waiting_cargo
Max cargo from this station waiting at any station.
Definition: station_base.h:260
StationClassID
bool NeedsPreprocessing() const
Tests whether this spritelayout needs preprocessing by PrepareLayout() and ProcessRegisters(), or whether it can be used directly.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
void StationMonthlyLoop()
Monthly loop for stations.
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition: tile_map.cpp:141
size_t Utf8StringLength(const char *s)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition: string.cpp:310
Upper track.
Definition: track_type.h:42
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:117
uint16 road_speed
Speed limit of road (bridges and track)
Definition: tile_cmd.h:66
Set of callback functions for performing tile operations of a given tile type.
Definition: tile_cmd.h:145
T * Last()
Get the last vehicle in the chain.
Oilrig airport.
Definition: airport.h:38
size_t MapSize() const
Count the number of ranges with equal keys in this MultiMap.
Definition: multimap.hpp:350
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1587
Use different sprite set for ground sprites.
Used for iterations.
uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, int y, bool centred)
Evaluate a tile&#39;s position within a station, and return the result in a bit-stuffed format...
virtual bool TileBelongsToRailStation(TileIndex tile) const =0
Check whether a specific tile belongs to this station.
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:157
Cargo support for NewGRFs.
void RerouteCargo(Station *st, CargoID c, StationID avoid, StationID avoid2)
Reroute cargo of type c at station st or in any vehicles unloading there.
void Invalidate()
Reduce all flows to minimum capacity so that they don&#39;t get in the way of link usage statistics too m...
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:359
static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
Items contains the two cargo names that are to be accepted or rejected.
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:579
bool include(std::vector< T > &vec, const T &item)
Helper function to append an item to a vector if it is not already contained Consider using std::set...
StringID name
name of this airport
Extended foundation block instead of simple.
Trigger station on new cargo arrival.
byte fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations...
Definition: rail.h:198
static Money RailBuildCost(RailType railtype)
Returns the cost of building the specified railtype.
Definition: rail.h:372
void Remove(const T &element)
Remove a single element from the tree, if it exists.
Definition: kdtree.hpp:420
OrderSettings order
settings related to orders
static const IndustryType NUM_INDUSTRYTYPES
total number of industry types, new and old; limited to 240 because we need some special ids like INV...
Definition: industry_type.h:26
static IndustryID GetIndustryIndex(TileIndex t)
Get the industry ID of the given tile.
Definition: industry_map.h:63
AnimationInfo animation
Information about the animation.
Track
These are used to specify a single track.
Definition: track_type.h:19
uint16 SourceID
Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
Definition: cargo_type.h:152
const SharesMap * GetShares() const
Get the actual shares as a const pointer so that they can be iterated over.
Definition: station_base.h:92
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:215
Sprites to use and how to display them for station tiles.
Bit sets of the above specified bits.
Definition: tile_cmd.h:34
byte town_council_tolerance
minimum required town ratings to be allowed to demolish stuff
Definition: settings_type.h:69
Station is a waypoint.
Definition: station_type.h:57
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:113
bool IsWithinMapBounds(byte table, TileIndex index) const
Check if the airport would be within the map bounds at the given tile.
Availability of station in construction window.
byte size_x
size of airport in x direction
void FreeTrainTrackReservation(const Train *v)
Free the reserved path in front of a vehicle.
Definition: train_cmd.cpp:2229
TileIndex xy
Base tile of the station.
TransportType
Available types of transport.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
void AppendShare(StationID st, uint flow, bool restricted=false)
Add some flow to the end of the shares map.
Definition: station_base.h:70
StringID airport_name
Name of the airport.
Definition: tile_cmd.h:59
A type of cargo is (no longer) accepted.
Definition: news_type.h:34
static bool IsOilRig(TileIndex t)
Is tile t part of an oilrig?
Definition: station_map.h:274
Slope
Enumeration for the slope-type.
Definition: slope_type.h:48
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:52
Town view; Window numbers:
Definition: window_type.h:326
A tile of a station.
Definition: tile_type.h:46
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition: elrail.cpp:562
BitmapTileArea catchment_tiles
NOSAVE: Set of individual tiles covered by catchment area.
Definition: station_base.h:470
Town data structure.
Definition: town.h:53
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
Checks if a road stop can be built at the given tile.
bool show_track_reservation
highlight reserved tracks.
void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool b)
Set the reservation for a complete station platform.
Definition: pbs.cpp:57
Main group of ground images.
Definition: rail.h:49
List of scheduled trains button.
static NewGRFClass * Get(Tid cls_id)
Get a particular class.
uint8 exclusive_counter
months till the exclusivity expires
Definition: town.h:75
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:299
Transport by road vehicle.
Flow statistics telling how much flow should be sent along a link.
Definition: station_base.h:36
static const int STATION_LINKGRAPH_TICKS
cycle duration for cleaning dead links
Definition: date_type.h:34
uint GetRailtypeSpriteOffset() const
Offset between the current railtype and normal rail.
Definition: rail.h:292
The vehicle is in a road stop.
Definition: roadveh.h:50
static bool IsRailWaypoint(TileIndex t)
Is this station tile a rail waypoint?
Definition: station_map.h:113
Station * neutral_station
Associated neutral station.
Definition: industry.h:43
void OffsetGroundSprite(int x, int y)
Called when a foundation has been drawn for the current tile.
Definition: viewport.cpp:587
static uint CountBits(T value)
Counts the number of set bits in a variable.
Defines the data structure of each individual tile of an airport.
Functions related to commands.
static bool IsValidID(size_t index)
Tests whether given index is a valid index for station of this type.
CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove a single tile from a rail station.
Coordinates of a point in 2D.
remove a single rail track
Definition: command_type.h:179
A Stop for a Road Vehicle.
Definition: roadstop_base.h:22
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
Called when new facility is built on the station.
Definition: station.cpp:202
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:88
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition: viewport.cpp:575
Owner owner
The owner of this station.
byte GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:644
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:318
static bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition: elrail_func.h:30
Date build_date
Date of construction of tile contents.
Definition: tile_cmd.h:55
static bool IsRoadStopTile(TileIndex t)
Is tile t a road stop station?
Definition: station_map.h:213
uint GetFlowFromVia(StationID from, StationID via) const
Get the flow from a specific station via a specific other station.
header file for electrified rail specific functions
Base for ships.
Triggered every 250 ticks (for all tiles at the same time).
static void DeleteStationIfEmpty(BaseStation *st)
This is called right after a station was deleted.
bool adjacent_stations
allow stations to be built directly adjacent to other stations
Station with bus stops.
Definition: station_type.h:54
ConstructionSettings construction
construction of things in-game
Functions that have tunnels and bridges in common.
static TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition: map_func.h:179
Base of all industries.
static DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t)
Gets the disallowed directions.
Definition: road_map.h:301
const char * GetName() const
Get the name of this grf.
static Pool::IterateWrapper< RoadVehicle > Iterate(size_t from=0)
Returns an iterable ensemble of all valid vehicles of type T.
Functions related to waypoints.
Aircraft vehicle type.
Definition: vehicle_type.h:27
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
Airport airport
Tile area the airport covers.
Definition: station_base.h:464
static bool AutoslopeCheckForEntranceEdge(TileIndex tile, int z_new, Slope tileh_new, DiagDirection entrance)
Autoslope check for tiles with an entrance on an edge.
Definition: autoslope.h:31
StringID name
Name of this rail type.
Definition: rail.h:173
CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Place an Airport.
RailTrackOffset
Offsets for sprites within an overlay/underlay set.
Definition: rail.h:67
CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
Remove a buoy.
const struct GRFFile * grffile
grf file that introduced this entity
static const uint MAX_LENGTH_STATION_NAME_CHARS
The maximum length of a station name in characters including &#39;\0&#39;.
Definition: station_type.h:87
StringID str
Description of the tile.
Definition: tile_cmd.h:52
StringID station_name
Default name for nearby station.
Definition: industrytype.h:131
static bool IsHangarTile(TileIndex t)
Is tile t an hangar tile?
Definition: station_map.h:326
Passengers.
Definition: cargotype.h:39
const Tcont * Packets() const
Returns a pointer to the cargo packet list (so you can iterate over it etc).
Definition: cargopacket.h:246
remove a (rectangle of) tiles from a rail station
Definition: command_type.h:190
void DeleteStaleLinks(Station *from)
Check all next hops of cargo packets in this station for existence of a a valid link they may use to ...
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
static bool HasTileWaterClass(TileIndex t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:95
DiagDirection
Enumeration for diagonal directions.
static TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:327
StringID station_class
Class of station.
Definition: tile_cmd.h:56
void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1=NR_NONE, uint32 ref1=UINT32_MAX, NewsReferenceType reftype2=NR_NONE, uint32 ref2=UINT32_MAX, void *free_data=nullptr)
Add a new newsitem to be shown.
Definition: news_gui.cpp:790
byte callback_mask
Bitmask of station callbacks that have to be called.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
byte disallowed_lengths
Bitmask of platform lengths available for the station.
Base of the town class.
StringID roadtype
Type of road on the tile.
Definition: tile_cmd.h:65
void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset)
Draw road underlay and overlay sprites.
Definition: road_cmd.cpp:1495
Station with truck stops.
Definition: station_type.h:53
Northeast, upper right on your monitor.
Required: Main group of ground images.
Definition: road.h:60
CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Build rail station.
Choose a sprite layout to draw, instead of the standard 0-7 range.
GameCreationSettings game_creation
settings used during the creation of a game (map)
static const uint NEW_AIRPORTTILE_OFFSET
offset of first newgrf airport tile
Definition: airport.h:24
uint AvailableCount() const
Returns sum of cargo still available for loading at the sation.
Definition: cargopacket.h:507
void UpdateAirplanesOnNewStation(const Station *st)
Updates the status of the Aircraft heading or in the station.
A house by a town.
Definition: tile_type.h:44
Full road along the y-axis (north-west + south-east)
Definition: road_type.h:57
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
IndustryType indtype
Industry type to get the name from.
Definition: station_base.h:468
Enum of the default airport tiles.
Check slope of new station tiles.
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition: industry.h:114
NewGRFSpriteLayout * renderdata
Array of tile layouts.
Small news item. (Information window with text and viewport)
Definition: news_type.h:77
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:661
void AfterStationTileSetChange(bool adding, StationType type)
After adding/removing tiles to station, update some station-related stuff.
Station with train station.
Definition: station_type.h:52
byte time_since_pickup
Number of rating-intervals (up to 255) since the last vehicle tried to load this cargo.
Definition: station_base.h:233
static CargoTypes GetAcceptanceMask(const Station *st)
Get a mask of the cargo types that the station accepts.
StringID name
Name of this station.
Defines the data structure for an airport.
Functions related to water (management)
static DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
static bool CMSAWater(TileIndex tile)
Check whether the tile is water.
An iterator for non-const edges.
Definition: linkgraph.h:322
static bool IsTileOnWater(TileIndex t)
Tests if the tile was built on water.
Definition: water_map.h:130
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:20
StationGfx GetTranslatedAirportTileID(StationGfx gfx)
Do airporttile gfx ID translation for NewGRFs.
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:23
CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove a single tile from a waypoint.
byte disallowed_platforms
Bitmask of number of platforms available for the station.
StringID airport_class
Name of the airport class.
Definition: tile_cmd.h:58
Functions related to news.
static void MakeRoadNormal(TileIndex t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram)
Make a normal road tile.
Definition: road_map.h:635
uint GetFlow() const
Get the sum of all flows from this FlowStatMap.
StationClassID cls_id
The class to which this spec belongs.
Base classes/functions for stations.
void RemoveEdge(NodeID to)
Remove an outgoing edge from this node.
Definition: linkgraph.cpp:227
static bool IsDock(TileIndex t)
Is tile t a dock tile?
Definition: station_map.h:285
static Station * Get(size_t index)
Gets station with given index.
Date _date
Current date in days (day counter)
Definition: date.cpp:27
bool TryPathReserve(Train *v, bool mark_as_stuck=false, bool first_tile_okay=false)
Try to reserve a path to a safe position.
Definition: train_cmd.cpp:2667
char * name
Custom name.
uint16 h
The height of the area.
Definition: tilearea_type.h:19
void Insert(const T &element)
Insert a single element in the tree.
Definition: kdtree.hpp:401
std::string cached_name
NOSAVE: Cache of the resolved name of the station, if not using a custom name.
static void SetDockingTile(TileIndex t, bool b)
Set the docking tile state of a tile.
Definition: water_map.h:355
Triggered when new cargo arrives at the station (for all tiles at the same time). ...
Industry * industry
NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st) ...
Definition: station_base.h:483
GRFFileProps grf_prop
properties related the the grf file
static Point RemapCoords2(int x, int y)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap...
Definition: landscape.h:98
CompanyID exclusivity
which company has exclusivity
Definition: town.h:74
StringID string_id
Default name (town area) of station.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
remove a (rectangle of) tiles from a rail waypoint
Definition: command_type.h:195
Y-axis track.
Definition: track_type.h:41
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
Definition: water_cmd.cpp:182
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
void Merge(LinkGraph *other)
Merge a link graph with another one.
Definition: linkgraph.cpp:85
Optional: Images for overlaying track.
Definition: road.h:59
Base class for all station-ish types.
Station data structure.
Definition: station_base.h:450
static const int STATION_ACCEPTANCE_TICKS
cycle duration for updating station acceptance
Definition: date_type.h:33
Axis
Allow incrementing of DiagDirDiff variables.
remove a road stop
Definition: command_type.h:198
static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
Find a nearby station that joins this station.
static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, std::vector< Train *> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
Checks if a rail station can be built at the given area.
struct GRFFileProps grf_prop
Properties related to the grf file.
custom station rating for this cargo type
LinkGraphSettings linkgraph
settings for link graph calculations
Used for industry tiles on land (also for oilrig if newgrf says so).
Definition: water_map.h:51
Road vehicle type.
Definition: vehicle_type.h:25
Set when the station accepts the cargo currently for final deliveries.
Definition: station_base.h:177
static RoadBits AxisToRoadBits(Axis a)
Create the road-part which belongs to the given Axis.
Definition: road_func.h:111
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition: map_func.h:163
Train is slowing down.
Definition: vehicle_base.h:34
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:973
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:115
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:316
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition: roadstop.cpp:266
Date build_date
Date of construction.
Called to calculate part of a station rating.
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:3319
Southwest.
static void RestoreTrainReservation(Train *v)
Restore platform reservation during station building/removing.
static int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition: tile_map.h:304
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199
CargoTypes always_accepted
Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn&#39;t accept c...
Definition: station_base.h:480
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:24
uint32 water
Count of company owned track bits for canals.
Definition: company_base.h:33
StringID name
Name of this class.
Definition: newgrf_class.h:39
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.