OpenTTD
station_cmd.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "aircraft.h"
14 #include "bridge_map.h"
15 #include "cmd_helper.h"
16 #include "viewport_func.h"
17 #include "command_func.h"
18 #include "town.h"
19 #include "news_func.h"
20 #include "train.h"
21 #include "ship.h"
22 #include "roadveh.h"
23 #include "industry.h"
24 #include "newgrf_cargo.h"
25 #include "newgrf_debug.h"
26 #include "newgrf_station.h"
27 #include "newgrf_canal.h" /* For the buoy */
29 #include "road_internal.h" /* For drawing catenary/checking road removal */
30 #include "autoslope.h"
31 #include "water.h"
32 #include "strings_func.h"
33 #include "clear_func.h"
34 #include "date_func.h"
35 #include "vehicle_func.h"
36 #include "string_func.h"
37 #include "animated_tile_func.h"
38 #include "elrail_func.h"
39 #include "station_base.h"
40 #include "roadstop_base.h"
41 #include "newgrf_railtype.h"
42 #include "waypoint_base.h"
43 #include "waypoint_func.h"
44 #include "pbs.h"
45 #include "debug.h"
46 #include "core/random_func.hpp"
47 #include "company_base.h"
48 #include "table/airporttile_ids.h"
49 #include "newgrf_airporttiles.h"
50 #include "order_backup.h"
51 #include "newgrf_house.h"
52 #include "company_gui.h"
54 #include "linkgraph/refresh.h"
55 #include "widgets/station_widget.h"
56 
57 #include "table/strings.h"
58 
59 #include "safeguards.h"
60 
66 /* static */ const FlowStat::SharesMap FlowStat::empty_sharesmap;
67 
75 {
76  assert(IsTileType(t, MP_STATION));
77 
78  /* If the tile isn't an airport there's no chance it's a hangar. */
79  if (!IsAirport(t)) return false;
80 
81  const Station *st = Station::GetByTile(t);
82  const AirportSpec *as = st->airport.GetSpec();
83 
84  for (uint i = 0; i < as->nof_depots; i++) {
85  if (st->airport.GetHangarTile(i) == t) return true;
86  }
87 
88  return false;
89 }
90 
99 template <class T>
100 CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
101 {
102  ta.tile -= TileDiffXY(1, 1);
103  ta.w += 2;
104  ta.h += 2;
105 
106  /* check around to see if there are any stations there owned by the company */
107  TILE_AREA_LOOP(tile_cur, ta) {
108  if (IsTileType(tile_cur, MP_STATION)) {
109  StationID t = GetStationIndex(tile_cur);
110  if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
111  if (closest_station == INVALID_STATION) {
112  closest_station = t;
113  } else if (closest_station != t) {
114  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
115  }
116  }
117  }
118  *st = (closest_station == INVALID_STATION) ? NULL : T::Get(closest_station);
119  return CommandCost();
120 }
121 
127 typedef bool (*CMSAMatcher)(TileIndex tile);
128 
136 {
137  int num = 0;
138 
139  for (int dx = -3; dx <= 3; dx++) {
140  for (int dy = -3; dy <= 3; dy++) {
141  TileIndex t = TileAddWrap(tile, dx, dy);
142  if (t != INVALID_TILE && cmp(t)) num++;
143  }
144  }
145 
146  return num;
147 }
148 
154 static bool CMSAMine(TileIndex tile)
155 {
156  /* No industry */
157  if (!IsTileType(tile, MP_INDUSTRY)) return false;
158 
159  const Industry *ind = Industry::GetByTile(tile);
160 
161  /* No extractive industry */
162  if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_EXTRACTIVE) == 0) return false;
163 
164  for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
165  /* The industry extracts something non-liquid, i.e. no oil or plastic, so it is a mine.
166  * Also the production of passengers and mail is ignored. */
167  if (ind->produced_cargo[i] != CT_INVALID &&
169  return true;
170  }
171  }
172 
173  return false;
174 }
175 
181 static bool CMSAWater(TileIndex tile)
182 {
183  return IsTileType(tile, MP_WATER) && IsWater(tile);
184 }
185 
191 static bool CMSATree(TileIndex tile)
192 {
193  return IsTileType(tile, MP_TREES);
194 }
195 
196 #define M(x) ((x) - STR_SV_STNAME)
197 
198 enum StationNaming {
199  STATIONNAMING_RAIL,
200  STATIONNAMING_ROAD,
201  STATIONNAMING_AIRPORT,
202  STATIONNAMING_OILRIG,
203  STATIONNAMING_DOCK,
204  STATIONNAMING_HELIPORT,
205 };
206 
209  uint32 free_names;
210  bool *indtypes;
211 };
212 
221 static bool FindNearIndustryName(TileIndex tile, void *user_data)
222 {
223  /* All already found industry types */
225  if (!IsTileType(tile, MP_INDUSTRY)) return false;
226 
227  /* If the station name is undefined it means that it doesn't name a station */
228  IndustryType indtype = GetIndustryType(tile);
229  if (GetIndustrySpec(indtype)->station_name == STR_UNDEFINED) return false;
230 
231  /* In all cases if an industry that provides a name is found two of
232  * the standard names will be disabled. */
233  sni->free_names &= ~(1 << M(STR_SV_STNAME_OILFIELD) | 1 << M(STR_SV_STNAME_MINES));
234  return !sni->indtypes[indtype];
235 }
236 
237 static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming name_class)
238 {
239  static const uint32 _gen_station_name_bits[] = {
240  0, // STATIONNAMING_RAIL
241  0, // STATIONNAMING_ROAD
242  1U << M(STR_SV_STNAME_AIRPORT), // STATIONNAMING_AIRPORT
243  1U << M(STR_SV_STNAME_OILFIELD), // STATIONNAMING_OILRIG
244  1U << M(STR_SV_STNAME_DOCKS), // STATIONNAMING_DOCK
245  1U << M(STR_SV_STNAME_HELIPORT), // STATIONNAMING_HELIPORT
246  };
247 
248  const Town *t = st->town;
249  uint32 free_names = UINT32_MAX;
250 
252  memset(indtypes, 0, sizeof(indtypes));
253 
254  const Station *s;
255  FOR_ALL_STATIONS(s) {
256  if (s != st && s->town == t) {
257  if (s->indtype != IT_INVALID) {
258  indtypes[s->indtype] = true;
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  Station *best_station = NULL;
363  Station *st;
364 
365  FOR_ALL_STATIONS(st) {
366  if (!st->IsInUse() && st->owner == _current_company) {
367  uint cur_dist = DistanceManhattan(tile, st->xy);
368 
369  if (cur_dist < threshold) {
370  threshold = cur_dist;
371  best_station = st;
372  }
373  }
374  }
375 
376  return best_station;
377 }
378 
379 
381 {
382  switch (type) {
383  case STATION_RAIL:
384  *ta = this->train_station;
385  return;
386 
387  case STATION_AIRPORT:
388  *ta = this->airport;
389  return;
390 
391  case STATION_TRUCK:
392  *ta = this->truck_station;
393  return;
394 
395  case STATION_BUS:
396  *ta = this->bus_station;
397  return;
398 
399  case STATION_DOCK:
400  case STATION_OILRIG:
401  ta->tile = this->dock_tile;
402  break;
403 
404  default: NOT_REACHED();
405  }
406 
407  ta->w = 1;
408  ta->h = 1;
409 }
410 
415 {
416  Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
417 
418  pt.y -= 32 * ZOOM_LVL_BASE;
419  if ((this->facilities & FACIL_AIRPORT) && this->airport.type == AT_OILRIG) pt.y -= 16 * ZOOM_LVL_BASE;
420 
421  SetDParam(0, this->index);
422  SetDParam(1, this->facilities);
423  this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_STATION);
424 
425  SetWindowDirty(WC_STATION_VIEW, this->index);
426 }
427 
430 {
431  BaseStation *st;
432 
433  FOR_ALL_BASE_STATIONS(st) {
434  st->UpdateVirtCoord();
435  }
436 }
437 
443 static CargoTypes GetAcceptanceMask(const Station *st)
444 {
445  CargoTypes mask = 0;
446 
447  for (CargoID i = 0; i < NUM_CARGO; i++) {
448  if (HasBit(st->goods[i].status, GoodsEntry::GES_ACCEPTANCE)) SetBit(mask, i);
449  }
450  return mask;
451 }
452 
457 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
458 {
459  for (uint i = 0; i < num_items; i++) {
460  SetDParam(i + 1, CargoSpec::Get(cargo[i])->name);
461  }
462 
463  SetDParam(0, st->index);
465 }
466 
474 CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
475 {
476  CargoArray produced;
477 
478  int x = TileX(tile);
479  int y = TileY(tile);
480 
481  /* expand the region by rad tiles on each side
482  * while making sure that we remain inside the board. */
483  int x2 = min(x + w + rad, MapSizeX());
484  int x1 = max(x - rad, 0);
485 
486  int y2 = min(y + h + rad, MapSizeY());
487  int y1 = max(y - rad, 0);
488 
489  assert(x1 < x2);
490  assert(y1 < y2);
491  assert(w > 0);
492  assert(h > 0);
493 
494  TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1));
495 
496  /* Loop over all tiles to get the produced cargo of
497  * everything except industries */
498  TILE_AREA_LOOP(tile, ta) AddProducedCargo(tile, produced);
499 
500  /* Loop over the industries. They produce cargo for
501  * anything that is within 'rad' from their bounding
502  * box. As such if you have e.g. a oil well the tile
503  * area loop might not hit an industry tile while
504  * the industry would produce cargo for the station.
505  */
506  const Industry *i;
507  FOR_ALL_INDUSTRIES(i) {
508  if (!ta.Intersects(i->location)) continue;
509 
510  for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
511  CargoID cargo = i->produced_cargo[j];
512  if (cargo != CT_INVALID) produced[cargo]++;
513  }
514  }
515 
516  return produced;
517 }
518 
527 CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted)
528 {
529  CargoArray acceptance;
530  if (always_accepted != NULL) *always_accepted = 0;
531 
532  int x = TileX(tile);
533  int y = TileY(tile);
534 
535  /* expand the region by rad tiles on each side
536  * while making sure that we remain inside the board. */
537  int x2 = min(x + w + rad, MapSizeX());
538  int y2 = min(y + h + rad, MapSizeY());
539  int x1 = max(x - rad, 0);
540  int y1 = max(y - rad, 0);
541 
542  assert(x1 < x2);
543  assert(y1 < y2);
544  assert(w > 0);
545  assert(h > 0);
546 
547  for (int yc = y1; yc != y2; yc++) {
548  for (int xc = x1; xc != x2; xc++) {
549  TileIndex tile = TileXY(xc, yc);
550  AddAcceptedCargo(tile, acceptance, always_accepted);
551  }
552  }
553 
554  return acceptance;
555 }
556 
562 void UpdateStationAcceptance(Station *st, bool show_msg)
563 {
564  /* old accepted goods types */
565  CargoTypes old_acc = GetAcceptanceMask(st);
566 
567  /* And retrieve the acceptance. */
568  CargoArray acceptance;
569  if (!st->rect.IsEmpty()) {
570  acceptance = GetAcceptanceAroundTiles(
571  TileXY(st->rect.left, st->rect.top),
572  st->rect.right - st->rect.left + 1,
573  st->rect.bottom - st->rect.top + 1,
574  st->GetCatchmentRadius(),
575  &st->always_accepted
576  );
577  }
578 
579  /* Adjust in case our station only accepts fewer kinds of goods */
580  for (CargoID i = 0; i < NUM_CARGO; i++) {
581  uint amt = acceptance[i];
582 
583  /* Make sure the station can accept the goods type. */
584  bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
585  if ((!is_passengers && !(st->facilities & ~FACIL_BUS_STOP)) ||
586  (is_passengers && !(st->facilities & ~FACIL_TRUCK_STOP))) {
587  amt = 0;
588  }
589 
590  GoodsEntry &ge = st->goods[i];
591  SB(ge.status, GoodsEntry::GES_ACCEPTANCE, 1, amt >= 8);
593  (*LinkGraph::Get(ge.link_graph))[ge.node].SetDemand(amt / 8);
594  }
595  }
596 
597  /* Only show a message in case the acceptance was actually changed. */
598  CargoTypes new_acc = GetAcceptanceMask(st);
599  if (old_acc == new_acc) return;
600 
601  /* show a message to report that the acceptance was changed? */
602  if (show_msg && st->owner == _local_company && st->IsInUse()) {
603  /* List of accept and reject strings for different number of
604  * cargo types */
605  static const StringID accept_msg[] = {
606  STR_NEWS_STATION_NOW_ACCEPTS_CARGO,
607  STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO,
608  };
609  static const StringID reject_msg[] = {
610  STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO,
611  STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO,
612  };
613 
614  /* Array of accepted and rejected cargo types */
615  CargoID accepts[2] = { CT_INVALID, CT_INVALID };
616  CargoID rejects[2] = { CT_INVALID, CT_INVALID };
617  uint num_acc = 0;
618  uint num_rej = 0;
619 
620  /* Test each cargo type to see if its acceptance has changed */
621  for (CargoID i = 0; i < NUM_CARGO; i++) {
622  if (HasBit(new_acc, i)) {
623  if (!HasBit(old_acc, i) && num_acc < lengthof(accepts)) {
624  /* New cargo is accepted */
625  accepts[num_acc++] = i;
626  }
627  } else {
628  if (HasBit(old_acc, i) && num_rej < lengthof(rejects)) {
629  /* Old cargo is no longer accepted */
630  rejects[num_rej++] = i;
631  }
632  }
633  }
634 
635  /* Show news message if there are any changes */
636  if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
637  if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
638  }
639 
640  /* redraw the station view since acceptance changed */
642 }
643 
644 static void UpdateStationSignCoord(BaseStation *st)
645 {
646  const StationRect *r = &st->rect;
647 
648  if (r->IsEmpty()) return; // no tiles belong to this station
649 
650  /* clamp sign coord to be inside the station rect */
651  st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
652  st->UpdateVirtCoord();
653 
654  if (!Station::IsExpected(st)) return;
655  Station *full_station = Station::From(st);
656  for (CargoID c = 0; c < NUM_CARGO; ++c) {
657  LinkGraphID lg = full_station->goods[c].link_graph;
658  if (!LinkGraph::IsValidID(lg)) continue;
659  (*LinkGraph::Get(lg))[full_station->goods[c].node].UpdateLocation(st->xy);
660  }
661 }
662 
672 static CommandCost BuildStationPart(Station **st, DoCommandFlag flags, bool reuse, TileArea area, StationNaming name_class)
673 {
674  /* Find a deleted station close to us */
675  if (*st == NULL && reuse) *st = GetClosestDeletedStation(area.tile);
676 
677  if (*st != NULL) {
678  if ((*st)->owner != _current_company) {
680  }
681 
682  CommandCost ret = (*st)->rect.BeforeAddRect(area.tile, area.w, area.h, StationRect::ADD_TEST);
683  if (ret.Failed()) return ret;
684  } else {
685  /* allocate and initialize new station */
686  if (!Station::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
687 
688  if (flags & DC_EXEC) {
689  *st = new Station(area.tile);
690 
691  (*st)->town = ClosestTownFromTile(area.tile, UINT_MAX);
692  (*st)->string_id = GenerateStationName(*st, area.tile, name_class);
693 
695  SetBit((*st)->town->have_ratings, _current_company);
696  }
697  }
698  }
699  return CommandCost();
700 }
701 
709 {
710  if (!st->IsInUse()) {
711  st->delete_ctr = 0;
713  }
714  /* station remains but it probably lost some parts - station sign should stay in the station boundaries */
715  UpdateStationSignCoord(st);
716 }
717 
719 
729 CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge = true)
730 {
731  if (check_bridge && IsBridgeAbove(tile)) {
732  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
733  }
734 
736  if (ret.Failed()) return ret;
737 
738  int z;
739  Slope tileh = GetTileSlope(tile, &z);
740 
741  /* Prohibit building if
742  * 1) The tile is "steep" (i.e. stretches two height levels).
743  * 2) The tile is non-flat and the build_on_slopes switch is disabled.
744  */
745  if ((!allow_steep && IsSteepSlope(tileh)) ||
747  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
748  }
749 
751  int flat_z = z + GetSlopeMaxZ(tileh);
752  if (tileh != SLOPE_FLAT) {
753  /* Forbid building if the tile faces a slope in a invalid direction. */
754  for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
755  if (HasBit(invalid_dirs, dir) && !CanBuildDepotByTileh(dir, tileh)) {
756  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
757  }
758  }
759  cost.AddCost(_price[PR_BUILD_FOUNDATION]);
760  }
761 
762  /* The level of this tile must be equal to allowed_z. */
763  if (allowed_z < 0) {
764  /* First tile. */
765  allowed_z = flat_z;
766  } else if (allowed_z != flat_z) {
767  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
768  }
769 
770  return cost;
771 }
772 
780 {
782  int allowed_z = -1;
783 
784  for (; tile_iter != INVALID_TILE; ++tile_iter) {
785  CommandCost ret = CheckBuildableTile(tile_iter, 0, allowed_z, true);
786  if (ret.Failed()) return ret;
787  cost.AddCost(ret);
788 
789  ret = DoCommand(tile_iter, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
790  if (ret.Failed()) return ret;
791  cost.AddCost(ret);
792  }
793 
794  return cost;
795 }
796 
811 static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, SmallVector<Train *, 4> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
812 {
814  int allowed_z = -1;
815  uint invalid_dirs = 5 << axis;
816 
817  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
818  bool slope_cb = statspec != NULL && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
819 
820  TILE_AREA_LOOP(tile_cur, tile_area) {
821  CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false);
822  if (ret.Failed()) return ret;
823  cost.AddCost(ret);
824 
825  if (slope_cb) {
826  /* Do slope check if requested. */
827  ret = PerformStationTileSlopeCheck(tile_area.tile, tile_cur, statspec, axis, plat_len, numtracks);
828  if (ret.Failed()) return ret;
829  }
830 
831  /* if station is set, then we have special handling to allow building on top of already existing stations.
832  * so station points to INVALID_STATION if we can build on any station.
833  * Or it points to a station if we're only allowed to build on exactly that station. */
834  if (station != NULL && IsTileType(tile_cur, MP_STATION)) {
835  if (!IsRailStation(tile_cur)) {
836  return ClearTile_Station(tile_cur, DC_AUTO); // get error message
837  } else {
838  StationID st = GetStationIndex(tile_cur);
839  if (*station == INVALID_STATION) {
840  *station = st;
841  } else if (*station != st) {
842  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
843  }
844  }
845  } else {
846  /* Rail type is only valid when building a railway station; if station to
847  * build isn't a rail station it's INVALID_RAILTYPE. */
848  if (rt != INVALID_RAILTYPE &&
849  IsPlainRailTile(tile_cur) && !HasSignals(tile_cur) &&
850  HasPowerOnRail(GetRailType(tile_cur), rt)) {
851  /* Allow overbuilding if the tile:
852  * - has rail, but no signals
853  * - it has exactly one track
854  * - the track is in line with the station
855  * - the current rail type has power on the to-be-built type (e.g. convert normal rail to el rail)
856  */
857  TrackBits tracks = GetTrackBits(tile_cur);
858  Track track = RemoveFirstTrack(&tracks);
859  Track expected_track = HasBit(invalid_dirs, DIAGDIR_NE) ? TRACK_X : TRACK_Y;
860 
861  if (tracks == TRACK_BIT_NONE && track == expected_track) {
862  /* Check for trains having a reservation for this tile. */
863  if (HasBit(GetRailReservationTrackBits(tile_cur), track)) {
864  Train *v = GetTrainForReservation(tile_cur, track);
865  if (v != NULL) {
866  *affected_vehicles.Append() = v;
867  }
868  }
869  CommandCost ret = DoCommand(tile_cur, 0, track, flags, CMD_REMOVE_SINGLE_RAIL);
870  if (ret.Failed()) return ret;
871  cost.AddCost(ret);
872  /* With flags & ~DC_EXEC CmdLandscapeClear would fail since the rail still exists */
873  continue;
874  }
875  }
876  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
877  if (ret.Failed()) return ret;
878  cost.AddCost(ret);
879  }
880  }
881 
882  return cost;
883 }
884 
897 static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadTypes rts)
898 {
900  int allowed_z = -1;
901 
902  TILE_AREA_LOOP(cur_tile, tile_area) {
903  CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through);
904  if (ret.Failed()) return ret;
905  cost.AddCost(ret);
906 
907  /* If station is set, then we have special handling to allow building on top of already existing stations.
908  * Station points to INVALID_STATION if we can build on any station.
909  * Or it points to a station if we're only allowed to build on exactly that station. */
910  if (station != NULL && IsTileType(cur_tile, MP_STATION)) {
911  if (!IsRoadStop(cur_tile)) {
912  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
913  } else {
914  if (is_truck_stop != IsTruckStop(cur_tile) ||
915  is_drive_through != IsDriveThroughStopTile(cur_tile)) {
916  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
917  }
918  /* Drive-through station in the wrong direction. */
919  if (is_drive_through && IsDriveThroughStopTile(cur_tile) && DiagDirToAxis(GetRoadStopDir(cur_tile)) != axis){
920  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
921  }
922  StationID st = GetStationIndex(cur_tile);
923  if (*station == INVALID_STATION) {
924  *station = st;
925  } else if (*station != st) {
926  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
927  }
928  }
929  } else {
930  bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
931  /* Road bits in the wrong direction. */
932  RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE;
933  if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) {
934  /* Someone was pedantic and *NEEDED* three fracking different error messages. */
935  switch (CountBits(rb)) {
936  case 1:
937  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
938 
939  case 2:
940  if (rb == ROAD_X || rb == ROAD_Y) return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
941  return_cmd_error(STR_ERROR_DRIVE_THROUGH_CORNER);
942 
943  default: // 3 or 4
944  return_cmd_error(STR_ERROR_DRIVE_THROUGH_JUNCTION);
945  }
946  }
947 
948  RoadTypes cur_rts = IsNormalRoadTile(cur_tile) ? GetRoadTypes(cur_tile) : ROADTYPES_NONE;
949  uint num_roadbits = 0;
950  if (build_over_road) {
951  /* There is a road, check if we can build road+tram stop over it. */
952  if (HasBit(cur_rts, ROADTYPE_ROAD)) {
953  Owner road_owner = GetRoadOwner(cur_tile, ROADTYPE_ROAD);
954  if (road_owner == OWNER_TOWN) {
955  if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
957  CommandCost ret = CheckOwnership(road_owner);
958  if (ret.Failed()) return ret;
959  }
960  num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
961  }
962 
963  if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD);
964 
965  /* There is a tram, check if we can build road+tram stop over it. */
966  if (HasBit(cur_rts, ROADTYPE_TRAM)) {
967  Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM);
968  if (Company::IsValidID(tram_owner) &&
970  /* Disallow breaking end-of-line of someone else
971  * so trams can still reverse on this tile. */
973  CommandCost ret = CheckOwnership(tram_owner);
974  if (ret.Failed()) return ret;
975  }
976  num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_TRAM));
977  }
978 
979  /* Take into account existing roadbits. */
980  rts |= cur_rts;
981  } else {
982  ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
983  if (ret.Failed()) return ret;
984  cost.AddCost(ret);
985  }
986 
987  uint roadbits_to_build = CountBits(rts) * 2 - num_roadbits;
988  cost.AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
989  }
990  }
991 
992  return cost;
993 }
994 
1003 {
1004  TileArea cur_ta = st->train_station;
1005 
1006  /* determine new size of train station region.. */
1007  int x = min(TileX(cur_ta.tile), TileX(new_ta.tile));
1008  int y = min(TileY(cur_ta.tile), TileY(new_ta.tile));
1009  new_ta.w = max(TileX(cur_ta.tile) + cur_ta.w, TileX(new_ta.tile) + new_ta.w) - x;
1010  new_ta.h = max(TileY(cur_ta.tile) + cur_ta.h, TileY(new_ta.tile) + new_ta.h) - y;
1011  new_ta.tile = TileXY(x, y);
1012 
1013  /* make sure the final size is not too big. */
1015  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1016  }
1017 
1018  return CommandCost();
1019 }
1020 
1021 static inline byte *CreateSingle(byte *layout, int n)
1022 {
1023  int i = n;
1024  do *layout++ = 0; while (--i);
1025  layout[((n - 1) >> 1) - n] = 2;
1026  return layout;
1027 }
1028 
1029 static inline byte *CreateMulti(byte *layout, int n, byte b)
1030 {
1031  int i = n;
1032  do *layout++ = b; while (--i);
1033  if (n > 4) {
1034  layout[0 - n] = 0;
1035  layout[n - 1 - n] = 0;
1036  }
1037  return layout;
1038 }
1039 
1047 void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec)
1048 {
1049  if (statspec != NULL && statspec->lengths >= plat_len &&
1050  statspec->platforms[plat_len - 1] >= numtracks &&
1051  statspec->layouts[plat_len - 1][numtracks - 1]) {
1052  /* Custom layout defined, follow it. */
1053  memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1],
1054  plat_len * numtracks);
1055  return;
1056  }
1057 
1058  if (plat_len == 1) {
1059  CreateSingle(layout, numtracks);
1060  } else {
1061  if (numtracks & 1) layout = CreateSingle(layout, plat_len);
1062  numtracks >>= 1;
1063 
1064  while (--numtracks >= 0) {
1065  layout = CreateMulti(layout, plat_len, 4);
1066  layout = CreateMulti(layout, plat_len, 6);
1067  }
1068  }
1069 }
1070 
1082 template <class T, StringID error_message>
1083 CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
1084 {
1085  assert(*st == NULL);
1086  bool check_surrounding = true;
1087 
1089  if (existing_station != INVALID_STATION) {
1090  if (adjacent && existing_station != station_to_join) {
1091  /* You can't build an adjacent station over the top of one that
1092  * already exists. */
1093  return_cmd_error(error_message);
1094  } else {
1095  /* Extend the current station, and don't check whether it will
1096  * be near any other stations. */
1097  *st = T::GetIfValid(existing_station);
1098  check_surrounding = (*st == NULL);
1099  }
1100  } else {
1101  /* There's no station here. Don't check the tiles surrounding this
1102  * one if the company wanted to build an adjacent station. */
1103  if (adjacent) check_surrounding = false;
1104  }
1105  }
1106 
1107  if (check_surrounding) {
1108  /* Make sure there is no more than one other station around us that is owned by us. */
1109  CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
1110  if (ret.Failed()) return ret;
1111  }
1112 
1113  /* Distant join */
1114  if (*st == NULL && station_to_join != INVALID_STATION) *st = T::GetIfValid(station_to_join);
1115 
1116  return CommandCost();
1117 }
1118 
1128 static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1129 {
1130  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
1131 }
1132 
1142 CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
1143 {
1144  return FindJoiningBaseStation<Waypoint, STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST>(existing_waypoint, waypoint_to_join, adjacent, ta, wp);
1145 }
1146 
1152 {
1155  v = v->Last();
1157 }
1158 
1164 {
1166  TryPathReserve(v, true, true);
1167  v = v->Last();
1169 }
1170 
1188 CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1189 {
1190  /* Unpack parameters */
1191  RailType rt = Extract<RailType, 0, 6>(p1);
1192  Axis axis = Extract<Axis, 6, 1>(p1);
1193  byte numtracks = GB(p1, 8, 8);
1194  byte plat_len = GB(p1, 16, 8);
1195  bool adjacent = HasBit(p1, 24);
1196 
1197  StationClassID spec_class = Extract<StationClassID, 0, 8>(p2);
1198  byte spec_index = GB(p2, 8, 8);
1199  StationID station_to_join = GB(p2, 16, 16);
1200 
1201  /* Does the authority allow this? */
1202  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile_org, flags);
1203  if (ret.Failed()) return ret;
1204 
1205  if (!ValParamRailtype(rt)) return CMD_ERROR;
1206 
1207  /* Check if the given station class is valid */
1208  if ((uint)spec_class >= StationClass::GetClassCount() || spec_class == STAT_CLASS_WAYP) return CMD_ERROR;
1209  if (spec_index >= StationClass::Get(spec_class)->GetSpecCount()) return CMD_ERROR;
1210  if (plat_len == 0 || numtracks == 0) return CMD_ERROR;
1211 
1212  int w_org, h_org;
1213  if (axis == AXIS_X) {
1214  w_org = plat_len;
1215  h_org = numtracks;
1216  } else {
1217  h_org = plat_len;
1218  w_org = numtracks;
1219  }
1220 
1221  bool reuse = (station_to_join != NEW_STATION);
1222  if (!reuse) station_to_join = INVALID_STATION;
1223  bool distant_join = (station_to_join != INVALID_STATION);
1224 
1225  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1226 
1228 
1229  /* these values are those that will be stored in train_tile and station_platforms */
1230  TileArea new_location(tile_org, w_org, h_org);
1231 
1232  /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
1233  StationID est = INVALID_STATION;
1234  SmallVector<Train *, 4> affected_vehicles;
1235  /* Clear the land below the station. */
1236  CommandCost cost = CheckFlatLandRailStation(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
1237  if (cost.Failed()) return cost;
1238  /* Add construction expenses. */
1239  cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);
1240  cost.AddCost(numtracks * plat_len * RailBuildCost(rt));
1241 
1242  Station *st = NULL;
1243  ret = FindJoiningStation(est, station_to_join, adjacent, new_location, &st);
1244  if (ret.Failed()) return ret;
1245 
1246  ret = BuildStationPart(&st, flags, reuse, new_location, STATIONNAMING_RAIL);
1247  if (ret.Failed()) return ret;
1248 
1249  if (st != NULL && st->train_station.tile != INVALID_TILE) {
1250  CommandCost ret = CanExpandRailStation(st, new_location, axis);
1251  if (ret.Failed()) return ret;
1252  }
1253 
1254  /* Check if we can allocate a custom stationspec to this station */
1255  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
1256  int specindex = AllocateSpecToStation(statspec, st, (flags & DC_EXEC) != 0);
1257  if (specindex == -1) return_cmd_error(STR_ERROR_TOO_MANY_STATION_SPECS);
1258 
1259  if (statspec != NULL) {
1260  /* Perform NewStation checks */
1261 
1262  /* Check if the station size is permitted */
1263  if (HasBit(statspec->disallowed_platforms, min(numtracks - 1, 7)) || HasBit(statspec->disallowed_lengths, min(plat_len - 1, 7))) {
1264  return CMD_ERROR;
1265  }
1266 
1267  /* Check if the station is buildable */
1268  if (HasBit(statspec->callback_mask, CBM_STATION_AVAIL)) {
1269  uint16 cb_res = GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE);
1270  if (cb_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res)) return CMD_ERROR;
1271  }
1272  }
1273 
1274  if (flags & DC_EXEC) {
1275  TileIndexDiff tile_delta;
1276  byte *layout_ptr;
1277  byte numtracks_orig;
1278  Track track;
1279 
1280  st->train_station = new_location;
1281  st->AddFacility(FACIL_TRAIN, new_location.tile);
1282 
1283  st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
1284 
1285  if (statspec != NULL) {
1286  /* Include this station spec's animation trigger bitmask
1287  * in the station's cached copy. */
1288  st->cached_anim_triggers |= statspec->animation.triggers;
1289  }
1290 
1291  tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1292  track = AxisToTrack(axis);
1293 
1294  layout_ptr = AllocaM(byte, numtracks * plat_len);
1295  GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
1296 
1297  numtracks_orig = numtracks;
1298 
1299  Company *c = Company::Get(st->owner);
1300  TileIndex tile_track = tile_org;
1301  do {
1302  TileIndex tile = tile_track;
1303  int w = plat_len;
1304  do {
1305  byte layout = *layout_ptr++;
1306  if (IsRailStationTile(tile) && HasStationReservation(tile)) {
1307  /* Check for trains having a reservation for this tile. */
1309  if (v != NULL) {
1310  *affected_vehicles.Append() = v;
1312  }
1313  }
1314 
1315  /* Railtype can change when overbuilding. */
1316  if (IsRailStationTile(tile)) {
1317  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]--;
1318  c->infrastructure.station--;
1319  }
1320 
1321  /* Remove animation if overbuilding */
1322  DeleteAnimatedTile(tile);
1323  byte old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0;
1324  MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, rt);
1325  /* Free the spec if we overbuild something */
1326  DeallocateSpecFromStation(st, old_specindex);
1327 
1328  SetCustomStationSpecIndex(tile, specindex);
1329  SetStationTileRandomBits(tile, GB(Random(), 0, 4));
1330  SetAnimationFrame(tile, 0);
1331 
1332  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++;
1333  c->infrastructure.station++;
1334 
1335  if (statspec != NULL) {
1336  /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
1337  uint32 platinfo = GetPlatformInfo(AXIS_X, GetStationGfx(tile), plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
1338 
1339  /* As the station is not yet completely finished, the station does not yet exist. */
1340  uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile);
1341  if (callback != CALLBACK_FAILED) {
1342  if (callback < 8) {
1343  SetStationGfx(tile, (callback & ~1) + axis);
1344  } else {
1346  }
1347  }
1348 
1349  /* Trigger station animation -- after building? */
1350  TriggerStationAnimation(st, tile, SAT_BUILT);
1351  }
1352 
1353  tile += tile_delta;
1354  } while (--w);
1355  AddTrackToSignalBuffer(tile_track, track, _current_company);
1356  YapfNotifyTrackLayoutChange(tile_track, track);
1357  tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
1358  } while (--numtracks);
1359 
1360  for (uint i = 0; i < affected_vehicles.Length(); ++i) {
1361  /* Restore reservations of trains. */
1362  RestoreTrainReservation(affected_vehicles[i]);
1363  }
1364 
1365  /* Check whether we need to expand the reservation of trains already on the station. */
1366  TileArea update_reservation_area;
1367  if (axis == AXIS_X) {
1368  update_reservation_area = TileArea(tile_org, 1, numtracks_orig);
1369  } else {
1370  update_reservation_area = TileArea(tile_org, numtracks_orig, 1);
1371  }
1372 
1373  TILE_AREA_LOOP(tile, update_reservation_area) {
1374  /* Don't even try to make eye candy parts reserved. */
1375  if (IsStationTileBlocked(tile)) continue;
1376 
1377  DiagDirection dir = AxisToDiagDir(axis);
1378  TileIndexDiff tile_offset = TileOffsByDiagDir(dir);
1379  TileIndex platform_begin = tile;
1380  TileIndex platform_end = tile;
1381 
1382  /* We can only account for tiles that are reachable from this tile, so ignore primarily blocked tiles while finding the platform begin and end. */
1383  for (TileIndex next_tile = platform_begin - tile_offset; IsCompatibleTrainStationTile(next_tile, platform_begin); next_tile -= tile_offset) {
1384  platform_begin = next_tile;
1385  }
1386  for (TileIndex next_tile = platform_end + tile_offset; IsCompatibleTrainStationTile(next_tile, platform_end); next_tile += tile_offset) {
1387  platform_end = next_tile;
1388  }
1389 
1390  /* If there is at least on reservation on the platform, we reserve the whole platform. */
1391  bool reservation = false;
1392  for (TileIndex t = platform_begin; !reservation && t <= platform_end; t += tile_offset) {
1393  reservation = HasStationReservation(t);
1394  }
1395 
1396  if (reservation) {
1397  SetRailStationPlatformReservation(platform_begin, dir, true);
1398  }
1399  }
1400 
1401  st->MarkTilesDirty(false);
1402  st->UpdateVirtCoord();
1403  UpdateStationAcceptance(st, false);
1409  }
1410 
1411  return cost;
1412 }
1413 
1414 static void MakeRailStationAreaSmaller(BaseStation *st)
1415 {
1416  TileArea ta = st->train_station;
1417 
1418 restart:
1419 
1420  /* too small? */
1421  if (ta.w != 0 && ta.h != 0) {
1422  /* check the left side, x = constant, y changes */
1423  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(0, i));) {
1424  /* the left side is unused? */
1425  if (++i == ta.h) {
1426  ta.tile += TileDiffXY(1, 0);
1427  ta.w--;
1428  goto restart;
1429  }
1430  }
1431 
1432  /* check the right side, x = constant, y changes */
1433  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(ta.w - 1, i));) {
1434  /* the right side is unused? */
1435  if (++i == ta.h) {
1436  ta.w--;
1437  goto restart;
1438  }
1439  }
1440 
1441  /* check the upper side, y = constant, x changes */
1442  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(i, 0));) {
1443  /* the left side is unused? */
1444  if (++i == ta.w) {
1445  ta.tile += TileDiffXY(0, 1);
1446  ta.h--;
1447  goto restart;
1448  }
1449  }
1450 
1451  /* check the lower side, y = constant, x changes */
1452  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(i, ta.h - 1));) {
1453  /* the left side is unused? */
1454  if (++i == ta.w) {
1455  ta.h--;
1456  goto restart;
1457  }
1458  }
1459  } else {
1460  ta.Clear();
1461  }
1462 
1463  st->train_station = ta;
1464 }
1465 
1476 template <class T>
1477 CommandCost RemoveFromRailBaseStation(TileArea ta, SmallVector<T *, 4> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
1478 {
1479  /* Count of the number of tiles removed */
1480  int quantity = 0;
1481  CommandCost total_cost(EXPENSES_CONSTRUCTION);
1482  /* Accumulator for the errors seen during clearing. If no errors happen,
1483  * and the quantity is 0 there is no station. Otherwise it will be one
1484  * of the other error that got accumulated. */
1486 
1487  /* Do the action for every tile into the area */
1488  TILE_AREA_LOOP(tile, ta) {
1489  /* Make sure the specified tile is a rail station */
1490  if (!HasStationTileRail(tile)) continue;
1491 
1492  /* If there is a vehicle on ground, do not allow to remove (flood) the tile */
1494  error.AddCost(ret);
1495  if (ret.Failed()) continue;
1496 
1497  /* Check ownership of station */
1498  T *st = T::GetByTile(tile);
1499  if (st == NULL) continue;
1500 
1501  if (_current_company != OWNER_WATER) {
1502  CommandCost ret = CheckOwnership(st->owner);
1503  error.AddCost(ret);
1504  if (ret.Failed()) continue;
1505  }
1506 
1507  /* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
1508  quantity++;
1509 
1510  if (keep_rail || IsStationTileBlocked(tile)) {
1511  /* Don't refund the 'steel' of the track when we keep the
1512  * rail, or when the tile didn't have any rail at all. */
1513  total_cost.AddCost(-_price[PR_CLEAR_RAIL]);
1514  }
1515 
1516  if (flags & DC_EXEC) {
1517  /* read variables before the station tile is removed */
1518  uint specindex = GetCustomStationSpecIndex(tile);
1519  Track track = GetRailStationTrack(tile);
1520  Owner owner = GetTileOwner(tile);
1521  RailType rt = GetRailType(tile);
1522  Train *v = NULL;
1523 
1524  if (HasStationReservation(tile)) {
1525  v = GetTrainForReservation(tile, track);
1526  if (v != NULL) FreeTrainReservation(v);
1527  }
1528 
1529  bool build_rail = keep_rail && !IsStationTileBlocked(tile);
1530  if (!build_rail && !IsStationTileBlocked(tile)) Company::Get(owner)->infrastructure.rail[rt]--;
1531 
1532  DoClearSquare(tile);
1533  DeleteNewGRFInspectWindow(GSF_STATIONS, tile);
1534  if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt);
1535  Company::Get(owner)->infrastructure.station--;
1537 
1538  st->rect.AfterRemoveTile(st, tile);
1539  AddTrackToSignalBuffer(tile, track, owner);
1540  YapfNotifyTrackLayoutChange(tile, track);
1541 
1542  DeallocateSpecFromStation(st, specindex);
1543 
1544  affected_stations.Include(st);
1545 
1546  if (v != NULL) RestoreTrainReservation(v);
1547  }
1548  }
1549 
1550  if (quantity == 0) return error.Failed() ? error : CommandCost(STR_ERROR_THERE_IS_NO_STATION);
1551 
1552  for (T **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
1553  T *st = *stp;
1554 
1555  /* now we need to make the "spanned" area of the railway station smaller
1556  * if we deleted something at the edges.
1557  * we also need to adjust train_tile. */
1558  MakeRailStationAreaSmaller(st);
1559  UpdateStationSignCoord(st);
1560 
1561  /* if we deleted the whole station, delete the train facility. */
1562  if (st->train_station.tile == INVALID_TILE) {
1563  st->facilities &= ~FACIL_TRAIN;
1565  st->UpdateVirtCoord();
1567  }
1568  }
1569 
1570  total_cost.AddCost(quantity * removal_cost);
1571  return total_cost;
1572 }
1573 
1585 CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1586 {
1587  TileIndex end = p1 == 0 ? start : p1;
1588  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1589 
1590  TileArea ta(start, end);
1591  SmallVector<Station *, 4> affected_stations;
1592 
1593  CommandCost ret = RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_STATION_RAIL], HasBit(p2, 0));
1594  if (ret.Failed()) return ret;
1595 
1596  /* Do all station specific functions here. */
1597  for (Station **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
1598  Station *st = *stp;
1599 
1601  st->MarkTilesDirty(false);
1603  }
1604 
1605  /* Now apply the rail cost to the number that we deleted */
1606  return ret;
1607 }
1608 
1620 CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1621 {
1622  TileIndex end = p1 == 0 ? start : p1;
1623  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1624 
1625  TileArea ta(start, end);
1626  SmallVector<Waypoint *, 4> affected_stations;
1627 
1628  return RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_WAYPOINT_RAIL], HasBit(p2, 0));
1629 }
1630 
1631 
1640 template <class T>
1642 {
1643  /* Current company owns the station? */
1644  if (_current_company != OWNER_WATER) {
1645  CommandCost ret = CheckOwnership(st->owner);
1646  if (ret.Failed()) return ret;
1647  }
1648 
1649  /* determine width and height of platforms */
1650  TileArea ta = st->train_station;
1651 
1652  assert(ta.w != 0 && ta.h != 0);
1653 
1655  /* clear all areas of the station */
1656  TILE_AREA_LOOP(tile, ta) {
1657  /* only remove tiles that are actually train station tiles */
1658  if (st->TileBelongsToRailStation(tile)) {
1659  SmallVector<T*, 4> affected_stations; // dummy
1660  CommandCost ret = RemoveFromRailBaseStation(TileArea(tile, 1, 1), affected_stations, flags, removal_cost, false);
1661  if (ret.Failed()) return ret;
1662  cost.AddCost(ret);
1663  }
1664  }
1665 
1666  return cost;
1667 }
1668 
1676 {
1677  /* if there is flooding, remove platforms tile by tile */
1678  if (_current_company == OWNER_WATER) {
1679  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_STATION);
1680  }
1681 
1682  Station *st = Station::GetByTile(tile);
1683  CommandCost cost = RemoveRailStation(st, flags, _price[PR_CLEAR_STATION_RAIL]);
1684 
1685  if (flags & DC_EXEC) st->RecomputeIndustriesNear();
1686 
1687  return cost;
1688 }
1689 
1697 {
1698  /* if there is flooding, remove waypoints tile by tile */
1699  if (_current_company == OWNER_WATER) {
1700  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_WAYPOINT);
1701  }
1702 
1703  return RemoveRailStation(Waypoint::GetByTile(tile), flags, _price[PR_CLEAR_WAYPOINT_RAIL]);
1704 }
1705 
1706 
1712 static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
1713 {
1714  RoadStop **primary_stop = (truck_station) ? &st->truck_stops : &st->bus_stops;
1715 
1716  if (*primary_stop == NULL) {
1717  /* we have no roadstop of the type yet, so write a "primary stop" */
1718  return primary_stop;
1719  } else {
1720  /* there are stops already, so append to the end of the list */
1721  RoadStop *stop = *primary_stop;
1722  while (stop->next != NULL) stop = stop->next;
1723  return &stop->next;
1724  }
1725 }
1726 
1728 
1738 static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1739 {
1740  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST>(existing_stop, station_to_join, adjacent, ta, st);
1741 }
1742 
1759 CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1760 {
1761  bool type = HasBit(p2, 0);
1762  bool is_drive_through = HasBit(p2, 1);
1763  RoadTypes rts = Extract<RoadTypes, 2, 2>(p2);
1764  StationID station_to_join = GB(p2, 16, 16);
1765  bool reuse = (station_to_join != NEW_STATION);
1766  if (!reuse) station_to_join = INVALID_STATION;
1767  bool distant_join = (station_to_join != INVALID_STATION);
1768 
1769  uint8 width = (uint8)GB(p1, 0, 8);
1770  uint8 length = (uint8)GB(p1, 8, 8);
1771 
1772  /* Check if the requested road stop is too big */
1773  if (width > _settings_game.station.station_spread || length > _settings_game.station.station_spread) return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1774  /* Check for incorrect width / length. */
1775  if (width == 0 || length == 0) return CMD_ERROR;
1776  /* Check if the first tile and the last tile are valid */
1777  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, length - 1) == INVALID_TILE) return CMD_ERROR;
1778 
1779  TileArea roadstop_area(tile, width, length);
1780 
1781  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1782 
1783  if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
1784 
1785  /* Trams only have drive through stops */
1786  if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR;
1787 
1788  DiagDirection ddir;
1789  Axis axis;
1790  if (is_drive_through) {
1791  /* By definition axis is valid, due to there being 2 axes and reading 1 bit. */
1792  axis = Extract<Axis, 6, 1>(p2);
1793  ddir = AxisToDiagDir(axis);
1794  } else {
1795  /* By definition ddir is valid, due to there being 4 diagonal directions and reading 2 bits. */
1796  ddir = Extract<DiagDirection, 6, 2>(p2);
1797  axis = DiagDirToAxis(ddir);
1798  }
1799 
1800  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
1801  if (ret.Failed()) return ret;
1802 
1803  /* Total road stop cost. */
1804  CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
1805  StationID est = INVALID_STATION;
1806  ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rts);
1807  if (ret.Failed()) return ret;
1808  cost.AddCost(ret);
1809 
1810  Station *st = NULL;
1811  ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 5), roadstop_area, &st);
1812  if (ret.Failed()) return ret;
1813 
1814  /* Check if this number of road stops can be allocated. */
1815  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);
1816 
1817  ret = BuildStationPart(&st, flags, reuse, roadstop_area, STATIONNAMING_ROAD);
1818  if (ret.Failed()) return ret;
1819 
1820  if (flags & DC_EXEC) {
1821  /* Check every tile in the area. */
1822  TILE_AREA_LOOP(cur_tile, roadstop_area) {
1823  RoadTypes cur_rts = GetRoadTypes(cur_tile);
1824  Owner road_owner = HasBit(cur_rts, ROADTYPE_ROAD) ? GetRoadOwner(cur_tile, ROADTYPE_ROAD) : _current_company;
1825  Owner tram_owner = HasBit(cur_rts, ROADTYPE_TRAM) ? GetRoadOwner(cur_tile, ROADTYPE_TRAM) : _current_company;
1826 
1827  if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
1828  RemoveRoadStop(cur_tile, flags);
1829  }
1830 
1831  RoadStop *road_stop = new RoadStop(cur_tile);
1832  /* Insert into linked list of RoadStops. */
1833  RoadStop **currstop = FindRoadStopSpot(type, st);
1834  *currstop = road_stop;
1835 
1836  if (type) {
1837  st->truck_station.Add(cur_tile);
1838  } else {
1839  st->bus_station.Add(cur_tile);
1840  }
1841 
1842  /* Initialize an empty station. */
1843  st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, cur_tile);
1844 
1845  st->rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
1846 
1847  RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
1848  if (is_drive_through) {
1849  /* Update company infrastructure counts. If the current tile is a normal
1850  * road tile, count only the new road bits needed to get a full diagonal road. */
1851  RoadType rt;
1852  FOR_EACH_SET_ROADTYPE(rt, cur_rts | rts) {
1853  Company *c = Company::GetIfValid(rt == ROADTYPE_ROAD ? road_owner : tram_owner);
1854  if (c != NULL) {
1855  c->infrastructure.road[rt] += 2 - (IsNormalRoadTile(cur_tile) && HasBit(cur_rts, rt) ? CountBits(GetRoadBits(cur_tile, rt)) : 0);
1857  }
1858  }
1859 
1860  MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, axis);
1861  road_stop->MakeDriveThrough();
1862  } else {
1863  /* Non-drive-through stop never overbuild and always count as two road bits. */
1864  Company::Get(st->owner)->infrastructure.road[FIND_FIRST_BIT(rts)] += 2;
1865  MakeRoadStop(cur_tile, st->owner, st->index, rs_type, rts, ddir);
1866  }
1867  Company::Get(st->owner)->infrastructure.station++;
1869 
1870  MarkTileDirtyByTile(cur_tile);
1871  }
1872  }
1873 
1874  if (st != NULL) {
1875  st->UpdateVirtCoord();
1876  UpdateStationAcceptance(st, false);
1881  }
1882  return cost;
1883 }
1884 
1885 
1886 static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
1887 {
1888  if (v->type == VEH_ROAD) {
1889  /* Okay... we are a road vehicle on a drive through road stop.
1890  * But that road stop has just been removed, so we need to make
1891  * sure we are in a valid state... however, vehicles can also
1892  * turn on road stop tiles, so only clear the 'road stop' state
1893  * bits and only when the state was 'in road stop', otherwise
1894  * we'll end up clearing the turn around bits. */
1895  RoadVehicle *rv = RoadVehicle::From(v);
1897  }
1898 
1899  return NULL;
1900 }
1901 
1902 
1910 {
1911  Station *st = Station::GetByTile(tile);
1912 
1913  if (_current_company != OWNER_WATER) {
1914  CommandCost ret = CheckOwnership(st->owner);
1915  if (ret.Failed()) return ret;
1916  }
1917 
1918  bool is_truck = IsTruckStop(tile);
1919 
1920  RoadStop **primary_stop;
1921  RoadStop *cur_stop;
1922  if (is_truck) { // truck stop
1923  primary_stop = &st->truck_stops;
1924  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_TRUCK);
1925  } else {
1926  primary_stop = &st->bus_stops;
1927  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_BUS);
1928  }
1929 
1930  assert(cur_stop != NULL);
1931 
1932  /* don't do the check for drive-through road stops when company bankrupts */
1933  if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
1934  /* remove the 'going through road stop' status from all vehicles on that tile */
1935  if (flags & DC_EXEC) FindVehicleOnPos(tile, NULL, &ClearRoadStopStatusEnum);
1936  } else {
1938  if (ret.Failed()) return ret;
1939  }
1940 
1941  if (flags & DC_EXEC) {
1942  if (*primary_stop == cur_stop) {
1943  /* removed the first stop in the list */
1944  *primary_stop = cur_stop->next;
1945  /* removed the only stop? */
1946  if (*primary_stop == NULL) {
1947  st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
1948  }
1949  } else {
1950  /* tell the predecessor in the list to skip this stop */
1951  RoadStop *pred = *primary_stop;
1952  while (pred->next != cur_stop) pred = pred->next;
1953  pred->next = cur_stop->next;
1954  }
1955 
1956  /* Update company infrastructure counts. */
1957  RoadType rt;
1958  FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1959  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
1960  if (c != NULL) {
1961  c->infrastructure.road[rt] -= 2;
1963  }
1964  }
1965  Company::Get(st->owner)->infrastructure.station--;
1967 
1968  if (IsDriveThroughStopTile(tile)) {
1969  /* Clears the tile for us */
1970  cur_stop->ClearDriveThrough();
1971  } else {
1972  DoClearSquare(tile);
1973  }
1974 
1976  delete cur_stop;
1977 
1978  /* Make sure no vehicle is going to the old roadstop */
1979  RoadVehicle *v;
1980  FOR_ALL_ROADVEHICLES(v) {
1981  if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
1982  v->dest_tile == tile) {
1983  v->SetDestTile(v->GetOrderStationLocation(st->index));
1984  }
1985  }
1986 
1987  st->rect.AfterRemoveTile(st, tile);
1988 
1989  st->UpdateVirtCoord();
1992 
1993  /* Update the tile area of the truck/bus stop */
1994  if (is_truck) {
1995  st->truck_station.Clear();
1996  for (const RoadStop *rs = st->truck_stops; rs != NULL; rs = rs->next) st->truck_station.Add(rs->xy);
1997  } else {
1998  st->bus_station.Clear();
1999  for (const RoadStop *rs = st->bus_stops; rs != NULL; rs = rs->next) st->bus_station.Add(rs->xy);
2000  }
2001  }
2002 
2003  return CommandCost(EXPENSES_CONSTRUCTION, _price[is_truck ? PR_CLEAR_STATION_TRUCK : PR_CLEAR_STATION_BUS]);
2004 }
2005 
2017 CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2018 {
2019  uint8 width = (uint8)GB(p1, 0, 8);
2020  uint8 height = (uint8)GB(p1, 8, 8);
2021  bool keep_drive_through_roads = !HasBit(p2, 1);
2022 
2023  /* Check for incorrect width / height. */
2024  if (width == 0 || height == 0) return CMD_ERROR;
2025  /* Check if the first tile and the last tile are valid */
2026  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, height - 1) == INVALID_TILE) return CMD_ERROR;
2027  /* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
2028  if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
2029 
2030  TileArea roadstop_area(tile, width, height);
2031 
2033  CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
2034  bool had_success = false;
2035 
2036  TILE_AREA_LOOP(cur_tile, roadstop_area) {
2037  /* Make sure the specified tile is a road stop of the correct type */
2038  if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
2039 
2040  /* Save information on to-be-restored roads before the stop is removed. */
2041  RoadTypes rts = ROADTYPES_NONE;
2042  RoadBits road_bits = ROAD_NONE;
2043  Owner road_owner[] = { OWNER_NONE, OWNER_NONE };
2044  assert_compile(lengthof(road_owner) == ROADTYPE_END);
2045  if (IsDriveThroughStopTile(cur_tile)) {
2046  RoadType rt;
2047  FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(cur_tile)) {
2048  road_owner[rt] = GetRoadOwner(cur_tile, rt);
2049  /* If we don't want to preserve our roads then restore only roads of others. */
2050  if (keep_drive_through_roads || road_owner[rt] != _current_company) SetBit(rts, rt);
2051  }
2052  road_bits = AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(cur_tile)));
2053  }
2054 
2055  CommandCost ret = RemoveRoadStop(cur_tile, flags);
2056  if (ret.Failed()) {
2057  last_error = ret;
2058  continue;
2059  }
2060  cost.AddCost(ret);
2061  had_success = true;
2062 
2063  /* Restore roads. */
2064  if ((flags & DC_EXEC) && rts != ROADTYPES_NONE) {
2065  MakeRoadNormal(cur_tile, road_bits, rts, ClosestTownFromTile(cur_tile, UINT_MAX)->index,
2066  road_owner[ROADTYPE_ROAD], road_owner[ROADTYPE_TRAM]);
2067 
2068  /* Update company infrastructure counts. */
2069  RoadType rt;
2070  FOR_EACH_SET_ROADTYPE(rt, rts) {
2071  Company *c = Company::GetIfValid(GetRoadOwner(cur_tile, rt));
2072  if (c != NULL) {
2073  c->infrastructure.road[rt] += CountBits(road_bits);
2075  }
2076  }
2077  }
2078  }
2079 
2080  return had_success ? cost : last_error;
2081 }
2082 
2090 {
2091  uint mindist = UINT_MAX;
2092 
2093  for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
2094  mindist = min(mindist, DistanceManhattan(town_tile, cur_tile));
2095  }
2096 
2097  return mindist;
2098 }
2099 
2110 {
2111  /* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
2112  * So no need to go any further*/
2113  if (as->noise_level < 2) return as->noise_level;
2114 
2115  uint distance = GetMinimalAirportDistanceToTile(it, town_tile);
2116 
2117  /* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
2118  * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
2119  * Basically, it says that the less tolerant a town is, the bigger the distance before
2120  * an actual decrease can be granted */
2121  uint8 town_tolerance_distance = 8 + (_settings_game.difficulty.town_council_tolerance * 4);
2122 
2123  /* now, we want to have the distance segmented using the distance judged bareable by town
2124  * This will give us the coefficient of reduction the distance provides. */
2125  uint noise_reduction = distance / town_tolerance_distance;
2126 
2127  /* If the noise reduction equals the airport noise itself, don't give it for free.
2128  * Otherwise, simply reduce the airport's level. */
2129  return noise_reduction >= as->noise_level ? 1 : as->noise_level - noise_reduction;
2130 }
2131 
2140 {
2141  Town *t, *nearest = NULL;
2142  uint add = as->size_x + as->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
2143  uint mindist = UINT_MAX - add; // prevent overflow
2144  FOR_ALL_TOWNS(t) {
2145  if (DistanceManhattan(t->xy, it) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
2146  TileIterator *copy = it.Clone();
2147  uint dist = GetMinimalAirportDistanceToTile(*copy, t->xy);
2148  delete copy;
2149  if (dist < mindist) {
2150  nearest = t;
2151  mindist = dist;
2152  }
2153  }
2154  }
2155 
2156  return nearest;
2157 }
2158 
2159 
2162 {
2163  Town *t;
2164  const Station *st;
2165 
2166  FOR_ALL_TOWNS(t) t->noise_reached = 0;
2167 
2168  FOR_ALL_STATIONS(st) {
2169  if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
2170  const AirportSpec *as = st->airport.GetSpec();
2171  AirportTileIterator it(st);
2172  Town *nearest = AirportGetNearestTown(as, it);
2173  nearest->noise_reached += GetAirportNoiseLevelForTown(as, it, nearest->xy);
2174  }
2175  }
2176 }
2177 
2191 CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2192 {
2193  StationID station_to_join = GB(p2, 16, 16);
2194  bool reuse = (station_to_join != NEW_STATION);
2195  if (!reuse) station_to_join = INVALID_STATION;
2196  bool distant_join = (station_to_join != INVALID_STATION);
2197  byte airport_type = GB(p1, 0, 8);
2198  byte layout = GB(p1, 8, 8);
2199 
2200  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2201 
2202  if (airport_type >= NUM_AIRPORTS) return CMD_ERROR;
2203 
2204  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2205  if (ret.Failed()) return ret;
2206 
2207  /* Check if a valid, buildable airport was chosen for construction */
2208  const AirportSpec *as = AirportSpec::Get(airport_type);
2209  if (!as->IsAvailable() || layout >= as->num_table) return CMD_ERROR;
2210 
2211  Direction rotation = as->rotation[layout];
2212  int w = as->size_x;
2213  int h = as->size_y;
2214  if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
2215  TileArea airport_area = TileArea(tile, w, h);
2216 
2218  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
2219  }
2220 
2221  AirportTileTableIterator iter(as->table[layout], tile);
2222  CommandCost cost = CheckFlatLandAirport(iter, flags);
2223  if (cost.Failed()) return cost;
2224 
2225  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
2226  Town *nearest = AirportGetNearestTown(as, iter);
2227  uint newnoise_level = GetAirportNoiseLevelForTown(as, iter, nearest->xy);
2228 
2229  /* Check if local auth would allow a new airport */
2230  StringID authority_refuse_message = STR_NULL;
2231  Town *authority_refuse_town = NULL;
2232 
2234  /* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
2235  if ((nearest->noise_reached + newnoise_level) > nearest->MaxTownNoise()) {
2236  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE;
2237  authority_refuse_town = nearest;
2238  }
2239  } else {
2240  Town *t = ClosestTownFromTile(tile, UINT_MAX);
2241  uint num = 0;
2242  const Station *st;
2243  FOR_ALL_STATIONS(st) {
2244  if (st->town == t && (st->facilities & FACIL_AIRPORT) && st->airport.type != AT_OILRIG) num++;
2245  }
2246  if (num >= 2) {
2247  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT;
2248  authority_refuse_town = t;
2249  }
2250  }
2251 
2252  if (authority_refuse_message != STR_NULL) {
2253  SetDParam(0, authority_refuse_town->index);
2254  return_cmd_error(authority_refuse_message);
2255  }
2256 
2257  Station *st = NULL;
2258  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p2, 0), airport_area, &st);
2259  if (ret.Failed()) return ret;
2260 
2261  /* Distant join */
2262  if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
2263 
2264  ret = BuildStationPart(&st, flags, reuse, airport_area, (GetAirport(airport_type)->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_AIRPORT : STATIONNAMING_HELIPORT);
2265  if (ret.Failed()) return ret;
2266 
2267  if (st != NULL && st->airport.tile != INVALID_TILE) {
2268  return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT);
2269  }
2270 
2271  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2272  cost.AddCost(_price[PR_BUILD_STATION_AIRPORT]);
2273  }
2274 
2275  if (flags & DC_EXEC) {
2276  /* Always add the noise, so there will be no need to recalculate when option toggles */
2277  nearest->noise_reached += newnoise_level;
2278 
2279  st->AddFacility(FACIL_AIRPORT, tile);
2280  st->airport.type = airport_type;
2281  st->airport.layout = layout;
2282  st->airport.flags = 0;
2283  st->airport.rotation = rotation;
2284 
2285  st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
2286 
2287  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2288  MakeAirport(iter, st->owner, st->index, iter.GetStationGfx(), WATER_CLASS_INVALID);
2289  SetStationTileRandomBits(iter, GB(Random(), 0, 4));
2290  st->airport.Add(iter);
2291 
2293  }
2294 
2295  /* Only call the animation trigger after all tiles have been built */
2296  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2297  AirportTileAnimationTrigger(st, iter, AAT_BUILT);
2298  }
2299 
2301 
2302  Company::Get(st->owner)->infrastructure.airport++;
2304 
2305  st->UpdateVirtCoord();
2306  UpdateStationAcceptance(st, false);
2311 
2314  }
2315  }
2316 
2317  return cost;
2318 }
2319 
2327 {
2328  Station *st = Station::GetByTile(tile);
2329 
2330  if (_current_company != OWNER_WATER) {
2331  CommandCost ret = CheckOwnership(st->owner);
2332  if (ret.Failed()) return ret;
2333  }
2334 
2335  tile = st->airport.tile;
2336 
2338 
2339  const Aircraft *a;
2340  FOR_ALL_AIRCRAFT(a) {
2341  if (!a->IsNormalAircraft()) continue;
2342  if (a->targetairport == st->index && a->state != FLYING) return CMD_ERROR;
2343  }
2344 
2345  if (flags & DC_EXEC) {
2346  const AirportSpec *as = st->airport.GetSpec();
2347  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
2348  * And as for construction, always remove it, even if the setting is not set, in order to avoid the
2349  * need of recalculation */
2350  AirportTileIterator it(st);
2351  Town *nearest = AirportGetNearestTown(as, it);
2352  nearest->noise_reached -= GetAirportNoiseLevelForTown(as, it, nearest->xy);
2353  }
2354 
2355  TILE_AREA_LOOP(tile_cur, st->airport) {
2356  if (!st->TileBelongsToAirport(tile_cur)) continue;
2357 
2358  CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
2359  if (ret.Failed()) return ret;
2360 
2361  cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
2362 
2363  if (flags & DC_EXEC) {
2364  if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
2365  DeleteAnimatedTile(tile_cur);
2366  DoClearSquare(tile_cur);
2367  DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
2368  }
2369  }
2370 
2371  if (flags & DC_EXEC) {
2372  /* Clear the persistent storage. */
2373  delete st->airport.psa;
2374 
2375  for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
2378  );
2379  }
2380 
2381  st->rect.AfterRemoveRect(st, st->airport);
2382 
2383  st->airport.Clear();
2384  st->facilities &= ~FACIL_AIRPORT;
2385 
2387 
2390  }
2391 
2392  Company::Get(st->owner)->infrastructure.airport--;
2394 
2395  st->UpdateVirtCoord();
2398  DeleteNewGRFInspectWindow(GSF_AIRPORTS, st->index);
2399  }
2400 
2401  return cost;
2402 }
2403 
2413 CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2414 {
2415  if (!Station::IsValidID(p1)) return CMD_ERROR;
2416  Station *st = Station::Get(p1);
2417 
2418  if (!(st->facilities & FACIL_AIRPORT) || st->owner == OWNER_NONE) return CMD_ERROR;
2419 
2420  CommandCost ret = CheckOwnership(st->owner);
2421  if (ret.Failed()) return ret;
2422 
2423  if (flags & DC_EXEC) {
2426  }
2427  return CommandCost();
2428 }
2429 
2436 bool HasStationInUse(StationID station, bool include_company, CompanyID company)
2437 {
2438  const Vehicle *v;
2439  FOR_ALL_VEHICLES(v) {
2440  if ((v->owner == company) == include_company) {
2441  const Order *order;
2442  FOR_VEHICLE_ORDERS(v, order) {
2443  if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
2444  return true;
2445  }
2446  }
2447  }
2448  }
2449  return false;
2450 }
2451 
2452 static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
2453  {-1, 0},
2454  { 0, 0},
2455  { 0, 0},
2456  { 0, -1}
2457 };
2458 static const byte _dock_w_chk[4] = { 2, 1, 2, 1 };
2459 static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
2460 
2470 CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2471 {
2472  StationID station_to_join = GB(p2, 16, 16);
2473  bool reuse = (station_to_join != NEW_STATION);
2474  if (!reuse) station_to_join = INVALID_STATION;
2475  bool distant_join = (station_to_join != INVALID_STATION);
2476 
2477  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2478 
2480  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2481  direction = ReverseDiagDir(direction);
2482 
2483  /* Docks cannot be placed on rapids */
2484  if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2485 
2486  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2487  if (ret.Failed()) return ret;
2488 
2489  if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2490 
2491  ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2492  if (ret.Failed()) return ret;
2493 
2494  TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
2495 
2496  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2497  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2498  }
2499 
2500  if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2501 
2502  /* Get the water class of the water tile before it is cleared.*/
2503  WaterClass wc = GetWaterClass(tile_cur);
2504 
2505  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2506  if (ret.Failed()) return ret;
2507 
2508  tile_cur += TileOffsByDiagDir(direction);
2509  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2510  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2511  }
2512 
2513  TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
2514  _dock_w_chk[direction], _dock_h_chk[direction]);
2515 
2516  /* middle */
2517  Station *st = NULL;
2518  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p1, 0), dock_area, &st);
2519  if (ret.Failed()) return ret;
2520 
2521  /* Distant join */
2522  if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
2523 
2524  ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK);
2525  if (ret.Failed()) return ret;
2526 
2527  if (st != NULL && st->dock_tile != INVALID_TILE) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK);
2528 
2529  if (flags & DC_EXEC) {
2530  st->dock_tile = tile;
2531  st->AddFacility(FACIL_DOCK, tile);
2532 
2533  st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY);
2534 
2535  /* If the water part of the dock is on a canal, update infrastructure counts.
2536  * This is needed as we've unconditionally cleared that tile before. */
2537  if (wc == WATER_CLASS_CANAL) {
2538  Company::Get(st->owner)->infrastructure.water++;
2539  }
2540  Company::Get(st->owner)->infrastructure.station += 2;
2542 
2543  MakeDock(tile, st->owner, st->index, direction, wc);
2544 
2545  st->UpdateVirtCoord();
2546  UpdateStationAcceptance(st, false);
2551  }
2552 
2553  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
2554 }
2555 
2563 {
2564  Station *st = Station::GetByTile(tile);
2565  CommandCost ret = CheckOwnership(st->owner);
2566  if (ret.Failed()) return ret;
2567 
2568  TileIndex docking_location = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
2569 
2570  TileIndex tile1 = st->dock_tile;
2571  TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
2572 
2573  ret = EnsureNoVehicleOnGround(tile1);
2574  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
2575  if (ret.Failed()) return ret;
2576 
2577  if (flags & DC_EXEC) {
2578  DoClearSquare(tile1);
2579  MarkTileDirtyByTile(tile1);
2580  MakeWaterKeepingClass(tile2, st->owner);
2581 
2582  st->rect.AfterRemoveTile(st, tile1);
2583  st->rect.AfterRemoveTile(st, tile2);
2584 
2585  st->dock_tile = INVALID_TILE;
2586  st->facilities &= ~FACIL_DOCK;
2587 
2588  Company::Get(st->owner)->infrastructure.station -= 2;
2590 
2592  st->UpdateVirtCoord();
2595 
2596  /* All ships that were going to our station, can't go to it anymore.
2597  * Just clear the order, then automatically the next appropriate order
2598  * will be selected and in case of no appropriate order it will just
2599  * wander around the world. */
2600  Ship *s;
2601  FOR_ALL_SHIPS(s) {
2602  if (s->current_order.IsType(OT_LOADING) && s->tile == docking_location) {
2603  s->LeaveStation();
2604  }
2605 
2606  if (s->dest_tile == docking_location) {
2607  s->SetDestTile(0);
2608  s->current_order.Free();
2609  }
2610  }
2611  }
2612 
2613  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_DOCK]);
2614 }
2615 
2616 #include "table/station_land.h"
2617 
2618 const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
2619 {
2620  return &_station_display_datas[st][gfx];
2621 }
2622 
2632 bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset)
2633 {
2634  bool snow_desert;
2635  switch (*ground) {
2636  case SPR_RAIL_TRACK_X:
2637  snow_desert = false;
2638  *overlay_offset = RTO_X;
2639  break;
2640 
2641  case SPR_RAIL_TRACK_Y:
2642  snow_desert = false;
2643  *overlay_offset = RTO_Y;
2644  break;
2645 
2646  case SPR_RAIL_TRACK_X_SNOW:
2647  snow_desert = true;
2648  *overlay_offset = RTO_X;
2649  break;
2650 
2651  case SPR_RAIL_TRACK_Y_SNOW:
2652  snow_desert = true;
2653  *overlay_offset = RTO_Y;
2654  break;
2655 
2656  default:
2657  return false;
2658  }
2659 
2660  if (ti != NULL) {
2661  /* Decide snow/desert from tile */
2663  case LT_ARCTIC:
2664  snow_desert = (uint)ti->z > GetSnowLine() * TILE_HEIGHT;
2665  break;
2666 
2667  case LT_TROPIC:
2668  snow_desert = GetTropicZone(ti->tile) == TROPICZONE_DESERT;
2669  break;
2670 
2671  default:
2672  break;
2673  }
2674  }
2675 
2676  *ground = snow_desert ? SPR_FLAT_SNOW_DESERT_TILE : SPR_FLAT_GRASS_TILE;
2677  return true;
2678 }
2679 
2680 static void DrawTile_Station(TileInfo *ti)
2681 {
2682  const NewGRFSpriteLayout *layout = NULL;
2683  DrawTileSprites tmp_rail_layout;
2684  const DrawTileSprites *t = NULL;
2685  RoadTypes roadtypes;
2686  int32 total_offset;
2687  const RailtypeInfo *rti = NULL;
2688  uint32 relocation = 0;
2689  uint32 ground_relocation = 0;
2690  BaseStation *st = NULL;
2691  const StationSpec *statspec = NULL;
2692  uint tile_layout = 0;
2693 
2694  if (HasStationRail(ti->tile)) {
2695  rti = GetRailTypeInfo(GetRailType(ti->tile));
2696  roadtypes = ROADTYPES_NONE;
2697  total_offset = rti->GetRailtypeSpriteOffset();
2698 
2699  if (IsCustomStationSpecIndex(ti->tile)) {
2700  /* look for customization */
2701  st = BaseStation::GetByTile(ti->tile);
2702  statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
2703 
2704  if (statspec != NULL) {
2705  tile_layout = GetStationGfx(ti->tile);
2706 
2708  uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
2709  if (callback != CALLBACK_FAILED) tile_layout = (callback & ~1) + GetRailStationAxis(ti->tile);
2710  }
2711 
2712  /* Ensure the chosen tile layout is valid for this custom station */
2713  if (statspec->renderdata != NULL) {
2714  layout = &statspec->renderdata[tile_layout < statspec->tiles ? tile_layout : (uint)GetRailStationAxis(ti->tile)];
2715  if (!layout->NeedsPreprocessing()) {
2716  t = layout;
2717  layout = NULL;
2718  }
2719  }
2720  }
2721  }
2722  } else {
2723  roadtypes = IsRoadStop(ti->tile) ? GetRoadTypes(ti->tile) : ROADTYPES_NONE;
2724  total_offset = 0;
2725  }
2726 
2727  StationGfx gfx = GetStationGfx(ti->tile);
2728  if (IsAirport(ti->tile)) {
2729  gfx = GetAirportGfx(ti->tile);
2730  if (gfx >= NEW_AIRPORTTILE_OFFSET) {
2731  const AirportTileSpec *ats = AirportTileSpec::Get(gfx);
2732  if (ats->grf_prop.spritegroup[0] != NULL && DrawNewAirportTile(ti, Station::GetByTile(ti->tile), gfx, ats)) {
2733  return;
2734  }
2735  /* No sprite group (or no valid one) found, meaning no graphics associated.
2736  * Use the substitute one instead */
2737  assert(ats->grf_prop.subst_id != INVALID_AIRPORTTILE);
2738  gfx = ats->grf_prop.subst_id;
2739  }
2740  switch (gfx) {
2741  case APT_RADAR_GRASS_FENCE_SW:
2742  t = &_station_display_datas_airport_radar_grass_fence_sw[GetAnimationFrame(ti->tile)];
2743  break;
2744  case APT_GRASS_FENCE_NE_FLAG:
2745  t = &_station_display_datas_airport_flag_grass_fence_ne[GetAnimationFrame(ti->tile)];
2746  break;
2747  case APT_RADAR_FENCE_SW:
2748  t = &_station_display_datas_airport_radar_fence_sw[GetAnimationFrame(ti->tile)];
2749  break;
2750  case APT_RADAR_FENCE_NE:
2751  t = &_station_display_datas_airport_radar_fence_ne[GetAnimationFrame(ti->tile)];
2752  break;
2753  case APT_GRASS_FENCE_NE_FLAG_2:
2754  t = &_station_display_datas_airport_flag_grass_fence_ne_2[GetAnimationFrame(ti->tile)];
2755  break;
2756  }
2757  }
2758 
2759  Owner owner = GetTileOwner(ti->tile);
2760 
2761  PaletteID palette;
2762  if (Company::IsValidID(owner)) {
2763  palette = COMPANY_SPRITE_COLOUR(owner);
2764  } else {
2765  /* Some stations are not owner by a company, namely oil rigs */
2766  palette = PALETTE_TO_GREY;
2767  }
2768 
2769  if (layout == NULL && (t == NULL || t->seq == NULL)) t = GetStationTileLayout(GetStationType(ti->tile), gfx);
2770 
2771  /* don't show foundation for docks */
2772  if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) {
2773  if (statspec != NULL && HasBit(statspec->flags, SSF_CUSTOM_FOUNDATIONS)) {
2774  /* Station has custom foundations.
2775  * Check whether the foundation continues beyond the tile's upper sides. */
2776  uint edge_info = 0;
2777  int z;
2778  Slope slope = GetFoundationPixelSlope(ti->tile, &z);
2779  if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0);
2780  if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1);
2781  SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, tile_layout, edge_info);
2782  if (image == 0) goto draw_default_foundation;
2783 
2784  if (HasBit(statspec->flags, SSF_EXTENDED_FOUNDATIONS)) {
2785  /* Station provides extended foundations. */
2786 
2787  static const uint8 foundation_parts[] = {
2788  0, 0, 0, 0, // Invalid, Invalid, Invalid, SLOPE_SW
2789  0, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
2790  0, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
2791  7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
2792  };
2793 
2794  AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2795  } else {
2796  /* Draw simple foundations, built up from 8 possible foundation sprites. */
2797 
2798  /* Each set bit represents one of the eight composite sprites to be drawn.
2799  * 'Invalid' entries will not drawn but are included for completeness. */
2800  static const uint8 composite_foundation_parts[] = {
2801  /* Invalid (00000000), Invalid (11010001), Invalid (11100100), SLOPE_SW (11100000) */
2802  0x00, 0xD1, 0xE4, 0xE0,
2803  /* Invalid (11001010), SLOPE_EW (11001001), SLOPE_SE (11000100), SLOPE_WSE (11000000) */
2804  0xCA, 0xC9, 0xC4, 0xC0,
2805  /* Invalid (11010010), SLOPE_NW (10010001), SLOPE_NS (11100100), SLOPE_NWS (10100000) */
2806  0xD2, 0x91, 0xE4, 0xA0,
2807  /* SLOPE_NE (01001010), SLOPE_ENW (00001001), SLOPE_SEN (01000100) */
2808  0x4A, 0x09, 0x44
2809  };
2810 
2811  uint8 parts = composite_foundation_parts[ti->tileh];
2812 
2813  /* If foundations continue beyond the tile's upper sides then
2814  * mask out the last two pieces. */
2815  if (HasBit(edge_info, 0)) ClrBit(parts, 6);
2816  if (HasBit(edge_info, 1)) ClrBit(parts, 7);
2817 
2818  if (parts == 0) {
2819  /* We always have to draw at least one sprite to make sure there is a boundingbox and a sprite with the
2820  * correct offset for the childsprites.
2821  * So, draw the (completely empty) sprite of the default foundations. */
2822  goto draw_default_foundation;
2823  }
2824 
2826  for (int i = 0; i < 8; i++) {
2827  if (HasBit(parts, i)) {
2828  AddSortableSpriteToDraw(image + i, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2829  }
2830  }
2831  EndSpriteCombine();
2832  }
2833 
2834  OffsetGroundSprite(31, 1);
2836  } else {
2837 draw_default_foundation:
2839  }
2840  }
2841 
2842  if (IsBuoy(ti->tile)) {
2843  DrawWaterClassGround(ti);
2844  SpriteID sprite = GetCanalSprite(CF_BUOY, ti->tile);
2845  if (sprite != 0) total_offset = sprite - SPR_IMG_BUOY;
2846  } else if (IsDock(ti->tile) || (IsOilRig(ti->tile) && IsTileOnWater(ti->tile))) {
2847  if (ti->tileh == SLOPE_FLAT) {
2848  DrawWaterClassGround(ti);
2849  } else {
2850  assert(IsDock(ti->tile));
2851  TileIndex water_tile = ti->tile + TileOffsByDiagDir(GetDockDirection(ti->tile));
2852  WaterClass wc = GetWaterClass(water_tile);
2853  if (wc == WATER_CLASS_SEA) {
2854  DrawShoreTile(ti->tileh);
2855  } else {
2856  DrawClearLandTile(ti, 3);
2857  }
2858  }
2859  } else {
2860  if (layout != NULL) {
2861  /* Sprite layout which needs preprocessing */
2862  bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
2863  uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
2864  uint8 var10;
2865  FOR_EACH_SET_BIT(var10, var10_values) {
2866  uint32 var10_relocation = GetCustomStationRelocation(statspec, st, ti->tile, var10);
2867  layout->ProcessRegisters(var10, var10_relocation, separate_ground);
2868  }
2869  tmp_rail_layout.seq = layout->GetLayout(&tmp_rail_layout.ground);
2870  t = &tmp_rail_layout;
2871  total_offset = 0;
2872  } else if (statspec != NULL) {
2873  /* Simple sprite layout */
2874  ground_relocation = relocation = GetCustomStationRelocation(statspec, st, ti->tile, 0);
2875  if (HasBit(statspec->flags, SSF_SEPARATE_GROUND)) {
2876  ground_relocation = GetCustomStationRelocation(statspec, st, ti->tile, 1);
2877  }
2878  ground_relocation += rti->fallback_railtype;
2879  }
2880 
2881  SpriteID image = t->ground.sprite;
2882  PaletteID pal = t->ground.pal;
2883  RailTrackOffset overlay_offset;
2884  if (rti != NULL && rti->UsesOverlay() && SplitGroundSpriteForOverlay(ti, &image, &overlay_offset)) {
2885  SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND);
2886  DrawGroundSprite(image, PAL_NONE);
2887  DrawGroundSprite(ground + overlay_offset, PAL_NONE);
2888 
2889  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationReservation(ti->tile)) {
2890  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
2891  DrawGroundSprite(overlay + overlay_offset, PALETTE_CRASH);
2892  }
2893  } else {
2894  image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset;
2895  if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation;
2896  DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
2897 
2898  /* PBS debugging, draw reserved tracks darker */
2899  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationRail(ti->tile) && HasStationReservation(ti->tile)) {
2900  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
2902  }
2903  }
2904  }
2905 
2907 
2908  if (HasBit(roadtypes, ROADTYPE_TRAM)) {
2909  Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
2910  DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
2911  DrawRoadCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
2912  }
2913 
2914  if (IsRailWaypoint(ti->tile)) {
2915  /* Don't offset the waypoint graphics; they're always the same. */
2916  total_offset = 0;
2917  }
2918 
2919  DrawRailTileSeq(ti, t, TO_BUILDINGS, total_offset, relocation, palette);
2920 }
2921 
2922 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
2923 {
2924  int32 total_offset = 0;
2925  PaletteID pal = COMPANY_SPRITE_COLOUR(_local_company);
2926  const DrawTileSprites *t = GetStationTileLayout(st, image);
2927  const RailtypeInfo *rti = NULL;
2928 
2929  if (railtype != INVALID_RAILTYPE) {
2930  rti = GetRailTypeInfo(railtype);
2931  total_offset = rti->GetRailtypeSpriteOffset();
2932  }
2933 
2934  SpriteID img = t->ground.sprite;
2935  RailTrackOffset overlay_offset;
2936  if (rti != NULL && rti->UsesOverlay() && SplitGroundSpriteForOverlay(NULL, &img, &overlay_offset)) {
2938  DrawSprite(img, PAL_NONE, x, y);
2939  DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
2940  } else {
2941  DrawSprite(img + total_offset, HasBit(img, PALETTE_MODIFIER_COLOUR) ? pal : PAL_NONE, x, y);
2942  }
2943 
2944  if (roadtype == ROADTYPE_TRAM) {
2945  DrawSprite(SPR_TRAMWAY_TRAM + (t->ground.sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
2946  }
2947 
2948  /* Default waypoint has no railtype specific sprites */
2949  DrawRailTileSeqInGUI(x, y, t, st == STATION_WAYPOINT ? 0 : total_offset, 0, pal);
2950 }
2951 
2952 static int GetSlopePixelZ_Station(TileIndex tile, uint x, uint y)
2953 {
2954  return GetTileMaxPixelZ(tile);
2955 }
2956 
2957 static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
2958 {
2959  return FlatteningFoundation(tileh);
2960 }
2961 
2962 static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
2963 {
2964  td->owner[0] = GetTileOwner(tile);
2965  if (IsDriveThroughStopTile(tile)) {
2966  Owner road_owner = INVALID_OWNER;
2967  Owner tram_owner = INVALID_OWNER;
2968  RoadTypes rts = GetRoadTypes(tile);
2969  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
2970  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
2971 
2972  /* Is there a mix of owners? */
2973  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
2974  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
2975  uint i = 1;
2976  if (road_owner != INVALID_OWNER) {
2977  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2978  td->owner[i] = road_owner;
2979  i++;
2980  }
2981  if (tram_owner != INVALID_OWNER) {
2982  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
2983  td->owner[i] = tram_owner;
2984  }
2985  }
2986  }
2988 
2989  if (HasStationTileRail(tile)) {
2990  const StationSpec *spec = GetStationSpec(tile);
2991 
2992  if (spec != NULL) {
2994  td->station_name = spec->name;
2995 
2996  if (spec->grf_prop.grffile != NULL) {
2997  const GRFConfig *gc = GetGRFConfig(spec->grf_prop.grffile->grfid);
2998  td->grf = gc->GetName();
2999  }
3000  }
3001 
3002  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
3003  td->rail_speed = rti->max_speed;
3004  td->railtype = rti->strings.name;
3005  }
3006 
3007  if (IsAirport(tile)) {
3008  const AirportSpec *as = Station::GetByTile(tile)->airport.GetSpec();
3010  td->airport_name = as->name;
3011 
3012  const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
3013  td->airport_tile_name = ats->name;
3014 
3015  if (as->grf_prop.grffile != NULL) {
3016  const GRFConfig *gc = GetGRFConfig(as->grf_prop.grffile->grfid);
3017  td->grf = gc->GetName();
3018  } else if (ats->grf_prop.grffile != NULL) {
3019  const GRFConfig *gc = GetGRFConfig(ats->grf_prop.grffile->grfid);
3020  td->grf = gc->GetName();
3021  }
3022  }
3023 
3024  StringID str;
3025  switch (GetStationType(tile)) {
3026  default: NOT_REACHED();
3027  case STATION_RAIL: str = STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION; break;
3028  case STATION_AIRPORT:
3029  str = (IsHangar(tile) ? STR_LAI_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_LAI_STATION_DESCRIPTION_AIRPORT);
3030  break;
3031  case STATION_TRUCK: str = STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
3032  case STATION_BUS: str = STR_LAI_STATION_DESCRIPTION_BUS_STATION; break;
3033  case STATION_OILRIG: str = STR_INDUSTRY_NAME_OIL_RIG; break;
3034  case STATION_DOCK: str = STR_LAI_STATION_DESCRIPTION_SHIP_DOCK; break;
3035  case STATION_BUOY: str = STR_LAI_STATION_DESCRIPTION_BUOY; break;
3036  case STATION_WAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT; break;
3037  }
3038  td->str = str;
3039 }
3040 
3041 
3042 static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
3043 {
3044  TrackBits trackbits = TRACK_BIT_NONE;
3045 
3046  switch (mode) {
3047  case TRANSPORT_RAIL:
3048  if (HasStationRail(tile) && !IsStationTileBlocked(tile)) {
3049  trackbits = TrackToTrackBits(GetRailStationTrack(tile));
3050  }
3051  break;
3052 
3053  case TRANSPORT_WATER:
3054  /* buoy is coded as a station, it is always on open water */
3055  if (IsBuoy(tile)) {
3056  trackbits = TRACK_BIT_ALL;
3057  /* remove tracks that connect NE map edge */
3058  if (TileX(tile) == 0) trackbits &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
3059  /* remove tracks that connect NW map edge */
3060  if (TileY(tile) == 0) trackbits &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
3061  }
3062  break;
3063 
3064  case TRANSPORT_ROAD:
3065  if ((GetRoadTypes(tile) & sub_mode) != 0 && IsRoadStop(tile)) {
3066  DiagDirection dir = GetRoadStopDir(tile);
3067  Axis axis = DiagDirToAxis(dir);
3068 
3069  if (side != INVALID_DIAGDIR) {
3070  if (axis != DiagDirToAxis(side) || (IsStandardRoadStopTile(tile) && dir != side)) break;
3071  }
3072 
3073  trackbits = AxisToTrackBits(axis);
3074  }
3075  break;
3076 
3077  default:
3078  break;
3079  }
3080 
3082 }
3083 
3084 
3085 static void TileLoop_Station(TileIndex tile)
3086 {
3087  /* FIXME -- GetTileTrackStatus_Station -> animated stationtiles
3088  * hardcoded.....not good */
3089  switch (GetStationType(tile)) {
3090  case STATION_AIRPORT:
3091  AirportTileAnimationTrigger(Station::GetByTile(tile), tile, AAT_TILELOOP);
3092  break;
3093 
3094  case STATION_DOCK:
3095  if (!IsTileFlat(tile)) break; // only handle water part
3096  FALLTHROUGH;
3097 
3098  case STATION_OILRIG: //(station part)
3099  case STATION_BUOY:
3100  TileLoop_Water(tile);
3101  break;
3102 
3103  default: break;
3104  }
3105 }
3106 
3107 
3108 static void AnimateTile_Station(TileIndex tile)
3109 {
3110  if (HasStationRail(tile)) {
3111  AnimateStationTile(tile);
3112  return;
3113  }
3114 
3115  if (IsAirport(tile)) {
3116  AnimateAirportTile(tile);
3117  }
3118 }
3119 
3120 
3121 static bool ClickTile_Station(TileIndex tile)
3122 {
3123  const BaseStation *bst = BaseStation::GetByTile(tile);
3124 
3125  if (bst->facilities & FACIL_WAYPOINT) {
3127  } else if (IsHangar(tile)) {
3128  const Station *st = Station::From(bst);
3130  } else {
3132  }
3133  return true;
3134 }
3135 
3136 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
3137 {
3138  if (v->type == VEH_TRAIN) {
3139  StationID station_id = GetStationIndex(tile);
3140  if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
3141  if (!IsRailStation(tile) || !v->IsFrontEngine()) return VETSB_CONTINUE;
3142 
3143  int station_ahead;
3144  int station_length;
3145  int stop = GetTrainStopLocation(station_id, tile, Train::From(v), &station_ahead, &station_length);
3146 
3147  /* Stop whenever that amount of station ahead + the distance from the
3148  * begin of the platform to the stop location is longer than the length
3149  * of the platform. Station ahead 'includes' the current tile where the
3150  * vehicle is on, so we need to subtract that. */
3151  if (stop + station_ahead - (int)TILE_SIZE >= station_length) return VETSB_CONTINUE;
3152 
3154 
3155  x &= 0xF;
3156  y &= 0xF;
3157 
3158  if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
3159  if (y == TILE_SIZE / 2) {
3160  if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
3161  stop &= TILE_SIZE - 1;
3162 
3163  if (x == stop) {
3164  return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); // enter station
3165  } else if (x < stop) {
3167  uint16 spd = max(0, (stop - x) * 20 - 15);
3168  if (spd < v->cur_speed) v->cur_speed = spd;
3169  }
3170  }
3171  } else if (v->type == VEH_ROAD) {
3172  RoadVehicle *rv = RoadVehicle::From(v);
3173  if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) {
3174  if (IsRoadStop(tile) && rv->IsFrontEngine()) {
3175  /* Attempt to allocate a parking bay in a road stop */
3177  }
3178  }
3179  }
3180 
3181  return VETSB_CONTINUE;
3182 }
3183 
3189 {
3190  /* Collect cargoes accepted since the last big tick. */
3191  CargoTypes cargoes = 0;
3192  for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
3193  if (HasBit(st->goods[cid].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cid);
3194  }
3195 
3196  /* Anything to do? */
3197  if (cargoes == 0) return;
3198 
3199  /* Loop over all houses in the catchment. */
3200  Rect r = st->GetCatchmentRect();
3201  TileArea ta(TileXY(r.left, r.top), TileXY(r.right, r.bottom));
3202  TILE_AREA_LOOP(tile, ta) {
3203  if (IsTileType(tile, MP_HOUSE)) {
3204  WatchedCargoCallback(tile, cargoes);
3205  }
3206  }
3207 }
3208 
3216 {
3217  if (!st->IsInUse()) {
3218  if (++st->delete_ctr >= 8) delete st;
3219  return false;
3220  }
3221 
3222  if (Station::IsExpected(st)) {
3224 
3225  for (CargoID i = 0; i < NUM_CARGO; i++) {
3226  ClrBit(Station::From(st)->goods[i].status, GoodsEntry::GES_ACCEPTED_BIGTICK);
3227  }
3228  }
3229 
3230 
3231  if ((st->facilities & FACIL_WAYPOINT) == 0) UpdateStationAcceptance(Station::From(st), true);
3232 
3233  return true;
3234 }
3235 
3236 static inline void byte_inc_sat(byte *p)
3237 {
3238  byte b = *p + 1;
3239  if (b != 0) *p = b;
3240 }
3241 
3248 static void TruncateCargo(const CargoSpec *cs, GoodsEntry *ge, uint amount = UINT_MAX)
3249 {
3250  /* If truncating also punish the source stations' ratings to
3251  * decrease the flow of incoming cargo. */
3252 
3253  StationCargoAmountMap waiting_per_source;
3254  ge->cargo.Truncate(amount, &waiting_per_source);
3255  for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
3256  Station *source_station = Station::GetIfValid(i->first);
3257  if (source_station == NULL) continue;
3258 
3259  GoodsEntry &source_ge = source_station->goods[cs->Index()];
3260  source_ge.max_waiting_cargo = max(source_ge.max_waiting_cargo, i->second);
3261  }
3262 }
3263 
3264 static void UpdateStationRating(Station *st)
3265 {
3266  bool waiting_changed = false;
3267 
3268  byte_inc_sat(&st->time_since_load);
3269  byte_inc_sat(&st->time_since_unload);
3270 
3271  const CargoSpec *cs;
3272  FOR_ALL_CARGOSPECS(cs) {
3273  GoodsEntry *ge = &st->goods[cs->Index()];
3274  /* Slowly increase the rating back to his original level in the case we
3275  * didn't deliver cargo yet to this station. This happens when a bribe
3276  * failed while you didn't moved that cargo yet to a station. */
3277  if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) {
3278  ge->rating++;
3279  }
3280 
3281  /* Only change the rating if we are moving this cargo */
3282  if (ge->HasRating()) {
3283  byte_inc_sat(&ge->time_since_pickup);
3284  if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) {
3286  ge->last_speed = 0;
3287  TruncateCargo(cs, ge);
3288  waiting_changed = true;
3289  continue;
3290  }
3291 
3292  bool skip = false;
3293  int rating = 0;
3294  uint waiting = ge->cargo.AvailableCount();
3295 
3296  /* num_dests is at least 1 if there is any cargo as
3297  * INVALID_STATION is also a destination.
3298  */
3299  uint num_dests = (uint)ge->cargo.Packets()->MapSize();
3300 
3301  /* Average amount of cargo per next hop, but prefer solitary stations
3302  * with only one or two next hops. They are allowed to have more
3303  * cargo waiting per next hop.
3304  * With manual cargo distribution waiting_avg = waiting / 2 as then
3305  * INVALID_STATION is the only destination.
3306  */
3307  uint waiting_avg = waiting / (num_dests + 1);
3308 
3310  /* Perform custom station rating. If it succeeds the speed, days in transit and
3311  * waiting cargo ratings must not be executed. */
3312 
3313  /* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
3314  uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
3315 
3316  uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
3317  /* Convert to the 'old' vehicle types */
3318  uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
3319  uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
3320  if (callback != CALLBACK_FAILED) {
3321  skip = true;
3322  rating = GB(callback, 0, 14);
3323 
3324  /* Simulate a 15 bit signed value */
3325  if (HasBit(callback, 14)) rating -= 0x4000;
3326  }
3327  }
3328 
3329  if (!skip) {
3330  int b = ge->last_speed - 85;
3331  if (b >= 0) rating += b >> 2;
3332 
3333  byte waittime = ge->time_since_pickup;
3334  if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2;
3335  (waittime > 21) ||
3336  (rating += 25, waittime > 12) ||
3337  (rating += 25, waittime > 6) ||
3338  (rating += 45, waittime > 3) ||
3339  (rating += 35, true);
3340 
3341  (rating -= 90, ge->max_waiting_cargo > 1500) ||
3342  (rating += 55, ge->max_waiting_cargo > 1000) ||
3343  (rating += 35, ge->max_waiting_cargo > 600) ||
3344  (rating += 10, ge->max_waiting_cargo > 300) ||
3345  (rating += 20, ge->max_waiting_cargo > 100) ||
3346  (rating += 10, true);
3347  }
3348 
3349  if (Company::IsValidID(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
3350 
3351  byte age = ge->last_age;
3352  (age >= 3) ||
3353  (rating += 10, age >= 2) ||
3354  (rating += 10, age >= 1) ||
3355  (rating += 13, true);
3356 
3357  {
3358  int or_ = ge->rating; // old rating
3359 
3360  /* only modify rating in steps of -2, -1, 0, 1 or 2 */
3361  ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
3362 
3363  /* if rating is <= 64 and more than 100 items waiting on average per destination,
3364  * remove some random amount of goods from the station */
3365  if (rating <= 64 && waiting_avg >= 100) {
3366  int dec = Random() & 0x1F;
3367  if (waiting_avg < 200) dec &= 7;
3368  waiting -= (dec + 1) * num_dests;
3369  waiting_changed = true;
3370  }
3371 
3372  /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
3373  if (rating <= 127 && waiting != 0) {
3374  uint32 r = Random();
3375  if (rating <= (int)GB(r, 0, 7)) {
3376  /* Need to have int, otherwise it will just overflow etc. */
3377  waiting = max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
3378  waiting_changed = true;
3379  }
3380  }
3381 
3382  /* At some point we really must cap the cargo. Previously this
3383  * was a strict 4095, but now we'll have a less strict, but
3384  * increasingly aggressive truncation of the amount of cargo. */
3385  static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
3386  static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
3387  static const uint MAX_WAITING_CARGO = 1 << 15;
3388 
3389  if (waiting > WAITING_CARGO_THRESHOLD) {
3390  uint difference = waiting - WAITING_CARGO_THRESHOLD;
3391  waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
3392 
3393  waiting = min(waiting, MAX_WAITING_CARGO);
3394  waiting_changed = true;
3395  }
3396 
3397  /* We can't truncate cargo that's already reserved for loading.
3398  * Thus StoredCount() here. */
3399  if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
3400  /* Feed back the exact own waiting cargo at this station for the
3401  * next rating calculation. */
3402  ge->max_waiting_cargo = 0;
3403 
3404  TruncateCargo(cs, ge, ge->cargo.AvailableCount() - waiting);
3405  } else {
3406  /* If the average number per next hop is low, be more forgiving. */
3407  ge->max_waiting_cargo = waiting_avg;
3408  }
3409  }
3410  }
3411  }
3412 
3413  StationID index = st->index;
3414  if (waiting_changed) {
3415  SetWindowDirty(WC_STATION_VIEW, index); // update whole window
3416  } else {
3417  SetWindowWidgetDirty(WC_STATION_VIEW, index, WID_SV_ACCEPT_RATING_LIST); // update only ratings list
3418  }
3419 }
3420 
3429 void RerouteCargo(Station *st, CargoID c, StationID avoid, StationID avoid2)
3430 {
3431  GoodsEntry &ge = st->goods[c];
3432 
3433  /* Reroute cargo in station. */
3434  ge.cargo.Reroute(UINT_MAX, &ge.cargo, avoid, avoid2, &ge);
3435 
3436  /* Reroute cargo staged to be transferred. */
3437  for (std::list<Vehicle *>::iterator it(st->loading_vehicles.begin()); it != st->loading_vehicles.end(); ++it) {
3438  for (Vehicle *v = *it; v != NULL; v = v->Next()) {
3439  if (v->cargo_type != c) continue;
3440  v->cargo.Reroute(UINT_MAX, &v->cargo, avoid, avoid2, &ge);
3441  }
3442  }
3443 }
3444 
3454 {
3455  for (CargoID c = 0; c < NUM_CARGO; ++c) {
3456  const bool auto_distributed = (_settings_game.linkgraph.GetDistributionType(c) != DT_MANUAL);
3457  GoodsEntry &ge = from->goods[c];
3459  if (lg == NULL) continue;
3460  Node node = (*lg)[ge.node];
3461  for (EdgeIterator it(node.Begin()); it != node.End();) {
3462  Edge edge = it->second;
3463  Station *to = Station::Get((*lg)[it->first].Station());
3464  assert(to->goods[c].node == it->first);
3465  ++it; // Do that before removing the edge. Anything else may crash.
3466  assert(_date >= edge.LastUpdate());
3467  uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3);
3468  if ((uint)(_date - edge.LastUpdate()) > timeout) {
3469  bool updated = false;
3470 
3471  if (auto_distributed) {
3472  /* Have all vehicles refresh their next hops before deciding to
3473  * remove the node. */
3474  OrderList *l;
3475  SmallVector<Vehicle *, 32> vehicles;
3476  FOR_ALL_ORDER_LISTS(l) {
3477  bool found_from = false;
3478  bool found_to = false;
3479  for (Order *order = l->GetFirstOrder(); order != NULL; order = order->next) {
3480  if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_IMPLICIT)) continue;
3481  if (order->GetDestination() == from->index) {
3482  found_from = true;
3483  if (found_to) break;
3484  } else if (order->GetDestination() == to->index) {
3485  found_to = true;
3486  if (found_from) break;
3487  }
3488  }
3489  if (!found_to || !found_from) continue;
3490  *(vehicles.Append()) = l->GetFirstSharedVehicle();
3491  }
3492 
3493  Vehicle **iter = vehicles.Begin();
3494  while (iter != vehicles.End()) {
3495  Vehicle *v = *iter;
3496 
3497  LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted.
3498  if (edge.LastUpdate() == _date) {
3499  updated = true;
3500  break;
3501  }
3502 
3503  Vehicle *next_shared = v->NextShared();
3504  if (next_shared) {
3505  *iter = next_shared;
3506  ++iter;
3507  } else {
3508  vehicles.Erase(iter);
3509  }
3510 
3511  if (iter == vehicles.End()) iter = vehicles.Begin();
3512  }
3513  }
3514 
3515  if (!updated) {
3516  /* If it's still considered dead remove it. */
3517  node.RemoveEdge(to->goods[c].node);
3518  ge.flows.DeleteFlows(to->index);
3519  RerouteCargo(from, c, to->index, from->index);
3520  }
3521  } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) {
3522  edge.Restrict();
3523  ge.flows.RestrictFlows(to->index);
3524  RerouteCargo(from, c, to->index, from->index);
3525  } else if (edge.LastRestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastRestrictedUpdate()) > timeout) {
3526  edge.Release();
3527  }
3528  }
3529  assert(_date >= lg->LastCompression());
3530  if ((uint)(_date - lg->LastCompression()) > LinkGraph::COMPRESSION_INTERVAL) {
3531  lg->Compress();
3532  }
3533  }
3534 }
3535 
3545 void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, EdgeUpdateMode mode)
3546 {
3547  GoodsEntry &ge1 = st->goods[cargo];
3548  Station *st2 = Station::Get(next_station_id);
3549  GoodsEntry &ge2 = st2->goods[cargo];
3550  LinkGraph *lg = NULL;
3551  if (ge1.link_graph == INVALID_LINK_GRAPH) {
3552  if (ge2.link_graph == INVALID_LINK_GRAPH) {
3554  lg = new LinkGraph(cargo);
3556  ge2.link_graph = lg->index;
3557  ge2.node = lg->AddNode(st2);
3558  } else {
3559  DEBUG(misc, 0, "Can't allocate link graph");
3560  }
3561  } else {
3562  lg = LinkGraph::Get(ge2.link_graph);
3563  }
3564  if (lg) {
3565  ge1.link_graph = lg->index;
3566  ge1.node = lg->AddNode(st);
3567  }
3568  } else if (ge2.link_graph == INVALID_LINK_GRAPH) {
3569  lg = LinkGraph::Get(ge1.link_graph);
3570  ge2.link_graph = lg->index;
3571  ge2.node = lg->AddNode(st2);
3572  } else {
3573  lg = LinkGraph::Get(ge1.link_graph);
3574  if (ge1.link_graph != ge2.link_graph) {
3575  LinkGraph *lg2 = LinkGraph::Get(ge2.link_graph);
3576  if (lg->Size() < lg2->Size()) {
3578  lg2->Merge(lg); // Updates GoodsEntries of lg
3579  lg = lg2;
3580  } else {
3582  lg->Merge(lg2); // Updates GoodsEntries of lg2
3583  }
3584  }
3585  }
3586  if (lg != NULL) {
3587  (*lg)[ge1.node].UpdateEdge(ge2.node, capacity, usage, mode);
3588  }
3589 }
3590 
3597 void IncreaseStats(Station *st, const Vehicle *front, StationID next_station_id)
3598 {
3599  for (const Vehicle *v = front; v != NULL; v = v->Next()) {
3600  if (v->refit_cap > 0) {
3601  /* The cargo count can indeed be higher than the refit_cap if
3602  * wagons have been auto-replaced and subsequently auto-
3603  * refitted to a higher capacity. The cargo gets redistributed
3604  * among the wagons in that case.
3605  * As usage is not such an important figure anyway we just
3606  * ignore the additional cargo then.*/
3607  IncreaseStats(st, v->cargo_type, next_station_id, v->refit_cap,
3609  }
3610  }
3611 }
3612 
3613 /* called for every station each tick */
3614 static void StationHandleSmallTick(BaseStation *st)
3615 {
3616  if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
3617 
3618  byte b = st->delete_ctr + 1;
3619  if (b >= STATION_RATING_TICKS) b = 0;
3620  st->delete_ctr = b;
3621 
3622  if (b == 0) UpdateStationRating(Station::From(st));
3623 }
3624 
3625 void OnTick_Station()
3626 {
3627  if (_game_mode == GM_EDITOR) return;
3628 
3629  BaseStation *st;
3630  FOR_ALL_BASE_STATIONS(st) {
3631  StationHandleSmallTick(st);
3632 
3633  /* Clean up the link graph about once a week. */
3634  if (Station::IsExpected(st) && (_tick_counter + st->index) % STATION_LINKGRAPH_TICKS == 0) {
3636  };
3637 
3638  /* Run STATION_ACCEPTANCE_TICKS = 250 tick interval trigger for station animation.
3639  * Station index is included so that triggers are not all done
3640  * at the same time. */
3641  if ((_tick_counter + st->index) % STATION_ACCEPTANCE_TICKS == 0) {
3642  /* Stop processing this station if it was deleted */
3643  if (!StationHandleBigTick(st)) continue;
3644  TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
3645  if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
3646  }
3647  }
3648 }
3649 
3652 {
3653  Station *st;
3654 
3655  FOR_ALL_STATIONS(st) {
3656  for (CargoID i = 0; i < NUM_CARGO; i++) {
3657  GoodsEntry *ge = &st->goods[i];
3660  }
3661  }
3662 }
3663 
3664 
3665 void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
3666 {
3667  Station *st;
3668 
3669  FOR_ALL_STATIONS(st) {
3670  if (st->owner == owner &&
3671  DistanceManhattan(tile, st->xy) <= radius) {
3672  for (CargoID i = 0; i < NUM_CARGO; i++) {
3673  GoodsEntry *ge = &st->goods[i];
3674 
3675  if (ge->status != 0) {
3676  ge->rating = Clamp(ge->rating + amount, 0, 255);
3677  }
3678  }
3679  }
3680  }
3681 }
3682 
3683 static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
3684 {
3685  /* We can't allocate a CargoPacket? Then don't do anything
3686  * at all; i.e. just discard the incoming cargo. */
3687  if (!CargoPacket::CanAllocateItem()) return 0;
3688 
3689  GoodsEntry &ge = st->goods[type];
3690  amount += ge.amount_fract;
3691  ge.amount_fract = GB(amount, 0, 8);
3692 
3693  amount >>= 8;
3694  /* No new "real" cargo item yet. */
3695  if (amount == 0) return 0;
3696 
3697  StationID next = ge.GetVia(st->index);
3698  ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id), next);
3699  LinkGraph *lg = NULL;
3700  if (ge.link_graph == INVALID_LINK_GRAPH) {
3702  lg = new LinkGraph(type);
3704  ge.link_graph = lg->index;
3705  ge.node = lg->AddNode(st);
3706  } else {
3707  DEBUG(misc, 0, "Can't allocate link graph");
3708  }
3709  } else {
3710  lg = LinkGraph::Get(ge.link_graph);
3711  }
3712  if (lg != NULL) (*lg)[ge.node].UpdateSupply(amount);
3713 
3714  if (!ge.HasRating()) {
3717  }
3718 
3720  TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
3721  AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
3722 
3724  st->MarkTilesDirty(true);
3725  return amount;
3726 }
3727 
3728 static bool IsUniqueStationName(const char *name)
3729 {
3730  const Station *st;
3731 
3732  FOR_ALL_STATIONS(st) {
3733  if (st->name != NULL && strcmp(st->name, name) == 0) return false;
3734  }
3735 
3736  return true;
3737 }
3738 
3748 CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
3749 {
3750  Station *st = Station::GetIfValid(p1);
3751  if (st == NULL) return CMD_ERROR;
3752 
3753  CommandCost ret = CheckOwnership(st->owner);
3754  if (ret.Failed()) return ret;
3755 
3756  bool reset = StrEmpty(text);
3757 
3758  if (!reset) {
3760  if (!IsUniqueStationName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
3761  }
3762 
3763  if (flags & DC_EXEC) {
3764  free(st->name);
3765  st->name = reset ? NULL : stredup(text);
3766 
3767  st->UpdateVirtCoord();
3769  }
3770 
3771  return CommandCost();
3772 }
3773 
3780 void FindStationsAroundTiles(const TileArea &location, StationList *stations)
3781 {
3782  /* area to search = producer plus station catchment radius */
3784 
3785  uint x = TileX(location.tile);
3786  uint y = TileY(location.tile);
3787 
3788  uint min_x = (x > max_rad) ? x - max_rad : 0;
3789  uint max_x = x + location.w + max_rad;
3790  uint min_y = (y > max_rad) ? y - max_rad : 0;
3791  uint max_y = y + location.h + max_rad;
3792 
3793  if (min_x == 0 && _settings_game.construction.freeform_edges) min_x = 1;
3794  if (min_y == 0 && _settings_game.construction.freeform_edges) min_y = 1;
3795  if (max_x >= MapSizeX()) max_x = MapSizeX() - 1;
3796  if (max_y >= MapSizeY()) max_y = MapSizeY() - 1;
3797 
3798  for (uint cy = min_y; cy < max_y; cy++) {
3799  for (uint cx = min_x; cx < max_x; cx++) {
3800  TileIndex cur_tile = TileXY(cx, cy);
3801  if (!IsTileType(cur_tile, MP_STATION)) continue;
3802 
3803  Station *st = Station::GetByTile(cur_tile);
3804  /* st can be NULL in case of waypoints */
3805  if (st == NULL) continue;
3806 
3808  int rad = st->GetCatchmentRadius();
3809  int rad_x = cx - x;
3810  int rad_y = cy - y;
3811 
3812  if (rad_x < -rad || rad_x >= rad + location.w) continue;
3813  if (rad_y < -rad || rad_y >= rad + location.h) continue;
3814  }
3815 
3816  /* Insert the station in the set. This will fail if it has
3817  * already been added.
3818  */
3819  stations->Include(st);
3820  }
3821  }
3822 }
3823 
3829 {
3830  if (this->tile != INVALID_TILE) {
3831  FindStationsAroundTiles(*this, &this->stations);
3832  this->tile = INVALID_TILE;
3833  }
3834  return &this->stations;
3835 }
3836 
3837 uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
3838 {
3839  /* Return if nothing to do. Also the rounding below fails for 0. */
3840  if (amount == 0) return 0;
3841 
3842  Station *st1 = NULL; // Station with best rating
3843  Station *st2 = NULL; // Second best station
3844  uint best_rating1 = 0; // rating of st1
3845  uint best_rating2 = 0; // rating of st2
3846 
3847  for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
3848  Station *st = *st_iter;
3849 
3850  /* Is the station reserved exclusively for somebody else? */
3851  if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
3852 
3853  if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
3854 
3855  if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) continue; // Selectively servicing stations, and not this one
3856 
3857  if (IsCargoInClass(type, CC_PASSENGERS)) {
3858  if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
3859  } else {
3860  if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
3861  }
3862 
3863  /* This station can be used, add it to st1/st2 */
3864  if (st1 == NULL || st->goods[type].rating >= best_rating1) {
3865  st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
3866  } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
3867  st2 = st; best_rating2 = st->goods[type].rating;
3868  }
3869  }
3870 
3871  /* no stations around at all? */
3872  if (st1 == NULL) return 0;
3873 
3874  /* From now we'll calculate with fractal cargo amounts.
3875  * First determine how much cargo we really have. */
3876  amount *= best_rating1 + 1;
3877 
3878  if (st2 == NULL) {
3879  /* only one station around */
3880  return UpdateStationWaiting(st1, type, amount, source_type, source_id);
3881  }
3882 
3883  /* several stations around, the best two (highest rating) are in st1 and st2 */
3884  assert(st1 != NULL);
3885  assert(st2 != NULL);
3886  assert(best_rating1 != 0 || best_rating2 != 0);
3887 
3888  /* Then determine the amount the worst station gets. We do it this way as the
3889  * best should get a bonus, which in this case is the rounding difference from
3890  * this calculation. In reality that will mean the bonus will be pretty low.
3891  * Nevertheless, the best station should always get the most cargo regardless
3892  * of rounding issues. */
3893  uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
3894  assert(worst_cargo <= (amount - worst_cargo));
3895 
3896  /* And then send the cargo to the stations! */
3897  uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
3898  /* These two UpdateStationWaiting's can't be in the statement as then the order
3899  * of execution would be undefined and that could cause desyncs with callbacks. */
3900  return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
3901 }
3902 
3903 void BuildOilRig(TileIndex tile)
3904 {
3905  if (!Station::CanAllocateItem()) {
3906  DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
3907  return;
3908  }
3909 
3910  Station *st = new Station(tile);
3911  st->town = ClosestTownFromTile(tile, UINT_MAX);
3912 
3913  st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
3914 
3915  assert(IsTileType(tile, MP_INDUSTRY));
3916  DeleteAnimatedTile(tile);
3917  MakeOilrig(tile, st->index, GetWaterClass(tile));
3918 
3919  st->owner = OWNER_NONE;
3920  st->airport.type = AT_OILRIG;
3921  st->airport.Add(tile);
3922  st->dock_tile = tile;
3924  st->build_date = _date;
3925 
3926  st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
3927 
3928  st->UpdateVirtCoord();
3929  UpdateStationAcceptance(st, false);
3931 }
3932 
3933 void DeleteOilRig(TileIndex tile)
3934 {
3935  Station *st = Station::GetByTile(tile);
3936 
3937  MakeWaterKeepingClass(tile, OWNER_NONE);
3938 
3939  st->dock_tile = INVALID_TILE;
3940  st->airport.Clear();
3941  st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK);
3942  st->airport.flags = 0;
3943 
3944  st->rect.AfterRemoveTile(st, tile);
3945 
3946  st->UpdateVirtCoord();
3948  if (!st->IsInUse()) delete st;
3949 }
3950 
3951 static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
3952 {
3953  if (IsRoadStopTile(tile)) {
3954  for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
3955  /* Update all roadtypes, no matter if they are present */
3956  if (GetRoadOwner(tile, rt) == old_owner) {
3957  if (HasTileRoadType(tile, rt)) {
3958  /* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
3959  Company::Get(old_owner)->infrastructure.road[rt] -= 2;
3960  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2;
3961  }
3962  SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
3963  }
3964  }
3965  }
3966 
3967  if (!IsTileOwner(tile, old_owner)) return;
3968 
3969  if (new_owner != INVALID_OWNER) {
3970  /* Update company infrastructure counts. Only do it here
3971  * if the new owner is valid as otherwise the clear
3972  * command will do it for us. No need to dirty windows
3973  * here, we'll redraw the whole screen anyway.*/
3974  Company *old_company = Company::Get(old_owner);
3975  Company *new_company = Company::Get(new_owner);
3976 
3977  /* Update counts for underlying infrastructure. */
3978  switch (GetStationType(tile)) {
3979  case STATION_RAIL:
3980  case STATION_WAYPOINT:
3981  if (!IsStationTileBlocked(tile)) {
3982  old_company->infrastructure.rail[GetRailType(tile)]--;
3983  new_company->infrastructure.rail[GetRailType(tile)]++;
3984  }
3985  break;
3986 
3987  case STATION_BUS:
3988  case STATION_TRUCK:
3989  /* Road stops were already handled above. */
3990  break;
3991 
3992  case STATION_BUOY:
3993  case STATION_DOCK:
3994  if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
3995  old_company->infrastructure.water--;
3996  new_company->infrastructure.water++;
3997  }
3998  break;
3999 
4000  default:
4001  break;
4002  }
4003 
4004  /* Update station tile count. */
4005  if (!IsBuoy(tile) && !IsAirport(tile)) {
4006  old_company->infrastructure.station--;
4007  new_company->infrastructure.station++;
4008  }
4009 
4010  /* for buoys, owner of tile is owner of water, st->owner == OWNER_NONE */
4011  SetTileOwner(tile, new_owner);
4013  } else {
4014  if (IsDriveThroughStopTile(tile)) {
4015  /* Remove the drive-through road stop */
4016  DoCommand(tile, 1 | 1 << 8, (GetStationType(tile) == STATION_TRUCK) ? ROADSTOP_TRUCK : ROADSTOP_BUS, DC_EXEC | DC_BANKRUPT, CMD_REMOVE_ROAD_STOP);
4017  assert(IsTileType(tile, MP_ROAD));
4018  /* Change owner of tile and all roadtypes */
4019  ChangeTileOwner(tile, old_owner, new_owner);
4020  } else {
4022  /* Set tile owner of water under (now removed) buoy and dock to OWNER_NONE.
4023  * Update owner of buoy if it was not removed (was in orders).
4024  * Do not update when owned by OWNER_WATER (sea and rivers). */
4025  if ((IsTileType(tile, MP_WATER) || IsBuoyTile(tile)) && IsTileOwner(tile, old_owner)) SetTileOwner(tile, OWNER_NONE);
4026  }
4027  }
4028 }
4029 
4039 {
4040  /* Yeah... water can always remove stops, right? */
4041  if (_current_company == OWNER_WATER) return true;
4042 
4043  RoadTypes rts = GetRoadTypes(tile);
4044  if (HasBit(rts, ROADTYPE_TRAM)) {
4045  Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
4046  if (tram_owner != OWNER_NONE && CheckOwnership(tram_owner).Failed()) return false;
4047  }
4048  if (HasBit(rts, ROADTYPE_ROAD)) {
4049  Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
4050  if (road_owner != OWNER_TOWN) {
4051  if (road_owner != OWNER_NONE && CheckOwnership(road_owner).Failed()) return false;
4052  } else {
4053  if (CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags).Failed()) return false;
4054  }
4055  }
4056 
4057  return true;
4058 }
4059 
4067 {
4068  if (flags & DC_AUTO) {
4069  switch (GetStationType(tile)) {
4070  default: break;
4071  case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
4072  case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
4073  case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
4074  case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
4075  case STATION_BUS: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
4076  case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
4077  case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
4078  case STATION_OILRIG:
4079  SetDParam(1, STR_INDUSTRY_NAME_OIL_RIG);
4080  return_cmd_error(STR_ERROR_GENERIC_OBJECT_IN_THE_WAY);
4081  }
4082  }
4083 
4084  switch (GetStationType(tile)) {
4085  case STATION_RAIL: return RemoveRailStation(tile, flags);
4086  case STATION_WAYPOINT: return RemoveRailWaypoint(tile, flags);
4087  case STATION_AIRPORT: return RemoveAirport(tile, flags);
4088  case STATION_TRUCK:
4089  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4090  return_cmd_error(STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
4091  }
4092  return RemoveRoadStop(tile, flags);
4093  case STATION_BUS:
4094  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4095  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
4096  }
4097  return RemoveRoadStop(tile, flags);
4098  case STATION_BUOY: return RemoveBuoy(tile, flags);
4099  case STATION_DOCK: return RemoveDock(tile, flags);
4100  default: break;
4101  }
4102 
4103  return CMD_ERROR;
4104 }
4105 
4106 static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
4107 {
4109  /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
4110  * TTDP does not call it.
4111  */
4112  if (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) {
4113  switch (GetStationType(tile)) {
4114  case STATION_WAYPOINT:
4115  case STATION_RAIL: {
4116  DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
4117  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4118  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4119  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4120  }
4121 
4122  case STATION_AIRPORT:
4123  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4124 
4125  case STATION_TRUCK:
4126  case STATION_BUS: {
4127  DiagDirection direction = GetRoadStopDir(tile);
4128  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4129  if (IsDriveThroughStopTile(tile)) {
4130  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4131  }
4132  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4133  }
4134 
4135  default: break;
4136  }
4137  }
4138  }
4139  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
4140 }
4141 
4147 uint FlowStat::GetShare(StationID st) const
4148 {
4149  uint32 prev = 0;
4150  for (SharesMap::const_iterator it = this->shares.begin(); it != this->shares.end(); ++it) {
4151  if (it->second == st) {
4152  return it->first - prev;
4153  } else {
4154  prev = it->first;
4155  }
4156  }
4157  return 0;
4158 }
4159 
4166 StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const
4167 {
4168  if (this->unrestricted == 0) return INVALID_STATION;
4169  assert(!this->shares.empty());
4170  SharesMap::const_iterator it = this->shares.upper_bound(RandomRange(this->unrestricted));
4171  assert(it != this->shares.end() && it->first <= this->unrestricted);
4172  if (it->second != excluded && it->second != excluded2) return it->second;
4173 
4174  /* We've hit one of the excluded stations.
4175  * Draw another share, from outside its range. */
4176 
4177  uint end = it->first;
4178  uint begin = (it == this->shares.begin() ? 0 : (--it)->first);
4179  uint interval = end - begin;
4180  if (interval >= this->unrestricted) return INVALID_STATION; // Only one station in the map.
4181  uint new_max = this->unrestricted - interval;
4182  uint rand = RandomRange(new_max);
4183  SharesMap::const_iterator it2 = (rand < begin) ? this->shares.upper_bound(rand) :
4184  this->shares.upper_bound(rand + interval);
4185  assert(it2 != this->shares.end() && it2->first <= this->unrestricted);
4186  if (it2->second != excluded && it2->second != excluded2) return it2->second;
4187 
4188  /* We've hit the second excluded station.
4189  * Same as before, only a bit more complicated. */
4190 
4191  uint end2 = it2->first;
4192  uint begin2 = (it2 == this->shares.begin() ? 0 : (--it2)->first);
4193  uint interval2 = end2 - begin2;
4194  if (interval2 >= new_max) return INVALID_STATION; // Only the two excluded stations in the map.
4195  new_max -= interval2;
4196  if (begin > begin2) {
4197  Swap(begin, begin2);
4198  Swap(end, end2);
4199  Swap(interval, interval2);
4200  }
4201  rand = RandomRange(new_max);
4202  SharesMap::const_iterator it3 = this->shares.upper_bound(this->unrestricted);
4203  if (rand < begin) {
4204  it3 = this->shares.upper_bound(rand);
4205  } else if (rand < begin2 - interval) {
4206  it3 = this->shares.upper_bound(rand + interval);
4207  } else {
4208  it3 = this->shares.upper_bound(rand + interval + interval2);
4209  }
4210  assert(it3 != this->shares.end() && it3->first <= this->unrestricted);
4211  return it3->second;
4212 }
4213 
4220 {
4221  assert(!this->shares.empty());
4222  SharesMap new_shares;
4223  uint i = 0;
4224  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4225  new_shares[++i] = it->second;
4226  if (it->first == this->unrestricted) this->unrestricted = i;
4227  }
4228  this->shares.swap(new_shares);
4229  assert(!this->shares.empty() && this->unrestricted <= (--this->shares.end())->first);
4230 }
4231 
4238 void FlowStat::ChangeShare(StationID st, int flow)
4239 {
4240  /* We assert only before changing as afterwards the shares can actually
4241  * be empty. In that case the whole flow stat must be deleted then. */
4242  assert(!this->shares.empty());
4243 
4244  uint removed_shares = 0;
4245  uint added_shares = 0;
4246  uint last_share = 0;
4247  SharesMap new_shares;
4248  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4249  if (it->second == st) {
4250  if (flow < 0) {
4251  uint share = it->first - last_share;
4252  if (flow == INT_MIN || (uint)(-flow) >= share) {
4253  removed_shares += share;
4254  if (it->first <= this->unrestricted) this->unrestricted -= share;
4255  if (flow != INT_MIN) flow += share;
4256  last_share = it->first;
4257  continue; // remove the whole share
4258  }
4259  removed_shares += (uint)(-flow);
4260  } else {
4261  added_shares += (uint)(flow);
4262  }
4263  if (it->first <= this->unrestricted) this->unrestricted += flow;
4264 
4265  /* If we don't continue above the whole flow has been added or
4266  * removed. */
4267  flow = 0;
4268  }
4269  new_shares[it->first + added_shares - removed_shares] = it->second;
4270  last_share = it->first;
4271  }
4272  if (flow > 0) {
4273  new_shares[last_share + (uint)flow] = st;
4274  if (this->unrestricted < last_share) {
4275  this->ReleaseShare(st);
4276  } else {
4277  this->unrestricted += flow;
4278  }
4279  }
4280  this->shares.swap(new_shares);
4281 }
4282 
4288 void FlowStat::RestrictShare(StationID st)
4289 {
4290  assert(!this->shares.empty());
4291  uint flow = 0;
4292  uint last_share = 0;
4293  SharesMap new_shares;
4294  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4295  if (flow == 0) {
4296  if (it->first > this->unrestricted) return; // Not present or already restricted.
4297  if (it->second == st) {
4298  flow = it->first - last_share;
4299  this->unrestricted -= flow;
4300  } else {
4301  new_shares[it->first] = it->second;
4302  }
4303  } else {
4304  new_shares[it->first - flow] = it->second;
4305  }
4306  last_share = it->first;
4307  }
4308  if (flow == 0) return;
4309  new_shares[last_share + flow] = st;
4310  this->shares.swap(new_shares);
4311  assert(!this->shares.empty());
4312 }
4313 
4319 void FlowStat::ReleaseShare(StationID st)
4320 {
4321  assert(!this->shares.empty());
4322  uint flow = 0;
4323  uint next_share = 0;
4324  bool found = false;
4325  for (SharesMap::reverse_iterator it(this->shares.rbegin()); it != this->shares.rend(); ++it) {
4326  if (it->first < this->unrestricted) return; // Note: not <= as the share may hit the limit.
4327  if (found) {
4328  flow = next_share - it->first;
4329  this->unrestricted += flow;
4330  break;
4331  } else {
4332  if (it->first == this->unrestricted) return; // !found -> Limit not hit.
4333  if (it->second == st) found = true;
4334  }
4335  next_share = it->first;
4336  }
4337  if (flow == 0) return;
4338  SharesMap new_shares;
4339  new_shares[flow] = st;
4340  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4341  if (it->second != st) {
4342  new_shares[flow + it->first] = it->second;
4343  } else {
4344  flow = 0;
4345  }
4346  }
4347  this->shares.swap(new_shares);
4348  assert(!this->shares.empty());
4349 }
4350 
4356 void FlowStat::ScaleToMonthly(uint runtime)
4357 {
4358  assert(runtime > 0);
4359  SharesMap new_shares;
4360  uint share = 0;
4361  for (SharesMap::iterator i = this->shares.begin(); i != this->shares.end(); ++i) {
4362  share = max(share + 1, i->first * 30 / runtime);
4363  new_shares[share] = i->second;
4364  if (this->unrestricted == i->first) this->unrestricted = share;
4365  }
4366  this->shares.swap(new_shares);
4367 }
4368 
4375 void FlowStatMap::AddFlow(StationID origin, StationID via, uint flow)
4376 {
4377  FlowStatMap::iterator origin_it = this->find(origin);
4378  if (origin_it == this->end()) {
4379  this->insert(std::make_pair(origin, FlowStat(via, flow)));
4380  } else {
4381  origin_it->second.ChangeShare(via, flow);
4382  assert(!origin_it->second.GetShares()->empty());
4383  }
4384 }
4385 
4394 void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow)
4395 {
4396  FlowStatMap::iterator prev_it = this->find(origin);
4397  if (prev_it == this->end()) {
4398  FlowStat fs(via, flow);
4399  fs.AppendShare(INVALID_STATION, flow);
4400  this->insert(std::make_pair(origin, fs));
4401  } else {
4402  prev_it->second.ChangeShare(via, flow);
4403  prev_it->second.ChangeShare(INVALID_STATION, flow);
4404  assert(!prev_it->second.GetShares()->empty());
4405  }
4406 }
4407 
4413 {
4414  for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
4415  FlowStat &fs = i->second;
4416  uint local = fs.GetShare(INVALID_STATION);
4417  if (local > INT_MAX) { // make sure it fits in an int
4418  fs.ChangeShare(self, -INT_MAX);
4419  fs.ChangeShare(INVALID_STATION, -INT_MAX);
4420  local -= INT_MAX;
4421  }
4422  fs.ChangeShare(self, -(int)local);
4423  fs.ChangeShare(INVALID_STATION, -(int)local);
4424 
4425  /* If the local share is used up there must be a share for some
4426  * remote station. */
4427  assert(!fs.GetShares()->empty());
4428  }
4429 }
4430 
4438 {
4439  StationIDStack ret;
4440  for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
4441  FlowStat &s_flows = f_it->second;
4442  s_flows.ChangeShare(via, INT_MIN);
4443  if (s_flows.GetShares()->empty()) {
4444  ret.Push(f_it->first);
4445  this->erase(f_it++);
4446  } else {
4447  ++f_it;
4448  }
4449  }
4450  return ret;
4451 }
4452 
4457 void FlowStatMap::RestrictFlows(StationID via)
4458 {
4459  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4460  it->second.RestrictShare(via);
4461  }
4462 }
4463 
4468 void FlowStatMap::ReleaseFlows(StationID via)
4469 {
4470  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4471  it->second.ReleaseShare(via);
4472  }
4473 }
4474 
4480 {
4481  uint ret = 0;
4482  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4483  ret += (--(i->second.GetShares()->end()))->first;
4484  }
4485  return ret;
4486 }
4487 
4493 uint FlowStatMap::GetFlowVia(StationID via) const
4494 {
4495  uint ret = 0;
4496  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4497  ret += i->second.GetShare(via);
4498  }
4499  return ret;
4500 }
4501 
4507 uint FlowStatMap::GetFlowFrom(StationID from) const
4508 {
4509  FlowStatMap::const_iterator i = this->find(from);
4510  if (i == this->end()) return 0;
4511  return (--(i->second.GetShares()->end()))->first;
4512 }
4513 
4520 uint FlowStatMap::GetFlowFromVia(StationID from, StationID via) const
4521 {
4522  FlowStatMap::const_iterator i = this->find(from);
4523  if (i == this->end()) return 0;
4524  return i->second.GetShare(via);
4525 }
4526 
4527 extern const TileTypeProcs _tile_type_station_procs = {
4528  DrawTile_Station, // draw_tile_proc
4529  GetSlopePixelZ_Station, // get_slope_z_proc
4530  ClearTile_Station, // clear_tile_proc
4531  NULL, // add_accepted_cargo_proc
4532  GetTileDesc_Station, // get_tile_desc_proc
4533  GetTileTrackStatus_Station, // get_tile_track_status_proc
4534  ClickTile_Station, // click_tile_proc
4535  AnimateTile_Station, // animate_tile_proc
4536  TileLoop_Station, // tile_loop_proc
4537  ChangeTileOwner_Station, // change_tile_owner_proc
4538  NULL, // add_produced_cargo_proc
4539  VehicleEnter_Station, // vehicle_enter_tile_proc
4540  GetFoundation_Station, // get_foundation_proc
4541  TerraformTile_Station, // terraform_tile_proc
4542 };
Functions related to OTTD&#39;s strings.
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
List of scheduled road vehs button.
Road vehicle states.
don&#39;t allow building on structures
Definition: command_type.h:346
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:397
void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner)
Change the owner of a tile.
Definition: landscape.cpp:602
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:326
Functions/types related to NewGRF debugging.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:277
byte type
Type of this airport,.
Definition: station_base.h:309
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
static void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d, WaterClass wc)
Make the given tile a dock tile.
Definition: station_map.h:651
void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
Add track to signal update buffer.
Definition: signal.cpp:582
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:309
byte state
Definition: roadveh.h:89
static uint MapSizeX()
Get the size of the map along the X.
Definition: map_func.h:74
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
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:257
NodeID AddNode(const Station *st)
Add a node to the component and create empty edges associated with it.
Definition: linkgraph.cpp:157
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:482
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition: industrytype.h:137
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:298
static TropicZone GetTropicZone(TileIndex tile)
Get the tropic zone.
Definition: tile_map.h:240
Select station (when joining stations); Window numbers:
Definition: window_type.h:237
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
static void SetAnimationFrame(TileIndex t, byte frame)
Set a new animation frame.
Definition: tile_map.h:264
A standard stop for trucks.
Definition: station_type.h:49
static const uint COMPRESSION_INTERVAL
Minimum number of days between subsequent compressions of a LG.
Definition: linkgraph.h:445
static uint MapSizeY()
Get the size of the map along the Y.
Definition: map_func.h:84
static bool IsCustomStationSpecIndex(TileIndex t)
Is there a custom rail station spec on this tile?
Definition: station_map.h:470
Rect GetCatchmentRect() const
Determines catchment rectangle of this station.
Definition: station.cpp:291
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:200
Tile information, used while rendering the tile.
Definition: tile_cmd.h:44
TileArea bus_station
Tile area the bus &#39;station&#39; part covers.
Definition: station_base.h:456
CompanyMask statues
which companies have a statue?
Definition: town.h:70
Definition of link refreshing utility.
StationID targetairport
Airport to go to next.
Definition: aircraft.h:80
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.
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, DoCommandFlag flags, bool town_check)
Is it allowed to remove the given road bits from the given tile?
Definition: road_cmd.cpp:116
const AirportFTAClass * GetAirport(const byte airport_type)
Get the finite state machine of an airport type.
Definition: airport.cpp:209
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:1153
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3179
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:55
void AddAnimatedTile(TileIndex tile)
Add the given tile to the animated tile table (if it does not exist on that table yet)...
DirectionByte direction
facing
Definition: vehicle_base.h:271
byte size_y
size of airport in y direction
Iterator to iterate over all tiles belonging to an airport.
Definition: station_base.h:512
company buildings - depots, stations, HQ, ...
Definition: transparency.h:29
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:29
Base class for roadstops.
Non-existing type of vehicle.
Definition: vehicle_type.h:37
static bool IsReversingRoadTrackdir(Trackdir dir)
Checks whether the trackdir means that we are reversing.
Definition: track_func.h:683
Tile is desert.
Definition: tile_type.h:73
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:105
bool HasVehicleEverTriedLoading() const
Reports whether a vehicle has ever tried to load the cargo at this station.
Definition: station_base.h:267
uint16 triggers
The triggers that trigger animation.
East.
virtual void UpdateVirtCoord()=0
Update the coordinated of the sign (as shown in the viewport).
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:93
Part of an industry.
Definition: tile_type.h:51
EconomySettings economy
settings to change the economy
static RoadBits GetAllRoadBits(TileIndex tile)
Get all set RoadBits on the given tile.
Definition: road_map.h:139
static RoadStopType GetRoadStopType(TileIndex t)
Get the road stop type of this tile.
Definition: station_map.h:57
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition: vehicle.cpp:539
Flag for an invalid DiagDirection.
int32 TileIndexDiff
An offset value between to tiles.
Definition: map_func.h:156
static bool IsWater(TileIndex t)
Is it a plain water tile?
Definition: water_map.h:141
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:246
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:63
uint GetSpecCount() const
Get the number of allocated specs within the class.
Definition: newgrf_class.h:46
CompanyByte exclusivity
which company has exclusivity
Definition: town.h:75
static const AirportTileSpec * GetByTile(TileIndex tile)
Retrieve airport tile spec for the given airport tile.
Basic road type.
Definition: road_type.h:24
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:252
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.
Functions related to debugging.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
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...
Track
These are used to specify a single track.
Definition: track_type.h:21
Can planes land on this airport type?
Definition: airport.h:148
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
A tile with road (or tram tracks)
Definition: tile_type.h:45
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
bool distant_join_stations
allow to join non-adjacent stations
static TrackBits AxisToTrackBits(Axis a)
Maps an Axis to the corresponding TrackBits value.
Definition: track_func.h:98
Depot view; Window numbers:
Definition: window_type.h:346
Slope tileh
Slope of the tile.
Definition: tile_cmd.h:47
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
Full road along the x-axis (south-west + north-east)
Definition: road_type.h:61
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.
Used for iterations.
Definition: road_type.h:26
Specification of a cargo type.
Definition: cargotype.h:56
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...
TileIndex dock_tile
The location of the dock.
Definition: station_base.h:461
IndustryLifeType life_type
This is also known as Industry production flag, in newgrf specs.
Definition: industrytype.h:120
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:237
bool ValParamRailtype(const RailType rail)
Validate functions for rail building.
Definition: rail.cpp:208
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:64
static bool IsRoadStop(TileIndex t)
Is the station at t a road station?
Definition: station_map.h:203
Transport over water.
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:76
Set when cargo was delivered for final delivery this month.
Definition: station_base.h:205
Manual distribution. No link graph calculations are run.
static const uint INVALID_AIRPORTTILE
id for an invalid airport tile
Definition: airport.h:27
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:430
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:207
A standard stop for buses.
Definition: station_type.h:48
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:212
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:663
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:162
StationIDStack DeleteFlows(StationID via)
Delete all flows at a station for specific cargo and destination.
static bool HasTileRoadType(TileIndex t, RoadType rt)
Check if a tile has a specific road type.
Definition: road_map.h:188
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:41
const T * Begin() const
Get the pointer to the first item (const)
Tile description for the &#39;land area information&#39; tool.
Definition: tile_cmd.h:53
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2174
demolish a tile
Definition: command_type.h:182
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:147
Vehicle is flying in the air.
Definition: airport.h:77
static RoadBits GetRoadBits(TileIndex t, RoadType rt)
Get the present road bits for a specific road type.
Definition: road_map.h:111
#define FOR_EACH_SET_ROADTYPE(var, road_types)
Iterate through each set RoadType in a RoadTypes value.
Definition: road_func.h:28
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:245
Northeast, upper right on your monitor.
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:38
T * First() const
Get the first vehicle in the chain.
static void FreeTrainReservation(Train *v)
Clear platform reservation during station building/removing.
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:18
Simple vector template class.
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition: station.cpp:200
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:76
static Track GetRailStationTrack(TileIndex t)
Get the rail track of a rail station tile.
Definition: station_map.h:350
CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
Find a nearby station that joins this station.
uint32 station
Count of company owned station tiles.
Definition: company_base.h:36
#define FOR_EACH_SET_BIT(bitpos_var, bitset_value)
Do an operation for each set set bit in a value.
#define AllocaM(T, num_elements)
alloca() has to be called in the parent function, so define AllocaM() as a macro
Definition: alloc_func.hpp:134
Common return value for all commands.
Definition: command_type.h:25
static bool IsStandardRoadStopTile(TileIndex t)
Is tile t a standard (non-drive through) road stop station?
Definition: station_map.h:224
Used for iterations.
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:751
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:26
uint16 classes
Classes of this cargo type.
Definition: cargotype.h:79
static bool IsDriveThroughStopTile(TileIndex t)
Is tile t a drive through road stop station?
Definition: station_map.h:234
Town * town
The town this station is associated with.
bool HasRating() const
Does this cargo have a rating at this station?
Definition: station_base.h:273
byte vehstatus
Status.
Definition: vehicle_base.h:317
Vehicle * GetFirstSharedVehicle() const
Get the first vehicle of this vehicle chain.
Definition: order_base.h:337
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:449
uint GetFlowFrom(StationID from) const
Get the sum of flows from a specific station from this FlowStatMap.
uint tiles
Number of tile layouts.
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition: cargopacket.h:366
uint16 w
The width of the area.
Definition: tilearea_type.h:20
static RoadVehicle * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Mail.
Definition: cargotype.h:41
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition: tile_map.cpp:102
void Clear()
Clears the &#39;tile area&#39;, i.e.
Definition: tilearea_type.h:40
Determine whether a newstation should be made available to build.
The vehicle entered a station.
Definition: tile_cmd.h:37
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:68
const T * End() const
Get the pointer behind the last valid item (const)
Waypoint class.
uint16 noise_reached
level of noise that all the airports are generating
Definition: town.h:68
a flat tile
Definition: slope_type.h:51
uint16 rail_speed
Speed limit of rail (bridges and track)
Definition: tile_cmd.h:66
byte nof_depots
the number of hangar tiles in this airport
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow. ...
Definition: aircraft.h:123
int z
Height.
Definition: tile_cmd.h:49
static StationType GetStationType(TileIndex t)
Get the station type of this tile.
Definition: station_map.h:45
StationSettings station
settings related to station management
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:472
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
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:83
RoadStopType
Types of RoadStops.
Definition: station_type.h:47
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition: landscape.cpp:472
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:64
Owner owner[4]
Name of the owner(s)
Definition: tile_cmd.h:55
Direction
Defines the 8 directions on the map.
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:494
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition: sprite.h:62
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:644
static Station * From(BaseStation *st)
Converts a BaseStation to SpecializedStation with type checking.
static uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Definition: math_func.hpp:184
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:118
CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
Clear a single tile of a station.
uint32 free_names
Current bitset of free names (we can remove names).
T * Append(uint to_add=1)
Append an item and return it.
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 NULL, end of list.
Definition: order_base.h:51
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:123
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:351
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:40
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:136
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:259
Right track.
Definition: track_type.h:48
bool freeform_edges
allow terraforming the tiles at the map edges
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:70
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:61
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:163
SpriteID single_y
single piece of rail in Y direction, without ground
Definition: rail.h:129
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:761
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:3297
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:379
Station is a waypoint.
Definition: station_type.h:60
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:41
Buses, trucks and trams belong to this class.
Definition: roadveh.h:88
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:2267
static bool IsTileOwner(TileIndex tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:216
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:252
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:3329
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:101
Maximal number of airports in total.
Definition: airport.h:43
Aircraft vehicle type.
Definition: vehicle_type.h:29
Tile animation!
byte noise_level
noise that this airport generates
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.
struct RailtypeInfo::@40 strings
Strings associated with the rail type.
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.
uint x
X position of the tile in unit coordinates.
Definition: tile_cmd.h:45
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:499
None of the directions are disallowed.
Definition: road_map.h:256
byte rating
Station rating for this cargo.
Definition: station_base.h:235
static TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:343
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:403
Foundation
Enumeration for Foundations.
Definition: slope_type.h:95
TileIndex xy
town center tile
Definition: town.h:56
static void SetStationTileRandomBits(TileIndex t, byte random_bits)
Set the random bits for a station tile.
Definition: station_map.h:506
static bool IsBuoy(TileIndex t)
Is tile t a buoy tile?
Definition: station_map.h:307
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:152
All possible tracks.
Definition: track_type.h:56
Triggered when the airport is built (for all tiles at the same time).
CommandCost RemoveFromRailBaseStation(TileArea ta, SmallVector< T *, 4 > &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
Remove a number of tiles from any rail station within the area.
static void MakeAirport(TileIndex t, Owner o, StationID sid, byte section, WaterClass wc)
Make the given tile an airport tile.
Definition: station_map.h:624
void UpdateVirtCoord()
Update the virtual coords needed to draw the station sign.
TileIndex tile
Tile index.
Definition: tile_cmd.h:48
AirportClassID cls_id
the class to which this airport type belongs
Updatable node class.
Definition: linkgraph.h:374
static uint ApplyPixelFoundationToSlope(Foundation f, Slope *s)
Applies a foundation to a slope.
Definition: landscape.h:131
Track along the y-axis (north-west to south-east)
Definition: track_type.h:24
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:440
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:457
This indicates whether a cargo has a rating at the station.
Definition: station_base.h:187
uint Length() const
Get the number of items in the list.
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:45
static int CountMapSquareAround(TileIndex tile, CMSAMatcher cmp)
Counts the numbers of tiles matching a specific type in the area around.
static Owner GetRoadOwner(TileIndex t, RoadType rt)
Get the owner of a specific road type.
Definition: road_map.h:199
StringID owner_type[4]
Type of each owner.
Definition: tile_cmd.h:56
void ClearDriveThrough()
Prepare for removal of this stop; update other neighbouring stops if needed.
Definition: roadstop.cpp:132
The tile is leveled up to a flat slope.
Definition: slope_type.h:97
LinkGraphID link_graph
Link graph this station belongs to.
Definition: station_base.h:257
West.
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:394
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:103
X-axis track.
Definition: track_type.h:43
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:60
#define FIND_FIRST_BIT(x)
Returns the first non-zero bit in a 6-bit value (from right).
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:81
static void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
Set the owner of a specific road type.
Definition: road_map.h:220
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:49
Images for overlaying track.
Definition: rail.h:43
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:181
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:191
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:258
bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts)
Finds out, whether given company has all given RoadTypes available.
Definition: road.cpp:110
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:63
TileArea truck_station
Tile area the truck &#39;station&#39; part covers.
Definition: station_base.h:458
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:180
struct RailtypeInfo::@37 base_sprites
Struct containing the main sprites.
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:343
bool Intersects(const OrthogonalTileArea &ta) const
Does this tile area intersect with another?
Definition: tilearea.cpp:77
Southeast.
Southwest.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
Station with truck stops.
Definition: station_type.h:56
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
byte status
Status of this cargo, see GoodsEntryStatus.
Definition: station_base.h:226
Piece of rail in X direction.
Definition: rail.h:62
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:152
&#39;Close airport&#39; button.
Container for cargo from the same location and time.
Definition: cargopacket.h:44
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:147
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.
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:32
static TrackBits GetRailReservationTrackBits(TileIndex t)
Returns the reserved track bits of the tile.
Definition: rail_map.h:195
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.
uint32 road[ROADTYPE_END]
Count of company owned track bits for each road type.
Definition: company_base.h:32
A number of safeguards to prevent using unsafe methods.
Trams.
Definition: road_type.h:25
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:28
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:260
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:129
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:170
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:39
Water tile.
Definition: tile_type.h:49
static Axis GetRailStationAxis(TileIndex t)
Get the rail direction of a rail station.
Definition: station_map.h:338
uint y
Y position of the tile in unit coordinates.
Definition: tile_cmd.h:46
struct RoadStop * next
Next stop of the given type at this station.
Definition: roadstop_base.h:71
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:46
uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, TileIterator &it, TileIndex town_tile)
Get a possible noise reduction factor based on distance from town center.
RoadBits
Enumeration for the road parts on a tile.
Definition: road_type.h:55
uint8 callback_mask
Bitmask of cargo callbacks that have to be called.
Definition: cargotype.h:69
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:74
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:1099
uint GetCatchmentRadius() const
Determines the catchment radius of the station.
Definition: station.cpp:268
static const uint MIN_TIMEOUT_DISTANCE
Minimum effective distance for timeout calculation.
Definition: linkgraph.h:442
TileArea location
Location of the industry.
Definition: industry.h:42
byte num_table
number of elements in the table
Used for iterations.
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:74
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:305
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:18
Train * GetTrainForReservation(TileIndex tile, Track track)
Find the train which has reserved a specific path.
Definition: pbs.cpp:333
No road-part is build.
Definition: road_type.h:56
static bool IsBuoyTile(TileIndex t)
Is tile t a buoy tile?
Definition: station_map.h:317
Represents the covered area of e.g.
Definition: tilearea_type.h:18
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
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:158
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:883
bool road_stop_on_town_road
allow building of drive-through road stops on town owned roads
Trigger station on new cargo arrival.
void RecomputeIndustriesNear()
Recomputes Station::industries_near, list of industries possibly accepting cargo in station&#39;s catchme...
Definition: station.cpp:354
uint16 max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:222
Order * GetFirstOrder() const
Get the first order of the order chain.
Definition: order_base.h:290
Map accessor functions for bridges.
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:498
Set when a sprite originates from an Action 1.
Definition: sprites.h:1511
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
Defines the data structure for constructing industry.
Definition: industrytype.h:103
StationSpecList * speclist
List of station specs of this station.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
void Push(const Titem &item)
Pushes a new item onto the stack if there is still space in the underlying pool.
static uint GetMinimalAirportDistanceToTile(TileIterator &it, TileIndex town_tile)
Computes the minimal distance from town&#39;s xy to any airport&#39;s tile.
Base class for tile iterators.
Definition: tilearea_type.h:99
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:34
The tile has no ownership.
Definition: company_type.h:27
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:1785
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:340
CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Build a dock/haven.
Date LastRestrictedUpdate() const
Get the date of the last update to the edge&#39;s restricted capacity.
Definition: linkgraph.h:111
StationRect - used to track station spread out rectangle - cheaper than scanning whole map...
Bit value for coloured news.
Definition: news_type.h:73
SpriteID single_x
single piece of rail in X direction, without ground
Definition: rail.h:128
Called when building a station to customize the tile layout.
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...
StationFacilityByte facilities
The facilities that this station has.
void AddFlow(StationID origin, StationID via, uint amount)
Add some flow from "origin", going via "via".
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
DiagDirection
Enumeration for diagonal directions.
Catchment for all stations with "modified catchment" disabled.
Definition: station_type.h:87
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
byte last_speed
Maximum speed (up to 255) of the last vehicle that tried to load this cargo.
Definition: station_base.h:246
Road vehicle type.
Definition: vehicle_type.h:27
uint8 cached_anim_triggers
NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen...
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
Types related to the station widgets.
static Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition: slope_func.h:371
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:91
StringID railtype
Type of rail on the tile.
Definition: tile_cmd.h:65
StringID airport_tile_name
Name of the airport tile.
Definition: tile_cmd.h:62
RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge_entrance)
Returns the RoadBits on an arbitrary tile Special behaviour:
Definition: road_map.cpp:35
static bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:150
Piece of rail in Y direction.
Definition: rail.h:63
Station with a dock.
Definition: station_type.h:59
uint16 refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:308
static DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition: slope_func.h:241
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:61
An updatable edge class.
Definition: linkgraph.h:293
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:18
static bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition: autoslope.h:46
uint DistanceFromEdge(TileIndex tile)
Param the minimum distance to an edge.
Definition: map.cpp:219
static TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition: track_func.h:398
bool build_on_slopes
allow building on slopes
Date LastCompression() const
Get date of last compression.
Definition: linkgraph.h:505
bool Failed() const
Did this command fail?
Definition: command_type.h:161
StringID station_name
Type of station within the class.
Definition: tile_cmd.h:59
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:69
DirectionByte rotation
How this airport is rotated.
Definition: station_base.h:311
All ships have this type.
Definition: ship.h:28
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition: road_type.h:36
Date LastUpdate() const
Get the date of the last update to any part of the edge&#39;s capacity.
Definition: linkgraph.h:117
RoadStop * bus_stops
All the road stops.
Definition: station_base.h:455
uint16 MaxTownNoise() const
Calculate the max town noise.
Definition: town.h:122
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:654
static Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition: track_func.h:257
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:35
byte state
State of the airport.
Definition: aircraft.h:81
uint Truncate(uint max_move=UINT_MAX, StationCargoAmountMap *cargo_per_source=NULL)
Truncates where each destination loses roughly the same percentage of its cargo.
#define FOR_ALL_SHIPS(var)
Iterate over all ships.
Definition: ship.h:66
void DrawRoadCatenary(const TileInfo *ti, RoadBits tram)
Draws the catenary for the given tile.
Definition: road_cmd.cpp:1198
Station list; Window numbers:
Definition: window_type.h:297
Ship vehicle type.
Definition: vehicle_type.h:28
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
static bool HasSignals(TileIndex t)
Checks if a rail tile has signals.
Definition: rail_map.h:73
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:116
CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
Find a nearby waypoint that joins this waypoint.
bool Enter(RoadVehicle *rv)
Enter the road stop.
Definition: roadstop.cpp:235
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:36
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:88
uint8 FindFirstBit(uint32 x)
Search the first set bit in a 32 bit variable.
SourceType
Types of cargo source and destination.
Definition: cargo_type.h:148
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:19
byte flags
Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size...
OwnerByte owner
The owner of this station.
uint16 _tick_counter
Ever incrementing (and sometimes wrapping) tick counter for setting off various events.
Definition: date.cpp:30
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:59
static TrackBits GetTrackBits(TileIndex tile)
Gets the track bits of the given tile.
Definition: rail_map.h:137
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:130
The X axis.
uint32 rail[RAILTYPE_END]
Count of company owned track bits for each rail type.
Definition: company_base.h:34
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1143
void ReleaseShare(StationID st)
Release ("unrestrict") a flow by moving it to the begin of the map and increasing the amount of unres...
Construction costs.
Definition: economy_type.h:151
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:232
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:345
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:87
uint GetHangarNum(TileIndex tile) const
Get the hangar number of the hangar at a specific tile.
Definition: station_base.h:403
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:3283
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:29
Tile got trees.
Definition: tile_type.h:47
List of scheduled ships button.
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:61
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:94
StationType
Station types.
Definition: station_type.h:35
this bit is set when a recolouring process is in action
Definition: sprites.h:1514
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:83
static bool IsNormalRoadTile(TileIndex t)
Return whether a tile is a normal road tile.
Definition: road_map.h:57
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:28
Header file for NewGRF stations.
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:4012
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:96
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:141
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:3193
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
Upper track.
Definition: track_type.h:45
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:19
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
void StationMonthlyLoop()
Monthly loop for stations.
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition: tile_map.cpp:143
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:312
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:118
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
Set of callback functions for performing tile operations of a given tile type.
Definition: tile_cmd.h:144
T * Last()
Get the last vehicle in the chain.
Oilrig airport.
Definition: airport.h:40
size_t MapSize() const
Count the number of ranges with equal keys in this MultiMap.
Definition: multimap.hpp:352
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1574
Use different sprite set for ground sprites.
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:159
Cargo support for NewGRFs.
Town * AirportGetNearestTown(const AirportSpec *as, const TileIterator &it)
Finds the town nearest to given airport.
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...
A town owns the tile, or a town is expanding.
Definition: company_type.h:26
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.
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=NULL)
Add a new newsitem to be shown.
Definition: news_gui.cpp:654
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:581
StringID name
name of this airport
Extended foundation block instead of simple.
bool modified_catchment
different-size catchment areas
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:192
static Money RailBuildCost(RailType railtype)
Returns the cost of building the specified railtype.
Definition: rail.h:346
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:28
AnimationInfo animation
Information about the animation.
uint16 SourceID
Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
Definition: cargo_type.h:155
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:217
Sprites to use and how to display them for station tiles.
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:65
Bit sets of the above specified bits.
Definition: tile_cmd.h:36
byte town_council_tolerance
minimum required town ratings to be allowed to demolish stuff
Definition: settings_type.h:71
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:111
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
void GetTileArea(TileArea *ta, StationType type) const
Get the tile area for a given station type.
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:2236
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:61
A type of cargo is (no longer) accepted.
Definition: news_type.h:36
static bool IsOilRig(TileIndex t)
Is tile t part of an oilrig?
Definition: station_map.h:275
Slope
Enumeration for the slope-type.
Definition: slope_type.h:50
Town view; Window numbers:
Definition: window_type.h:328
A tile of a station.
Definition: tile_type.h:48
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition: elrail.cpp:564
static void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d)
Make the given tile a roadstop tile.
Definition: station_map.h:589
bool Include(const T &item)
Tests whether a item is present in the vector, and appends it to the end if not.
void Erase(T *item)
Removes given item from this vector.
Town data structure.
Definition: town.h:55
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific 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:59
Main group of ground images.
Definition: rail.h:44
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:76
Station with train station.
Definition: station_type.h:55
TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
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:36
uint GetRailtypeSpriteOffset() const
Offset between the current railtype and normal rail.
Definition: rail.h:286
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:114
void OffsetGroundSprite(int x, int y)
Called when a foundation has been drawn for the current tile.
Definition: viewport.cpp:582
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.
No roadtypes.
Definition: road_type.h:37
Coordinates of a point in 2D.
remove a single rail track
Definition: command_type.h:181
A Stop for a Road Vehicle.
Definition: roadstop_base.h:24
void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy)
Called when new facility is built on the station.
Definition: station.cpp:184
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:89
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:570
byte GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:646
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
#define FOR_ALL_AIRCRAFT(var)
Macro for iterating over all aircraft.
Definition: aircraft.h:144
static bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition: elrail_func.h:32
Date build_date
Date of construction of tile contents.
Definition: tile_cmd.h:57
static bool IsRoadStopTile(TileIndex t)
Is tile t a road stop station?
Definition: station_map.h:214
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 CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, SmallVector< Train *, 4 > &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.
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:57
static void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram)
Make a normal road tile.
Definition: road_map.h:554
ConstructionSettings construction
construction of things in-game
static TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition: map_func.h:181
Base of all industries.
static DisallowedRoadDirections GetDisallowedRoadDirections(TileIndex t)
Gets the disallowed directions.
Definition: road_map.h:271
const char * GetName() const
Get the name of this grf.
static RoadTypes GetRoadTypes(TileIndex t)
Get the present road types of a tile.
Definition: road_map.h:166
Functions related to waypoints.
StationClassID
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
Airport airport
Tile area the airport covers.
Definition: station_base.h:460
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:33
StringID name
Name of this rail type.
Definition: rail.h:167
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:61
static TileIndexDiffC GetDockOffset(TileIndex t)
Get the tileoffset from this tile a ship should target to get to this dock.
Definition: station_map.h:444
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:92
StringID str
Description of the tile.
Definition: tile_cmd.h:54
StringID station_name
Default name for nearby station.
Definition: industrytype.h:129
static bool IsHangarTile(TileIndex t)
Is tile t an hangar tile?
Definition: station_map.h:327
Passengers.
Definition: cargotype.h:40
const Tcont * Packets() const
Returns a pointer to the cargo packet list (so you can iterate over it etc).
Definition: cargopacket.h:261
remove a (rectangle of) tiles from a rail station
Definition: command_type.h:192
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 TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:329
#define FOR_ALL_VEHICLES(var)
Iterate over all vehicles.
Definition: vehicle_base.h:987
StringID station_class
Class of station.
Definition: tile_cmd.h:58
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:85
byte disallowed_lengths
Bitmask of platform lengths available for the station.
Base of the town class.
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)
No track build.
Definition: track_type.h:107
static const uint NEW_AIRPORTTILE_OFFSET
offset of first newgrf airport tile
Definition: airport.h:26
uint AvailableCount() const
Returns sum of cargo still available for loading at the sation.
Definition: cargopacket.h:522
void UpdateAirplanesOnNewStation(const Station *st)
Updates the status of the Aircraft heading or in the station.
Specification of a rectangle with absolute coordinates of all edges.
A house by a town.
Definition: tile_type.h:46
Full road along the y-axis (north-west + south-east)
Definition: road_type.h:62
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
IndustryType indtype
Industry type to get the name from.
Definition: station_base.h:463
Left track.
Definition: track_type.h:47
Flag for invalid railtype.
Definition: rail_type.h:36
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:112
NewGRFSpriteLayout * renderdata
Array of tile layouts.
Small news item. (Information window with text and viewport)
Definition: news_type.h:79
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:663
Owner
Enum for all companies/owners.
Definition: company_type.h:20
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.
Maximum catchment for airports with "modified catchment" enabled.
Definition: station_type.h:89
Defines the data structure for an airport.
Track along the x-axis (north-east to south-west)
Definition: track_type.h:23
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:324
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:22
#define TILE_ADD(x, y)
Adds to tiles together.
Definition: map_func.h:246
StationGfx GetTranslatedAirportTileID(StationGfx gfx)
Do airporttile gfx ID translation for NewGRFs.
static void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadTypes rt, Axis a)
Make the given tile a drivethrough roadstop tile.
Definition: station_map.h:608
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:25
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:60
Functions related to news.
void FindStationsAroundTiles(const TileArea &location, StationList *stations)
Find all stations around a rectangular producer (industry, house, headquarter, ...)
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:226
static bool IsDock(TileIndex t)
Is tile t a dock tile?
Definition: station_map.h:286
static Station * Get(size_t index)
Gets station with given index.
Date _date
Current date in days (day counter)
Definition: date.cpp:28
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:2674
char * name
Custom name.
uint16 h
The height of the area.
Definition: tilearea_type.h:21
Triggered when new cargo arrives at the station (for all tiles at the same time). ...
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:100
StringID string_id
Default name (town area) of station.
The tile/execution is done by "water".
Definition: company_type.h:28
remove a (rectangle of) tiles from a rail waypoint
Definition: command_type.h:197
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:56
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:87
Base class for all station-ish types.
Station data structure.
Definition: station_base.h:446
No track.
Definition: track_type.h:42
static const int STATION_ACCEPTANCE_TICKS
cycle duration for updating station acceptance
Definition: date_type.h:35
Axis
Allow incrementing of DiagDirDiff variables.
remove a road stop
Definition: command_type.h:200
static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
Find a nearby station that joins this station.
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:53
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadTypes rts)
Checks if a road stop can be built at the given tile.
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:159
Station with an airport.
Definition: station_type.h:58
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition: map_func.h:165
Train is slowing down.
Definition: vehicle_base.h:36
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:833
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:116
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:318
Y-axis track.
Definition: track_type.h:44
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition: roadstop.cpp:268
Date build_date
Date of construction.
An invalid owner.
Definition: company_type.h:31
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:3279
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:306
Train vehicle type.
Definition: vehicle_type.h:26
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:201
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:473
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:26
uint32 water
Count of company owned track bits for canals.
Definition: company_base.h:35
StringID name
Name of this class.
Definition: newgrf_class.h:41
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.