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 
724 {
725  this->UpdateVirtCoord();
726  this->RecomputeIndustriesNear();
728  if (adding) InvalidateWindowData(WC_STATION_LIST, this->owner, 0);
729 
730  switch (type) {
731  case STATION_RAIL:
733  break;
734  case STATION_AIRPORT:
735  break;
736  case STATION_TRUCK:
737  case STATION_BUS:
739  break;
740  case STATION_DOCK:
742  break;
743  default: NOT_REACHED();
744  }
745 
746  if (adding) {
747  UpdateStationAcceptance(this, false);
749  } else {
750  DeleteStationIfEmpty(this);
751  }
752 
753 }
754 
756 
766 CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z, bool allow_steep, bool check_bridge = true)
767 {
768  if (check_bridge && IsBridgeAbove(tile)) {
769  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
770  }
771 
773  if (ret.Failed()) return ret;
774 
775  int z;
776  Slope tileh = GetTileSlope(tile, &z);
777 
778  /* Prohibit building if
779  * 1) The tile is "steep" (i.e. stretches two height levels).
780  * 2) The tile is non-flat and the build_on_slopes switch is disabled.
781  */
782  if ((!allow_steep && IsSteepSlope(tileh)) ||
784  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
785  }
786 
788  int flat_z = z + GetSlopeMaxZ(tileh);
789  if (tileh != SLOPE_FLAT) {
790  /* Forbid building if the tile faces a slope in a invalid direction. */
791  for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
792  if (HasBit(invalid_dirs, dir) && !CanBuildDepotByTileh(dir, tileh)) {
793  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
794  }
795  }
796  cost.AddCost(_price[PR_BUILD_FOUNDATION]);
797  }
798 
799  /* The level of this tile must be equal to allowed_z. */
800  if (allowed_z < 0) {
801  /* First tile. */
802  allowed_z = flat_z;
803  } else if (allowed_z != flat_z) {
804  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
805  }
806 
807  return cost;
808 }
809 
817 {
819  int allowed_z = -1;
820 
821  for (; tile_iter != INVALID_TILE; ++tile_iter) {
822  CommandCost ret = CheckBuildableTile(tile_iter, 0, allowed_z, true);
823  if (ret.Failed()) return ret;
824  cost.AddCost(ret);
825 
826  ret = DoCommand(tile_iter, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
827  if (ret.Failed()) return ret;
828  cost.AddCost(ret);
829  }
830 
831  return cost;
832 }
833 
848 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)
849 {
851  int allowed_z = -1;
852  uint invalid_dirs = 5 << axis;
853 
854  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
855  bool slope_cb = statspec != NULL && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
856 
857  TILE_AREA_LOOP(tile_cur, tile_area) {
858  CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false);
859  if (ret.Failed()) return ret;
860  cost.AddCost(ret);
861 
862  if (slope_cb) {
863  /* Do slope check if requested. */
864  ret = PerformStationTileSlopeCheck(tile_area.tile, tile_cur, statspec, axis, plat_len, numtracks);
865  if (ret.Failed()) return ret;
866  }
867 
868  /* if station is set, then we have special handling to allow building on top of already existing stations.
869  * so station points to INVALID_STATION if we can build on any station.
870  * Or it points to a station if we're only allowed to build on exactly that station. */
871  if (station != NULL && IsTileType(tile_cur, MP_STATION)) {
872  if (!IsRailStation(tile_cur)) {
873  return ClearTile_Station(tile_cur, DC_AUTO); // get error message
874  } else {
875  StationID st = GetStationIndex(tile_cur);
876  if (*station == INVALID_STATION) {
877  *station = st;
878  } else if (*station != st) {
879  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
880  }
881  }
882  } else {
883  /* Rail type is only valid when building a railway station; if station to
884  * build isn't a rail station it's INVALID_RAILTYPE. */
885  if (rt != INVALID_RAILTYPE &&
886  IsPlainRailTile(tile_cur) && !HasSignals(tile_cur) &&
887  HasPowerOnRail(GetRailType(tile_cur), rt)) {
888  /* Allow overbuilding if the tile:
889  * - has rail, but no signals
890  * - it has exactly one track
891  * - the track is in line with the station
892  * - the current rail type has power on the to-be-built type (e.g. convert normal rail to el rail)
893  */
894  TrackBits tracks = GetTrackBits(tile_cur);
895  Track track = RemoveFirstTrack(&tracks);
896  Track expected_track = HasBit(invalid_dirs, DIAGDIR_NE) ? TRACK_X : TRACK_Y;
897 
898  if (tracks == TRACK_BIT_NONE && track == expected_track) {
899  /* Check for trains having a reservation for this tile. */
900  if (HasBit(GetRailReservationTrackBits(tile_cur), track)) {
901  Train *v = GetTrainForReservation(tile_cur, track);
902  if (v != NULL) {
903  *affected_vehicles.Append() = v;
904  }
905  }
906  CommandCost ret = DoCommand(tile_cur, 0, track, flags, CMD_REMOVE_SINGLE_RAIL);
907  if (ret.Failed()) return ret;
908  cost.AddCost(ret);
909  /* With flags & ~DC_EXEC CmdLandscapeClear would fail since the rail still exists */
910  continue;
911  }
912  }
913  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
914  if (ret.Failed()) return ret;
915  cost.AddCost(ret);
916  }
917  }
918 
919  return cost;
920 }
921 
934 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)
935 {
937  int allowed_z = -1;
938 
939  TILE_AREA_LOOP(cur_tile, tile_area) {
940  CommandCost ret = CheckBuildableTile(cur_tile, invalid_dirs, allowed_z, !is_drive_through);
941  if (ret.Failed()) return ret;
942  cost.AddCost(ret);
943 
944  /* If station is set, then we have special handling to allow building on top of already existing stations.
945  * Station points to INVALID_STATION if we can build on any station.
946  * Or it points to a station if we're only allowed to build on exactly that station. */
947  if (station != NULL && IsTileType(cur_tile, MP_STATION)) {
948  if (!IsRoadStop(cur_tile)) {
949  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
950  } else {
951  if (is_truck_stop != IsTruckStop(cur_tile) ||
952  is_drive_through != IsDriveThroughStopTile(cur_tile)) {
953  return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
954  }
955  /* Drive-through station in the wrong direction. */
956  if (is_drive_through && IsDriveThroughStopTile(cur_tile) && DiagDirToAxis(GetRoadStopDir(cur_tile)) != axis){
957  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
958  }
959  StationID st = GetStationIndex(cur_tile);
960  if (*station == INVALID_STATION) {
961  *station = st;
962  } else if (*station != st) {
963  return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
964  }
965  }
966  } else {
967  bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
968  /* Road bits in the wrong direction. */
969  RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE;
970  if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) {
971  /* Someone was pedantic and *NEEDED* three fracking different error messages. */
972  switch (CountBits(rb)) {
973  case 1:
974  return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
975 
976  case 2:
977  if (rb == ROAD_X || rb == ROAD_Y) return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
978  return_cmd_error(STR_ERROR_DRIVE_THROUGH_CORNER);
979 
980  default: // 3 or 4
981  return_cmd_error(STR_ERROR_DRIVE_THROUGH_JUNCTION);
982  }
983  }
984 
985  RoadTypes cur_rts = IsNormalRoadTile(cur_tile) ? GetRoadTypes(cur_tile) : ROADTYPES_NONE;
986  uint num_roadbits = 0;
987  if (build_over_road) {
988  /* There is a road, check if we can build road+tram stop over it. */
989  if (HasBit(cur_rts, ROADTYPE_ROAD)) {
990  Owner road_owner = GetRoadOwner(cur_tile, ROADTYPE_ROAD);
991  if (road_owner == OWNER_TOWN) {
992  if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
994  CommandCost ret = CheckOwnership(road_owner);
995  if (ret.Failed()) return ret;
996  }
997  num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
998 
999  if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE && road_owner != OWNER_TOWN) {
1000  CommandCost ret = CheckOwnership(road_owner);
1001  if (ret.Failed()) return ret;
1002  }
1003  }
1004 
1005  /* There is a tram, check if we can build road+tram stop over it. */
1006  if (HasBit(cur_rts, ROADTYPE_TRAM)) {
1007  Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM);
1008  if (Company::IsValidID(tram_owner) &&
1010  /* Disallow breaking end-of-line of someone else
1011  * so trams can still reverse on this tile. */
1013  CommandCost ret = CheckOwnership(tram_owner);
1014  if (ret.Failed()) return ret;
1015  }
1016  num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_TRAM));
1017  }
1018 
1019  /* Take into account existing roadbits. */
1020  rts |= cur_rts;
1021  } else {
1022  ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1023  if (ret.Failed()) return ret;
1024  cost.AddCost(ret);
1025  }
1026 
1027  uint roadbits_to_build = CountBits(rts) * 2 - num_roadbits;
1028  cost.AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
1029  }
1030  }
1031 
1032  return cost;
1033 }
1034 
1043 {
1044  TileArea cur_ta = st->train_station;
1045 
1046  /* determine new size of train station region.. */
1047  int x = min(TileX(cur_ta.tile), TileX(new_ta.tile));
1048  int y = min(TileY(cur_ta.tile), TileY(new_ta.tile));
1049  new_ta.w = max(TileX(cur_ta.tile) + cur_ta.w, TileX(new_ta.tile) + new_ta.w) - x;
1050  new_ta.h = max(TileY(cur_ta.tile) + cur_ta.h, TileY(new_ta.tile) + new_ta.h) - y;
1051  new_ta.tile = TileXY(x, y);
1052 
1053  /* make sure the final size is not too big. */
1055  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1056  }
1057 
1058  return CommandCost();
1059 }
1060 
1061 static inline byte *CreateSingle(byte *layout, int n)
1062 {
1063  int i = n;
1064  do *layout++ = 0; while (--i);
1065  layout[((n - 1) >> 1) - n] = 2;
1066  return layout;
1067 }
1068 
1069 static inline byte *CreateMulti(byte *layout, int n, byte b)
1070 {
1071  int i = n;
1072  do *layout++ = b; while (--i);
1073  if (n > 4) {
1074  layout[0 - n] = 0;
1075  layout[n - 1 - n] = 0;
1076  }
1077  return layout;
1078 }
1079 
1087 void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec)
1088 {
1089  if (statspec != NULL && statspec->lengths >= plat_len &&
1090  statspec->platforms[plat_len - 1] >= numtracks &&
1091  statspec->layouts[plat_len - 1][numtracks - 1]) {
1092  /* Custom layout defined, follow it. */
1093  memcpy(layout, statspec->layouts[plat_len - 1][numtracks - 1],
1094  plat_len * numtracks);
1095  return;
1096  }
1097 
1098  if (plat_len == 1) {
1099  CreateSingle(layout, numtracks);
1100  } else {
1101  if (numtracks & 1) layout = CreateSingle(layout, plat_len);
1102  numtracks >>= 1;
1103 
1104  while (--numtracks >= 0) {
1105  layout = CreateMulti(layout, plat_len, 4);
1106  layout = CreateMulti(layout, plat_len, 6);
1107  }
1108  }
1109 }
1110 
1122 template <class T, StringID error_message>
1123 CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
1124 {
1125  assert(*st == NULL);
1126  bool check_surrounding = true;
1127 
1129  if (existing_station != INVALID_STATION) {
1130  if (adjacent && existing_station != station_to_join) {
1131  /* You can't build an adjacent station over the top of one that
1132  * already exists. */
1133  return_cmd_error(error_message);
1134  } else {
1135  /* Extend the current station, and don't check whether it will
1136  * be near any other stations. */
1137  *st = T::GetIfValid(existing_station);
1138  check_surrounding = (*st == NULL);
1139  }
1140  } else {
1141  /* There's no station here. Don't check the tiles surrounding this
1142  * one if the company wanted to build an adjacent station. */
1143  if (adjacent) check_surrounding = false;
1144  }
1145  }
1146 
1147  if (check_surrounding) {
1148  /* Make sure there is no more than one other station around us that is owned by us. */
1149  CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
1150  if (ret.Failed()) return ret;
1151  }
1152 
1153  /* Distant join */
1154  if (*st == NULL && station_to_join != INVALID_STATION) *st = T::GetIfValid(station_to_join);
1155 
1156  return CommandCost();
1157 }
1158 
1168 static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1169 {
1170  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
1171 }
1172 
1182 CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
1183 {
1184  return FindJoiningBaseStation<Waypoint, STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST>(existing_waypoint, waypoint_to_join, adjacent, ta, wp);
1185 }
1186 
1192 {
1195  v = v->Last();
1197 }
1198 
1204 {
1206  TryPathReserve(v, true, true);
1207  v = v->Last();
1209 }
1210 
1228 CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1229 {
1230  /* Unpack parameters */
1231  RailType rt = Extract<RailType, 0, 6>(p1);
1232  Axis axis = Extract<Axis, 6, 1>(p1);
1233  byte numtracks = GB(p1, 8, 8);
1234  byte plat_len = GB(p1, 16, 8);
1235  bool adjacent = HasBit(p1, 24);
1236 
1237  StationClassID spec_class = Extract<StationClassID, 0, 8>(p2);
1238  byte spec_index = GB(p2, 8, 8);
1239  StationID station_to_join = GB(p2, 16, 16);
1240 
1241  /* Does the authority allow this? */
1242  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile_org, flags);
1243  if (ret.Failed()) return ret;
1244 
1245  if (!ValParamRailtype(rt)) return CMD_ERROR;
1246 
1247  /* Check if the given station class is valid */
1248  if ((uint)spec_class >= StationClass::GetClassCount() || spec_class == STAT_CLASS_WAYP) return CMD_ERROR;
1249  if (spec_index >= StationClass::Get(spec_class)->GetSpecCount()) return CMD_ERROR;
1250  if (plat_len == 0 || numtracks == 0) return CMD_ERROR;
1251 
1252  int w_org, h_org;
1253  if (axis == AXIS_X) {
1254  w_org = plat_len;
1255  h_org = numtracks;
1256  } else {
1257  h_org = plat_len;
1258  w_org = numtracks;
1259  }
1260 
1261  bool reuse = (station_to_join != NEW_STATION);
1262  if (!reuse) station_to_join = INVALID_STATION;
1263  bool distant_join = (station_to_join != INVALID_STATION);
1264 
1265  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1266 
1268 
1269  /* these values are those that will be stored in train_tile and station_platforms */
1270  TileArea new_location(tile_org, w_org, h_org);
1271 
1272  /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
1273  StationID est = INVALID_STATION;
1274  SmallVector<Train *, 4> affected_vehicles;
1275  /* Clear the land below the station. */
1276  CommandCost cost = CheckFlatLandRailStation(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
1277  if (cost.Failed()) return cost;
1278  /* Add construction expenses. */
1279  cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);
1280  cost.AddCost(numtracks * plat_len * RailBuildCost(rt));
1281 
1282  Station *st = NULL;
1283  ret = FindJoiningStation(est, station_to_join, adjacent, new_location, &st);
1284  if (ret.Failed()) return ret;
1285 
1286  ret = BuildStationPart(&st, flags, reuse, new_location, STATIONNAMING_RAIL);
1287  if (ret.Failed()) return ret;
1288 
1289  if (st != NULL && st->train_station.tile != INVALID_TILE) {
1290  CommandCost ret = CanExpandRailStation(st, new_location, axis);
1291  if (ret.Failed()) return ret;
1292  }
1293 
1294  /* Check if we can allocate a custom stationspec to this station */
1295  const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
1296  int specindex = AllocateSpecToStation(statspec, st, (flags & DC_EXEC) != 0);
1297  if (specindex == -1) return_cmd_error(STR_ERROR_TOO_MANY_STATION_SPECS);
1298 
1299  if (statspec != NULL) {
1300  /* Perform NewStation checks */
1301 
1302  /* Check if the station size is permitted */
1303  if (HasBit(statspec->disallowed_platforms, min(numtracks - 1, 7)) || HasBit(statspec->disallowed_lengths, min(plat_len - 1, 7))) {
1304  return CMD_ERROR;
1305  }
1306 
1307  /* Check if the station is buildable */
1308  if (HasBit(statspec->callback_mask, CBM_STATION_AVAIL)) {
1309  uint16 cb_res = GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE);
1310  if (cb_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res)) return CMD_ERROR;
1311  }
1312  }
1313 
1314  if (flags & DC_EXEC) {
1315  TileIndexDiff tile_delta;
1316  byte *layout_ptr;
1317  byte numtracks_orig;
1318  Track track;
1319 
1320  st->train_station = new_location;
1321  st->AddFacility(FACIL_TRAIN, new_location.tile);
1322 
1323  st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
1324 
1325  if (statspec != NULL) {
1326  /* Include this station spec's animation trigger bitmask
1327  * in the station's cached copy. */
1328  st->cached_anim_triggers |= statspec->animation.triggers;
1329  }
1330 
1331  tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1332  track = AxisToTrack(axis);
1333 
1334  layout_ptr = AllocaM(byte, numtracks * plat_len);
1335  GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
1336 
1337  numtracks_orig = numtracks;
1338 
1339  Company *c = Company::Get(st->owner);
1340  TileIndex tile_track = tile_org;
1341  do {
1342  TileIndex tile = tile_track;
1343  int w = plat_len;
1344  do {
1345  byte layout = *layout_ptr++;
1346  if (IsRailStationTile(tile) && HasStationReservation(tile)) {
1347  /* Check for trains having a reservation for this tile. */
1349  if (v != NULL) {
1350  *affected_vehicles.Append() = v;
1352  }
1353  }
1354 
1355  /* Railtype can change when overbuilding. */
1356  if (IsRailStationTile(tile)) {
1357  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]--;
1358  c->infrastructure.station--;
1359  }
1360 
1361  /* Remove animation if overbuilding */
1362  DeleteAnimatedTile(tile);
1363  byte old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0;
1364  MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, rt);
1365  /* Free the spec if we overbuild something */
1366  DeallocateSpecFromStation(st, old_specindex);
1367 
1368  SetCustomStationSpecIndex(tile, specindex);
1369  SetStationTileRandomBits(tile, GB(Random(), 0, 4));
1370  SetAnimationFrame(tile, 0);
1371 
1372  if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++;
1373  c->infrastructure.station++;
1374 
1375  if (statspec != NULL) {
1376  /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
1377  uint32 platinfo = GetPlatformInfo(AXIS_X, GetStationGfx(tile), plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
1378 
1379  /* As the station is not yet completely finished, the station does not yet exist. */
1380  uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile);
1381  if (callback != CALLBACK_FAILED) {
1382  if (callback < 8) {
1383  SetStationGfx(tile, (callback & ~1) + axis);
1384  } else {
1386  }
1387  }
1388 
1389  /* Trigger station animation -- after building? */
1390  TriggerStationAnimation(st, tile, SAT_BUILT);
1391  }
1392 
1393  tile += tile_delta;
1394  } while (--w);
1395  AddTrackToSignalBuffer(tile_track, track, _current_company);
1396  YapfNotifyTrackLayoutChange(tile_track, track);
1397  tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
1398  } while (--numtracks);
1399 
1400  for (uint i = 0; i < affected_vehicles.Length(); ++i) {
1401  /* Restore reservations of trains. */
1402  RestoreTrainReservation(affected_vehicles[i]);
1403  }
1404 
1405  /* Check whether we need to expand the reservation of trains already on the station. */
1406  TileArea update_reservation_area;
1407  if (axis == AXIS_X) {
1408  update_reservation_area = TileArea(tile_org, 1, numtracks_orig);
1409  } else {
1410  update_reservation_area = TileArea(tile_org, numtracks_orig, 1);
1411  }
1412 
1413  TILE_AREA_LOOP(tile, update_reservation_area) {
1414  /* Don't even try to make eye candy parts reserved. */
1415  if (IsStationTileBlocked(tile)) continue;
1416 
1417  DiagDirection dir = AxisToDiagDir(axis);
1418  TileIndexDiff tile_offset = TileOffsByDiagDir(dir);
1419  TileIndex platform_begin = tile;
1420  TileIndex platform_end = tile;
1421 
1422  /* We can only account for tiles that are reachable from this tile, so ignore primarily blocked tiles while finding the platform begin and end. */
1423  for (TileIndex next_tile = platform_begin - tile_offset; IsCompatibleTrainStationTile(next_tile, platform_begin); next_tile -= tile_offset) {
1424  platform_begin = next_tile;
1425  }
1426  for (TileIndex next_tile = platform_end + tile_offset; IsCompatibleTrainStationTile(next_tile, platform_end); next_tile += tile_offset) {
1427  platform_end = next_tile;
1428  }
1429 
1430  /* If there is at least on reservation on the platform, we reserve the whole platform. */
1431  bool reservation = false;
1432  for (TileIndex t = platform_begin; !reservation && t <= platform_end; t += tile_offset) {
1433  reservation = HasStationReservation(t);
1434  }
1435 
1436  if (reservation) {
1437  SetRailStationPlatformReservation(platform_begin, dir, true);
1438  }
1439  }
1440 
1441  st->MarkTilesDirty(false);
1442  st->AfterStationTileSetChange(true, STATION_RAIL);
1443  }
1444 
1445  return cost;
1446 }
1447 
1448 static void MakeRailStationAreaSmaller(BaseStation *st)
1449 {
1450  TileArea ta = st->train_station;
1451 
1452 restart:
1453 
1454  /* too small? */
1455  if (ta.w != 0 && ta.h != 0) {
1456  /* check the left side, x = constant, y changes */
1457  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(0, i));) {
1458  /* the left side is unused? */
1459  if (++i == ta.h) {
1460  ta.tile += TileDiffXY(1, 0);
1461  ta.w--;
1462  goto restart;
1463  }
1464  }
1465 
1466  /* check the right side, x = constant, y changes */
1467  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(ta.w - 1, i));) {
1468  /* the right side is unused? */
1469  if (++i == ta.h) {
1470  ta.w--;
1471  goto restart;
1472  }
1473  }
1474 
1475  /* check the upper side, y = constant, x changes */
1476  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(i, 0));) {
1477  /* the left side is unused? */
1478  if (++i == ta.w) {
1479  ta.tile += TileDiffXY(0, 1);
1480  ta.h--;
1481  goto restart;
1482  }
1483  }
1484 
1485  /* check the lower side, y = constant, x changes */
1486  for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(i, ta.h - 1));) {
1487  /* the left side is unused? */
1488  if (++i == ta.w) {
1489  ta.h--;
1490  goto restart;
1491  }
1492  }
1493  } else {
1494  ta.Clear();
1495  }
1496 
1497  st->train_station = ta;
1498 }
1499 
1510 template <class T>
1511 CommandCost RemoveFromRailBaseStation(TileArea ta, SmallVector<T *, 4> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
1512 {
1513  /* Count of the number of tiles removed */
1514  int quantity = 0;
1515  CommandCost total_cost(EXPENSES_CONSTRUCTION);
1516  /* Accumulator for the errors seen during clearing. If no errors happen,
1517  * and the quantity is 0 there is no station. Otherwise it will be one
1518  * of the other error that got accumulated. */
1520 
1521  /* Do the action for every tile into the area */
1522  TILE_AREA_LOOP(tile, ta) {
1523  /* Make sure the specified tile is a rail station */
1524  if (!HasStationTileRail(tile)) continue;
1525 
1526  /* If there is a vehicle on ground, do not allow to remove (flood) the tile */
1528  error.AddCost(ret);
1529  if (ret.Failed()) continue;
1530 
1531  /* Check ownership of station */
1532  T *st = T::GetByTile(tile);
1533  if (st == NULL) continue;
1534 
1535  if (_current_company != OWNER_WATER) {
1536  CommandCost ret = CheckOwnership(st->owner);
1537  error.AddCost(ret);
1538  if (ret.Failed()) continue;
1539  }
1540 
1541  /* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
1542  quantity++;
1543 
1544  if (keep_rail || IsStationTileBlocked(tile)) {
1545  /* Don't refund the 'steel' of the track when we keep the
1546  * rail, or when the tile didn't have any rail at all. */
1547  total_cost.AddCost(-_price[PR_CLEAR_RAIL]);
1548  }
1549 
1550  if (flags & DC_EXEC) {
1551  /* read variables before the station tile is removed */
1552  uint specindex = GetCustomStationSpecIndex(tile);
1553  Track track = GetRailStationTrack(tile);
1554  Owner owner = GetTileOwner(tile);
1555  RailType rt = GetRailType(tile);
1556  Train *v = NULL;
1557 
1558  if (HasStationReservation(tile)) {
1559  v = GetTrainForReservation(tile, track);
1560  if (v != NULL) FreeTrainReservation(v);
1561  }
1562 
1563  bool build_rail = keep_rail && !IsStationTileBlocked(tile);
1564  if (!build_rail && !IsStationTileBlocked(tile)) Company::Get(owner)->infrastructure.rail[rt]--;
1565 
1566  DoClearSquare(tile);
1567  DeleteNewGRFInspectWindow(GSF_STATIONS, tile);
1568  if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt);
1569  Company::Get(owner)->infrastructure.station--;
1571 
1572  st->rect.AfterRemoveTile(st, tile);
1573  AddTrackToSignalBuffer(tile, track, owner);
1574  YapfNotifyTrackLayoutChange(tile, track);
1575 
1576  DeallocateSpecFromStation(st, specindex);
1577 
1578  affected_stations.Include(st);
1579 
1580  if (v != NULL) RestoreTrainReservation(v);
1581  }
1582  }
1583 
1584  if (quantity == 0) return error.Failed() ? error : CommandCost(STR_ERROR_THERE_IS_NO_STATION);
1585 
1586  for (T **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
1587  T *st = *stp;
1588 
1589  /* now we need to make the "spanned" area of the railway station smaller
1590  * if we deleted something at the edges.
1591  * we also need to adjust train_tile. */
1592  MakeRailStationAreaSmaller(st);
1593  UpdateStationSignCoord(st);
1594 
1595  /* if we deleted the whole station, delete the train facility. */
1596  if (st->train_station.tile == INVALID_TILE) {
1597  st->facilities &= ~FACIL_TRAIN;
1599  st->UpdateVirtCoord();
1601  }
1602  }
1603 
1604  total_cost.AddCost(quantity * removal_cost);
1605  return total_cost;
1606 }
1607 
1619 CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1620 {
1621  TileIndex end = p1 == 0 ? start : p1;
1622  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1623 
1624  TileArea ta(start, end);
1625  SmallVector<Station *, 4> affected_stations;
1626 
1627  CommandCost ret = RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_STATION_RAIL], HasBit(p2, 0));
1628  if (ret.Failed()) return ret;
1629 
1630  /* Do all station specific functions here. */
1631  for (Station **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
1632  Station *st = *stp;
1633 
1635  st->MarkTilesDirty(false);
1637  }
1638 
1639  /* Now apply the rail cost to the number that we deleted */
1640  return ret;
1641 }
1642 
1654 CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1655 {
1656  TileIndex end = p1 == 0 ? start : p1;
1657  if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
1658 
1659  TileArea ta(start, end);
1660  SmallVector<Waypoint *, 4> affected_stations;
1661 
1662  return RemoveFromRailBaseStation(ta, affected_stations, flags, _price[PR_CLEAR_WAYPOINT_RAIL], HasBit(p2, 0));
1663 }
1664 
1665 
1674 template <class T>
1676 {
1677  /* Current company owns the station? */
1678  if (_current_company != OWNER_WATER) {
1679  CommandCost ret = CheckOwnership(st->owner);
1680  if (ret.Failed()) return ret;
1681  }
1682 
1683  /* determine width and height of platforms */
1684  TileArea ta = st->train_station;
1685 
1686  assert(ta.w != 0 && ta.h != 0);
1687 
1689  /* clear all areas of the station */
1690  TILE_AREA_LOOP(tile, ta) {
1691  /* only remove tiles that are actually train station tiles */
1692  if (st->TileBelongsToRailStation(tile)) {
1693  SmallVector<T*, 4> affected_stations; // dummy
1694  CommandCost ret = RemoveFromRailBaseStation(TileArea(tile, 1, 1), affected_stations, flags, removal_cost, false);
1695  if (ret.Failed()) return ret;
1696  cost.AddCost(ret);
1697  }
1698  }
1699 
1700  return cost;
1701 }
1702 
1710 {
1711  /* if there is flooding, remove platforms tile by tile */
1712  if (_current_company == OWNER_WATER) {
1713  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_STATION);
1714  }
1715 
1716  Station *st = Station::GetByTile(tile);
1717  CommandCost cost = RemoveRailStation(st, flags, _price[PR_CLEAR_STATION_RAIL]);
1718 
1719  if (flags & DC_EXEC) st->RecomputeIndustriesNear();
1720 
1721  return cost;
1722 }
1723 
1731 {
1732  /* if there is flooding, remove waypoints tile by tile */
1733  if (_current_company == OWNER_WATER) {
1734  return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_WAYPOINT);
1735  }
1736 
1737  return RemoveRailStation(Waypoint::GetByTile(tile), flags, _price[PR_CLEAR_WAYPOINT_RAIL]);
1738 }
1739 
1740 
1746 static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
1747 {
1748  RoadStop **primary_stop = (truck_station) ? &st->truck_stops : &st->bus_stops;
1749 
1750  if (*primary_stop == NULL) {
1751  /* we have no roadstop of the type yet, so write a "primary stop" */
1752  return primary_stop;
1753  } else {
1754  /* there are stops already, so append to the end of the list */
1755  RoadStop *stop = *primary_stop;
1756  while (stop->next != NULL) stop = stop->next;
1757  return &stop->next;
1758  }
1759 }
1760 
1762 
1772 static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
1773 {
1774  return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST>(existing_stop, station_to_join, adjacent, ta, st);
1775 }
1776 
1793 CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1794 {
1795  bool type = HasBit(p2, 0);
1796  bool is_drive_through = HasBit(p2, 1);
1797  RoadTypes rts = Extract<RoadTypes, 2, 2>(p2);
1798  StationID station_to_join = GB(p2, 16, 16);
1799  bool reuse = (station_to_join != NEW_STATION);
1800  if (!reuse) station_to_join = INVALID_STATION;
1801  bool distant_join = (station_to_join != INVALID_STATION);
1802 
1803  uint8 width = (uint8)GB(p1, 0, 8);
1804  uint8 length = (uint8)GB(p1, 8, 8);
1805 
1806  /* Check if the requested road stop is too big */
1807  if (width > _settings_game.station.station_spread || length > _settings_game.station.station_spread) return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
1808  /* Check for incorrect width / length. */
1809  if (width == 0 || length == 0) return CMD_ERROR;
1810  /* Check if the first tile and the last tile are valid */
1811  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, length - 1) == INVALID_TILE) return CMD_ERROR;
1812 
1813  TileArea roadstop_area(tile, width, length);
1814 
1815  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
1816 
1817  if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
1818 
1819  /* Trams only have drive through stops */
1820  if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR;
1821 
1822  DiagDirection ddir;
1823  Axis axis;
1824  if (is_drive_through) {
1825  /* By definition axis is valid, due to there being 2 axes and reading 1 bit. */
1826  axis = Extract<Axis, 6, 1>(p2);
1827  ddir = AxisToDiagDir(axis);
1828  } else {
1829  /* By definition ddir is valid, due to there being 4 diagonal directions and reading 2 bits. */
1830  ddir = Extract<DiagDirection, 6, 2>(p2);
1831  axis = DiagDirToAxis(ddir);
1832  }
1833 
1834  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
1835  if (ret.Failed()) return ret;
1836 
1837  /* Total road stop cost. */
1838  CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
1839  StationID est = INVALID_STATION;
1840  ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rts);
1841  if (ret.Failed()) return ret;
1842  cost.AddCost(ret);
1843 
1844  Station *st = NULL;
1845  ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 5), roadstop_area, &st);
1846  if (ret.Failed()) return ret;
1847 
1848  /* Check if this number of road stops can be allocated. */
1849  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);
1850 
1851  ret = BuildStationPart(&st, flags, reuse, roadstop_area, STATIONNAMING_ROAD);
1852  if (ret.Failed()) return ret;
1853 
1854  if (flags & DC_EXEC) {
1855  /* Check every tile in the area. */
1856  TILE_AREA_LOOP(cur_tile, roadstop_area) {
1857  RoadTypes cur_rts = GetRoadTypes(cur_tile);
1858  Owner road_owner = HasBit(cur_rts, ROADTYPE_ROAD) ? GetRoadOwner(cur_tile, ROADTYPE_ROAD) : _current_company;
1859  Owner tram_owner = HasBit(cur_rts, ROADTYPE_TRAM) ? GetRoadOwner(cur_tile, ROADTYPE_TRAM) : _current_company;
1860 
1861  if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
1862  RemoveRoadStop(cur_tile, flags);
1863  }
1864 
1865  RoadStop *road_stop = new RoadStop(cur_tile);
1866  /* Insert into linked list of RoadStops. */
1867  RoadStop **currstop = FindRoadStopSpot(type, st);
1868  *currstop = road_stop;
1869 
1870  if (type) {
1871  st->truck_station.Add(cur_tile);
1872  } else {
1873  st->bus_station.Add(cur_tile);
1874  }
1875 
1876  /* Initialize an empty station. */
1877  st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, cur_tile);
1878 
1879  st->rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
1880 
1881  RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
1882  if (is_drive_through) {
1883  /* Update company infrastructure counts. If the current tile is a normal
1884  * road tile, count only the new road bits needed to get a full diagonal road. */
1885  RoadType rt;
1886  FOR_EACH_SET_ROADTYPE(rt, cur_rts | rts) {
1887  Company *c = Company::GetIfValid(rt == ROADTYPE_ROAD ? road_owner : tram_owner);
1888  if (c != NULL) {
1889  c->infrastructure.road[rt] += 2 - (IsNormalRoadTile(cur_tile) && HasBit(cur_rts, rt) ? CountBits(GetRoadBits(cur_tile, rt)) : 0);
1891  }
1892  }
1893 
1894  MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, axis);
1895  road_stop->MakeDriveThrough();
1896  } else {
1897  /* Non-drive-through stop never overbuild and always count as two road bits. */
1898  Company::Get(st->owner)->infrastructure.road[FIND_FIRST_BIT(rts)] += 2;
1899  MakeRoadStop(cur_tile, st->owner, st->index, rs_type, rts, ddir);
1900  }
1901  Company::Get(st->owner)->infrastructure.station++;
1902 
1903  MarkTileDirtyByTile(cur_tile);
1904  }
1905  }
1906 
1907  if (st != NULL) {
1908  st->AfterStationTileSetChange(true, type ? STATION_TRUCK: STATION_BUS);
1909  }
1910  return cost;
1911 }
1912 
1913 
1914 static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
1915 {
1916  if (v->type == VEH_ROAD) {
1917  /* Okay... we are a road vehicle on a drive through road stop.
1918  * But that road stop has just been removed, so we need to make
1919  * sure we are in a valid state... however, vehicles can also
1920  * turn on road stop tiles, so only clear the 'road stop' state
1921  * bits and only when the state was 'in road stop', otherwise
1922  * we'll end up clearing the turn around bits. */
1923  RoadVehicle *rv = RoadVehicle::From(v);
1925  }
1926 
1927  return NULL;
1928 }
1929 
1930 
1938 {
1939  Station *st = Station::GetByTile(tile);
1940 
1941  if (_current_company != OWNER_WATER) {
1942  CommandCost ret = CheckOwnership(st->owner);
1943  if (ret.Failed()) return ret;
1944  }
1945 
1946  bool is_truck = IsTruckStop(tile);
1947 
1948  RoadStop **primary_stop;
1949  RoadStop *cur_stop;
1950  if (is_truck) { // truck stop
1951  primary_stop = &st->truck_stops;
1952  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_TRUCK);
1953  } else {
1954  primary_stop = &st->bus_stops;
1955  cur_stop = RoadStop::GetByTile(tile, ROADSTOP_BUS);
1956  }
1957 
1958  assert(cur_stop != NULL);
1959 
1960  /* don't do the check for drive-through road stops when company bankrupts */
1961  if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
1962  /* remove the 'going through road stop' status from all vehicles on that tile */
1963  if (flags & DC_EXEC) FindVehicleOnPos(tile, NULL, &ClearRoadStopStatusEnum);
1964  } else {
1966  if (ret.Failed()) return ret;
1967  }
1968 
1969  if (flags & DC_EXEC) {
1970  if (*primary_stop == cur_stop) {
1971  /* removed the first stop in the list */
1972  *primary_stop = cur_stop->next;
1973  /* removed the only stop? */
1974  if (*primary_stop == NULL) {
1975  st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
1976  }
1977  } else {
1978  /* tell the predecessor in the list to skip this stop */
1979  RoadStop *pred = *primary_stop;
1980  while (pred->next != cur_stop) pred = pred->next;
1981  pred->next = cur_stop->next;
1982  }
1983 
1984  /* Update company infrastructure counts. */
1985  RoadType rt;
1986  FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1987  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
1988  if (c != NULL) {
1989  c->infrastructure.road[rt] -= 2;
1991  }
1992  }
1993  Company::Get(st->owner)->infrastructure.station--;
1995 
1996  if (IsDriveThroughStopTile(tile)) {
1997  /* Clears the tile for us */
1998  cur_stop->ClearDriveThrough();
1999  } else {
2000  DoClearSquare(tile);
2001  }
2002 
2003  delete cur_stop;
2004 
2005  /* Make sure no vehicle is going to the old roadstop */
2006  RoadVehicle *v;
2007  FOR_ALL_ROADVEHICLES(v) {
2008  if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
2009  v->dest_tile == tile) {
2010  v->SetDestTile(v->GetOrderStationLocation(st->index));
2011  }
2012  }
2013 
2014  st->rect.AfterRemoveTile(st, tile);
2015 
2016  st->AfterStationTileSetChange(false, is_truck ? STATION_TRUCK: STATION_BUS);
2017 
2018  /* Update the tile area of the truck/bus stop */
2019  if (is_truck) {
2020  st->truck_station.Clear();
2021  for (const RoadStop *rs = st->truck_stops; rs != NULL; rs = rs->next) st->truck_station.Add(rs->xy);
2022  } else {
2023  st->bus_station.Clear();
2024  for (const RoadStop *rs = st->bus_stops; rs != NULL; rs = rs->next) st->bus_station.Add(rs->xy);
2025  }
2026  }
2027 
2028  return CommandCost(EXPENSES_CONSTRUCTION, _price[is_truck ? PR_CLEAR_STATION_TRUCK : PR_CLEAR_STATION_BUS]);
2029 }
2030 
2042 CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2043 {
2044  uint8 width = (uint8)GB(p1, 0, 8);
2045  uint8 height = (uint8)GB(p1, 8, 8);
2046  bool keep_drive_through_roads = !HasBit(p2, 1);
2047 
2048  /* Check for incorrect width / height. */
2049  if (width == 0 || height == 0) return CMD_ERROR;
2050  /* Check if the first tile and the last tile are valid */
2051  if (!IsValidTile(tile) || TileAddWrap(tile, width - 1, height - 1) == INVALID_TILE) return CMD_ERROR;
2052  /* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
2053  if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
2054 
2055  TileArea roadstop_area(tile, width, height);
2056 
2058  CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
2059  bool had_success = false;
2060 
2061  TILE_AREA_LOOP(cur_tile, roadstop_area) {
2062  /* Make sure the specified tile is a road stop of the correct type */
2063  if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
2064 
2065  /* Save information on to-be-restored roads before the stop is removed. */
2066  RoadTypes rts = ROADTYPES_NONE;
2067  RoadBits road_bits = ROAD_NONE;
2068  Owner road_owner[] = { OWNER_NONE, OWNER_NONE };
2069  assert_compile(lengthof(road_owner) == ROADTYPE_END);
2070  if (IsDriveThroughStopTile(cur_tile)) {
2071  RoadType rt;
2072  FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(cur_tile)) {
2073  road_owner[rt] = GetRoadOwner(cur_tile, rt);
2074  /* If we don't want to preserve our roads then restore only roads of others. */
2075  if (keep_drive_through_roads || road_owner[rt] != _current_company) SetBit(rts, rt);
2076  }
2077  road_bits = AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(cur_tile)));
2078  }
2079 
2080  CommandCost ret = RemoveRoadStop(cur_tile, flags);
2081  if (ret.Failed()) {
2082  last_error = ret;
2083  continue;
2084  }
2085  cost.AddCost(ret);
2086  had_success = true;
2087 
2088  /* Restore roads. */
2089  if ((flags & DC_EXEC) && rts != ROADTYPES_NONE) {
2090  MakeRoadNormal(cur_tile, road_bits, rts, ClosestTownFromTile(cur_tile, UINT_MAX)->index,
2091  road_owner[ROADTYPE_ROAD], road_owner[ROADTYPE_TRAM]);
2092 
2093  /* Update company infrastructure counts. */
2094  RoadType rt;
2095  FOR_EACH_SET_ROADTYPE(rt, rts) {
2096  Company *c = Company::GetIfValid(GetRoadOwner(cur_tile, rt));
2097  if (c != NULL) {
2098  c->infrastructure.road[rt] += CountBits(road_bits);
2100  }
2101  }
2102  }
2103  }
2104 
2105  return had_success ? cost : last_error;
2106 }
2107 
2115 {
2116  uint mindist = UINT_MAX;
2117 
2118  for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
2119  mindist = min(mindist, DistanceManhattan(town_tile, cur_tile));
2120  }
2121 
2122  return mindist;
2123 }
2124 
2135 {
2136  /* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
2137  * So no need to go any further*/
2138  if (as->noise_level < 2) return as->noise_level;
2139 
2140  uint distance = GetMinimalAirportDistanceToTile(it, town_tile);
2141 
2142  /* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
2143  * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
2144  * Basically, it says that the less tolerant a town is, the bigger the distance before
2145  * an actual decrease can be granted */
2146  uint8 town_tolerance_distance = 8 + (_settings_game.difficulty.town_council_tolerance * 4);
2147 
2148  /* now, we want to have the distance segmented using the distance judged bareable by town
2149  * This will give us the coefficient of reduction the distance provides. */
2150  uint noise_reduction = distance / town_tolerance_distance;
2151 
2152  /* If the noise reduction equals the airport noise itself, don't give it for free.
2153  * Otherwise, simply reduce the airport's level. */
2154  return noise_reduction >= as->noise_level ? 1 : as->noise_level - noise_reduction;
2155 }
2156 
2165 {
2166  Town *t, *nearest = NULL;
2167  uint add = as->size_x + as->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
2168  uint mindist = UINT_MAX - add; // prevent overflow
2169  FOR_ALL_TOWNS(t) {
2170  if (DistanceManhattan(t->xy, it) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
2171  TileIterator *copy = it.Clone();
2172  uint dist = GetMinimalAirportDistanceToTile(*copy, t->xy);
2173  delete copy;
2174  if (dist < mindist) {
2175  nearest = t;
2176  mindist = dist;
2177  }
2178  }
2179  }
2180 
2181  return nearest;
2182 }
2183 
2184 
2187 {
2188  Town *t;
2189  const Station *st;
2190 
2191  FOR_ALL_TOWNS(t) t->noise_reached = 0;
2192 
2193  FOR_ALL_STATIONS(st) {
2194  if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
2195  const AirportSpec *as = st->airport.GetSpec();
2196  AirportTileIterator it(st);
2197  Town *nearest = AirportGetNearestTown(as, it);
2198  nearest->noise_reached += GetAirportNoiseLevelForTown(as, it, nearest->xy);
2199  }
2200  }
2201 }
2202 
2216 CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2217 {
2218  StationID station_to_join = GB(p2, 16, 16);
2219  bool reuse = (station_to_join != NEW_STATION);
2220  if (!reuse) station_to_join = INVALID_STATION;
2221  bool distant_join = (station_to_join != INVALID_STATION);
2222  byte airport_type = GB(p1, 0, 8);
2223  byte layout = GB(p1, 8, 8);
2224 
2225  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2226 
2227  if (airport_type >= NUM_AIRPORTS) return CMD_ERROR;
2228 
2229  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2230  if (ret.Failed()) return ret;
2231 
2232  /* Check if a valid, buildable airport was chosen for construction */
2233  const AirportSpec *as = AirportSpec::Get(airport_type);
2234  if (!as->IsAvailable() || layout >= as->num_table) return CMD_ERROR;
2235 
2236  Direction rotation = as->rotation[layout];
2237  int w = as->size_x;
2238  int h = as->size_y;
2239  if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
2240  TileArea airport_area = TileArea(tile, w, h);
2241 
2243  return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
2244  }
2245 
2246  AirportTileTableIterator iter(as->table[layout], tile);
2247  CommandCost cost = CheckFlatLandAirport(iter, flags);
2248  if (cost.Failed()) return cost;
2249 
2250  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
2251  Town *nearest = AirportGetNearestTown(as, iter);
2252  uint newnoise_level = GetAirportNoiseLevelForTown(as, iter, nearest->xy);
2253 
2254  /* Check if local auth would allow a new airport */
2255  StringID authority_refuse_message = STR_NULL;
2256  Town *authority_refuse_town = NULL;
2257 
2259  /* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
2260  if ((nearest->noise_reached + newnoise_level) > nearest->MaxTownNoise()) {
2261  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE;
2262  authority_refuse_town = nearest;
2263  }
2264  } else {
2265  Town *t = ClosestTownFromTile(tile, UINT_MAX);
2266  uint num = 0;
2267  const Station *st;
2268  FOR_ALL_STATIONS(st) {
2269  if (st->town == t && (st->facilities & FACIL_AIRPORT) && st->airport.type != AT_OILRIG) num++;
2270  }
2271  if (num >= 2) {
2272  authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT;
2273  authority_refuse_town = t;
2274  }
2275  }
2276 
2277  if (authority_refuse_message != STR_NULL) {
2278  SetDParam(0, authority_refuse_town->index);
2279  return_cmd_error(authority_refuse_message);
2280  }
2281 
2282  Station *st = NULL;
2283  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p2, 0), airport_area, &st);
2284  if (ret.Failed()) return ret;
2285 
2286  /* Distant join */
2287  if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
2288 
2289  ret = BuildStationPart(&st, flags, reuse, airport_area, (GetAirport(airport_type)->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_AIRPORT : STATIONNAMING_HELIPORT);
2290  if (ret.Failed()) return ret;
2291 
2292  if (st != NULL && st->airport.tile != INVALID_TILE) {
2293  return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT);
2294  }
2295 
2296  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2297  cost.AddCost(_price[PR_BUILD_STATION_AIRPORT]);
2298  }
2299 
2300  if (flags & DC_EXEC) {
2301  /* Always add the noise, so there will be no need to recalculate when option toggles */
2302  nearest->noise_reached += newnoise_level;
2303 
2304  st->AddFacility(FACIL_AIRPORT, tile);
2305  st->airport.type = airport_type;
2306  st->airport.layout = layout;
2307  st->airport.flags = 0;
2308  st->airport.rotation = rotation;
2309 
2310  st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
2311 
2312  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2313  MakeAirport(iter, st->owner, st->index, iter.GetStationGfx(), WATER_CLASS_INVALID);
2314  SetStationTileRandomBits(iter, GB(Random(), 0, 4));
2315  st->airport.Add(iter);
2316 
2318  }
2319 
2320  /* Only call the animation trigger after all tiles have been built */
2321  for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
2322  AirportTileAnimationTrigger(st, iter, AAT_BUILT);
2323  }
2324 
2326 
2327  Company::Get(st->owner)->infrastructure.airport++;
2328 
2329  st->AfterStationTileSetChange(true, STATION_AIRPORT);
2331 
2334  }
2335  }
2336 
2337  return cost;
2338 }
2339 
2347 {
2348  Station *st = Station::GetByTile(tile);
2349 
2350  if (_current_company != OWNER_WATER) {
2351  CommandCost ret = CheckOwnership(st->owner);
2352  if (ret.Failed()) return ret;
2353  }
2354 
2355  tile = st->airport.tile;
2356 
2358 
2359  const Aircraft *a;
2360  FOR_ALL_AIRCRAFT(a) {
2361  if (!a->IsNormalAircraft()) continue;
2362  if (a->targetairport == st->index && a->state != FLYING) {
2363  return_cmd_error(STR_ERROR_AIRCRAFT_IN_THE_WAY);
2364  }
2365  }
2366 
2367  if (flags & DC_EXEC) {
2368  const AirportSpec *as = st->airport.GetSpec();
2369  /* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
2370  * And as for construction, always remove it, even if the setting is not set, in order to avoid the
2371  * need of recalculation */
2372  AirportTileIterator it(st);
2373  Town *nearest = AirportGetNearestTown(as, it);
2374  nearest->noise_reached -= GetAirportNoiseLevelForTown(as, it, nearest->xy);
2375  }
2376 
2377  TILE_AREA_LOOP(tile_cur, st->airport) {
2378  if (!st->TileBelongsToAirport(tile_cur)) continue;
2379 
2380  CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
2381  if (ret.Failed()) return ret;
2382 
2383  cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
2384 
2385  if (flags & DC_EXEC) {
2386  if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
2387  DeleteAnimatedTile(tile_cur);
2388  DoClearSquare(tile_cur);
2389  DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
2390  }
2391  }
2392 
2393  if (flags & DC_EXEC) {
2394  /* Clear the persistent storage. */
2395  delete st->airport.psa;
2396 
2397  for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
2400  );
2401  }
2402 
2403  st->rect.AfterRemoveRect(st, st->airport);
2404 
2405  st->airport.Clear();
2406  st->facilities &= ~FACIL_AIRPORT;
2407 
2409 
2412  }
2413 
2414  Company::Get(st->owner)->infrastructure.airport--;
2415 
2416  st->AfterStationTileSetChange(false, STATION_AIRPORT);
2417 
2418  DeleteNewGRFInspectWindow(GSF_AIRPORTS, st->index);
2419  }
2420 
2421  return cost;
2422 }
2423 
2433 CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2434 {
2435  if (!Station::IsValidID(p1)) return CMD_ERROR;
2436  Station *st = Station::Get(p1);
2437 
2438  if (!(st->facilities & FACIL_AIRPORT) || st->owner == OWNER_NONE) return CMD_ERROR;
2439 
2440  CommandCost ret = CheckOwnership(st->owner);
2441  if (ret.Failed()) return ret;
2442 
2443  if (flags & DC_EXEC) {
2446  }
2447  return CommandCost();
2448 }
2449 
2456 bool HasStationInUse(StationID station, bool include_company, CompanyID company)
2457 {
2458  const Vehicle *v;
2459  FOR_ALL_VEHICLES(v) {
2460  if ((v->owner == company) == include_company) {
2461  const Order *order;
2462  FOR_VEHICLE_ORDERS(v, order) {
2463  if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
2464  return true;
2465  }
2466  }
2467  }
2468  }
2469  return false;
2470 }
2471 
2472 static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
2473  {-1, 0},
2474  { 0, 0},
2475  { 0, 0},
2476  { 0, -1}
2477 };
2478 static const byte _dock_w_chk[4] = { 2, 1, 2, 1 };
2479 static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
2480 
2490 CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2491 {
2492  StationID station_to_join = GB(p2, 16, 16);
2493  bool reuse = (station_to_join != NEW_STATION);
2494  if (!reuse) station_to_join = INVALID_STATION;
2495  bool distant_join = (station_to_join != INVALID_STATION);
2496 
2497  if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
2498 
2500  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2501  direction = ReverseDiagDir(direction);
2502 
2503  /* Docks cannot be placed on rapids */
2504  if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2505 
2506  CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
2507  if (ret.Failed()) return ret;
2508 
2509  if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2510 
2511  ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2512  if (ret.Failed()) return ret;
2513 
2514  TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
2515 
2516  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2517  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2518  }
2519 
2520  if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2521 
2522  /* Get the water class of the water tile before it is cleared.*/
2523  WaterClass wc = GetWaterClass(tile_cur);
2524 
2525  ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2526  if (ret.Failed()) return ret;
2527 
2528  tile_cur += TileOffsByDiagDir(direction);
2529  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
2530  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2531  }
2532 
2533  TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
2534  _dock_w_chk[direction], _dock_h_chk[direction]);
2535 
2536  /* middle */
2537  Station *st = NULL;
2538  ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p1, 0), dock_area, &st);
2539  if (ret.Failed()) return ret;
2540 
2541  /* Distant join */
2542  if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
2543 
2544  ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK);
2545  if (ret.Failed()) return ret;
2546 
2547  if (st != NULL && st->dock_tile != INVALID_TILE) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK);
2548 
2549  if (flags & DC_EXEC) {
2550  st->dock_tile = tile;
2551  st->AddFacility(FACIL_DOCK, tile);
2552 
2553  st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY);
2554 
2555  /* If the water part of the dock is on a canal, update infrastructure counts.
2556  * This is needed as we've unconditionally cleared that tile before. */
2557  if (wc == WATER_CLASS_CANAL) {
2558  Company::Get(st->owner)->infrastructure.water++;
2559  }
2560  Company::Get(st->owner)->infrastructure.station += 2;
2561 
2562  MakeDock(tile, st->owner, st->index, direction, wc);
2563 
2564  st->AfterStationTileSetChange(true, STATION_DOCK);
2565  }
2566 
2567  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
2568 }
2569 
2577 {
2578  Station *st = Station::GetByTile(tile);
2579  CommandCost ret = CheckOwnership(st->owner);
2580  if (ret.Failed()) return ret;
2581 
2582  TileIndex docking_location = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
2583 
2584  TileIndex tile1 = st->dock_tile;
2585  TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
2586 
2587  ret = EnsureNoVehicleOnGround(tile1);
2588  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
2589  if (ret.Failed()) return ret;
2590 
2591  if (flags & DC_EXEC) {
2592  DoClearSquare(tile1);
2593  MarkTileDirtyByTile(tile1);
2594  MakeWaterKeepingClass(tile2, st->owner);
2595 
2596  st->rect.AfterRemoveTile(st, tile1);
2597  st->rect.AfterRemoveTile(st, tile2);
2598 
2599  st->dock_tile = INVALID_TILE;
2600  st->facilities &= ~FACIL_DOCK;
2601 
2602  Company::Get(st->owner)->infrastructure.station -= 2;
2603 
2604  st->AfterStationTileSetChange(false, STATION_DOCK);
2605 
2606  /* All ships that were going to our station, can't go to it anymore.
2607  * Just clear the order, then automatically the next appropriate order
2608  * will be selected and in case of no appropriate order it will just
2609  * wander around the world. */
2610  Ship *s;
2611  FOR_ALL_SHIPS(s) {
2612  if (s->current_order.IsType(OT_LOADING) && s->tile == docking_location) {
2613  s->LeaveStation();
2614  }
2615 
2616  if (s->dest_tile == docking_location) {
2617  s->SetDestTile(0);
2618  s->current_order.Free();
2619  }
2620  }
2621  }
2622 
2623  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_DOCK]);
2624 }
2625 
2626 #include "table/station_land.h"
2627 
2628 const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
2629 {
2630  return &_station_display_datas[st][gfx];
2631 }
2632 
2642 bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset)
2643 {
2644  bool snow_desert;
2645  switch (*ground) {
2646  case SPR_RAIL_TRACK_X:
2647  case SPR_MONO_TRACK_X:
2648  case SPR_MGLV_TRACK_X:
2649  snow_desert = false;
2650  *overlay_offset = RTO_X;
2651  break;
2652 
2653  case SPR_RAIL_TRACK_Y:
2654  case SPR_MONO_TRACK_Y:
2655  case SPR_MGLV_TRACK_Y:
2656  snow_desert = false;
2657  *overlay_offset = RTO_Y;
2658  break;
2659 
2660  case SPR_RAIL_TRACK_X_SNOW:
2661  case SPR_MONO_TRACK_X_SNOW:
2662  case SPR_MGLV_TRACK_X_SNOW:
2663  snow_desert = true;
2664  *overlay_offset = RTO_X;
2665  break;
2666 
2667  case SPR_RAIL_TRACK_Y_SNOW:
2668  case SPR_MONO_TRACK_Y_SNOW:
2669  case SPR_MGLV_TRACK_Y_SNOW:
2670  snow_desert = true;
2671  *overlay_offset = RTO_Y;
2672  break;
2673 
2674  default:
2675  return false;
2676  }
2677 
2678  if (ti != NULL) {
2679  /* Decide snow/desert from tile */
2681  case LT_ARCTIC:
2682  snow_desert = (uint)ti->z > GetSnowLine() * TILE_HEIGHT;
2683  break;
2684 
2685  case LT_TROPIC:
2686  snow_desert = GetTropicZone(ti->tile) == TROPICZONE_DESERT;
2687  break;
2688 
2689  default:
2690  break;
2691  }
2692  }
2693 
2694  *ground = snow_desert ? SPR_FLAT_SNOW_DESERT_TILE : SPR_FLAT_GRASS_TILE;
2695  return true;
2696 }
2697 
2698 static void DrawTile_Station(TileInfo *ti)
2699 {
2700  const NewGRFSpriteLayout *layout = NULL;
2701  DrawTileSprites tmp_rail_layout;
2702  const DrawTileSprites *t = NULL;
2703  RoadTypes roadtypes;
2704  int32 total_offset;
2705  const RailtypeInfo *rti = NULL;
2706  uint32 relocation = 0;
2707  uint32 ground_relocation = 0;
2708  BaseStation *st = NULL;
2709  const StationSpec *statspec = NULL;
2710  uint tile_layout = 0;
2711 
2712  if (HasStationRail(ti->tile)) {
2713  rti = GetRailTypeInfo(GetRailType(ti->tile));
2714  roadtypes = ROADTYPES_NONE;
2715  total_offset = rti->GetRailtypeSpriteOffset();
2716 
2717  if (IsCustomStationSpecIndex(ti->tile)) {
2718  /* look for customization */
2719  st = BaseStation::GetByTile(ti->tile);
2720  statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
2721 
2722  if (statspec != NULL) {
2723  tile_layout = GetStationGfx(ti->tile);
2724 
2726  uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
2727  if (callback != CALLBACK_FAILED) tile_layout = (callback & ~1) + GetRailStationAxis(ti->tile);
2728  }
2729 
2730  /* Ensure the chosen tile layout is valid for this custom station */
2731  if (statspec->renderdata != NULL) {
2732  layout = &statspec->renderdata[tile_layout < statspec->tiles ? tile_layout : (uint)GetRailStationAxis(ti->tile)];
2733  if (!layout->NeedsPreprocessing()) {
2734  t = layout;
2735  layout = NULL;
2736  }
2737  }
2738  }
2739  }
2740  } else {
2741  roadtypes = IsRoadStop(ti->tile) ? GetRoadTypes(ti->tile) : ROADTYPES_NONE;
2742  total_offset = 0;
2743  }
2744 
2745  StationGfx gfx = GetStationGfx(ti->tile);
2746  if (IsAirport(ti->tile)) {
2747  gfx = GetAirportGfx(ti->tile);
2748  if (gfx >= NEW_AIRPORTTILE_OFFSET) {
2749  const AirportTileSpec *ats = AirportTileSpec::Get(gfx);
2750  if (ats->grf_prop.spritegroup[0] != NULL && DrawNewAirportTile(ti, Station::GetByTile(ti->tile), gfx, ats)) {
2751  return;
2752  }
2753  /* No sprite group (or no valid one) found, meaning no graphics associated.
2754  * Use the substitute one instead */
2755  assert(ats->grf_prop.subst_id != INVALID_AIRPORTTILE);
2756  gfx = ats->grf_prop.subst_id;
2757  }
2758  switch (gfx) {
2759  case APT_RADAR_GRASS_FENCE_SW:
2760  t = &_station_display_datas_airport_radar_grass_fence_sw[GetAnimationFrame(ti->tile)];
2761  break;
2762  case APT_GRASS_FENCE_NE_FLAG:
2763  t = &_station_display_datas_airport_flag_grass_fence_ne[GetAnimationFrame(ti->tile)];
2764  break;
2765  case APT_RADAR_FENCE_SW:
2766  t = &_station_display_datas_airport_radar_fence_sw[GetAnimationFrame(ti->tile)];
2767  break;
2768  case APT_RADAR_FENCE_NE:
2769  t = &_station_display_datas_airport_radar_fence_ne[GetAnimationFrame(ti->tile)];
2770  break;
2771  case APT_GRASS_FENCE_NE_FLAG_2:
2772  t = &_station_display_datas_airport_flag_grass_fence_ne_2[GetAnimationFrame(ti->tile)];
2773  break;
2774  }
2775  }
2776 
2777  Owner owner = GetTileOwner(ti->tile);
2778 
2779  PaletteID palette;
2780  if (Company::IsValidID(owner)) {
2781  palette = COMPANY_SPRITE_COLOUR(owner);
2782  } else {
2783  /* Some stations are not owner by a company, namely oil rigs */
2784  palette = PALETTE_TO_GREY;
2785  }
2786 
2787  if (layout == NULL && (t == NULL || t->seq == NULL)) t = GetStationTileLayout(GetStationType(ti->tile), gfx);
2788 
2789  /* don't show foundation for docks */
2790  if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) {
2791  if (statspec != NULL && HasBit(statspec->flags, SSF_CUSTOM_FOUNDATIONS)) {
2792  /* Station has custom foundations.
2793  * Check whether the foundation continues beyond the tile's upper sides. */
2794  uint edge_info = 0;
2795  int z;
2796  Slope slope = GetFoundationPixelSlope(ti->tile, &z);
2797  if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0);
2798  if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1);
2799  SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, tile_layout, edge_info);
2800  if (image == 0) goto draw_default_foundation;
2801 
2802  if (HasBit(statspec->flags, SSF_EXTENDED_FOUNDATIONS)) {
2803  /* Station provides extended foundations. */
2804 
2805  static const uint8 foundation_parts[] = {
2806  0, 0, 0, 0, // Invalid, Invalid, Invalid, SLOPE_SW
2807  0, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
2808  0, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
2809  7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
2810  };
2811 
2812  AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2813  } else {
2814  /* Draw simple foundations, built up from 8 possible foundation sprites. */
2815 
2816  /* Each set bit represents one of the eight composite sprites to be drawn.
2817  * 'Invalid' entries will not drawn but are included for completeness. */
2818  static const uint8 composite_foundation_parts[] = {
2819  /* Invalid (00000000), Invalid (11010001), Invalid (11100100), SLOPE_SW (11100000) */
2820  0x00, 0xD1, 0xE4, 0xE0,
2821  /* Invalid (11001010), SLOPE_EW (11001001), SLOPE_SE (11000100), SLOPE_WSE (11000000) */
2822  0xCA, 0xC9, 0xC4, 0xC0,
2823  /* Invalid (11010010), SLOPE_NW (10010001), SLOPE_NS (11100100), SLOPE_NWS (10100000) */
2824  0xD2, 0x91, 0xE4, 0xA0,
2825  /* SLOPE_NE (01001010), SLOPE_ENW (00001001), SLOPE_SEN (01000100) */
2826  0x4A, 0x09, 0x44
2827  };
2828 
2829  uint8 parts = composite_foundation_parts[ti->tileh];
2830 
2831  /* If foundations continue beyond the tile's upper sides then
2832  * mask out the last two pieces. */
2833  if (HasBit(edge_info, 0)) ClrBit(parts, 6);
2834  if (HasBit(edge_info, 1)) ClrBit(parts, 7);
2835 
2836  if (parts == 0) {
2837  /* We always have to draw at least one sprite to make sure there is a boundingbox and a sprite with the
2838  * correct offset for the childsprites.
2839  * So, draw the (completely empty) sprite of the default foundations. */
2840  goto draw_default_foundation;
2841  }
2842 
2844  for (int i = 0; i < 8; i++) {
2845  if (HasBit(parts, i)) {
2846  AddSortableSpriteToDraw(image + i, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
2847  }
2848  }
2849  EndSpriteCombine();
2850  }
2851 
2852  OffsetGroundSprite(31, 1);
2854  } else {
2855 draw_default_foundation:
2857  }
2858  }
2859 
2860  if (IsBuoy(ti->tile)) {
2861  DrawWaterClassGround(ti);
2862  SpriteID sprite = GetCanalSprite(CF_BUOY, ti->tile);
2863  if (sprite != 0) total_offset = sprite - SPR_IMG_BUOY;
2864  } else if (IsDock(ti->tile) || (IsOilRig(ti->tile) && IsTileOnWater(ti->tile))) {
2865  if (ti->tileh == SLOPE_FLAT) {
2866  DrawWaterClassGround(ti);
2867  } else {
2868  assert(IsDock(ti->tile));
2869  TileIndex water_tile = ti->tile + TileOffsByDiagDir(GetDockDirection(ti->tile));
2870  WaterClass wc = GetWaterClass(water_tile);
2871  if (wc == WATER_CLASS_SEA) {
2872  DrawShoreTile(ti->tileh);
2873  } else {
2874  DrawClearLandTile(ti, 3);
2875  }
2876  }
2877  } else {
2878  if (layout != NULL) {
2879  /* Sprite layout which needs preprocessing */
2880  bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
2881  uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
2882  uint8 var10;
2883  FOR_EACH_SET_BIT(var10, var10_values) {
2884  uint32 var10_relocation = GetCustomStationRelocation(statspec, st, ti->tile, var10);
2885  layout->ProcessRegisters(var10, var10_relocation, separate_ground);
2886  }
2887  tmp_rail_layout.seq = layout->GetLayout(&tmp_rail_layout.ground);
2888  t = &tmp_rail_layout;
2889  total_offset = 0;
2890  } else if (statspec != NULL) {
2891  /* Simple sprite layout */
2892  ground_relocation = relocation = GetCustomStationRelocation(statspec, st, ti->tile, 0);
2893  if (HasBit(statspec->flags, SSF_SEPARATE_GROUND)) {
2894  ground_relocation = GetCustomStationRelocation(statspec, st, ti->tile, 1);
2895  }
2896  ground_relocation += rti->fallback_railtype;
2897  }
2898 
2899  SpriteID image = t->ground.sprite;
2900  PaletteID pal = t->ground.pal;
2901  RailTrackOffset overlay_offset;
2902  if (rti != NULL && rti->UsesOverlay() && SplitGroundSpriteForOverlay(ti, &image, &overlay_offset)) {
2903  SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND);
2904  DrawGroundSprite(image, PAL_NONE);
2905  DrawGroundSprite(ground + overlay_offset, PAL_NONE);
2906 
2907  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationReservation(ti->tile)) {
2908  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
2909  DrawGroundSprite(overlay + overlay_offset, PALETTE_CRASH);
2910  }
2911  } else {
2912  image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset;
2913  if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation;
2914  DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
2915 
2916  /* PBS debugging, draw reserved tracks darker */
2917  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasStationRail(ti->tile) && HasStationReservation(ti->tile)) {
2918  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
2920  }
2921  }
2922  }
2923 
2925 
2926  if (HasBit(roadtypes, ROADTYPE_TRAM)) {
2927  Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
2928  DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
2929  DrawRoadCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
2930  }
2931 
2932  if (IsRailWaypoint(ti->tile)) {
2933  /* Don't offset the waypoint graphics; they're always the same. */
2934  total_offset = 0;
2935  }
2936 
2937  DrawRailTileSeq(ti, t, TO_BUILDINGS, total_offset, relocation, palette);
2938 }
2939 
2940 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
2941 {
2942  int32 total_offset = 0;
2943  PaletteID pal = COMPANY_SPRITE_COLOUR(_local_company);
2944  const DrawTileSprites *t = GetStationTileLayout(st, image);
2945  const RailtypeInfo *rti = NULL;
2946 
2947  if (railtype != INVALID_RAILTYPE) {
2948  rti = GetRailTypeInfo(railtype);
2949  total_offset = rti->GetRailtypeSpriteOffset();
2950  }
2951 
2952  SpriteID img = t->ground.sprite;
2953  RailTrackOffset overlay_offset;
2954  if (rti != NULL && rti->UsesOverlay() && SplitGroundSpriteForOverlay(NULL, &img, &overlay_offset)) {
2956  DrawSprite(img, PAL_NONE, x, y);
2957  DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
2958  } else {
2959  DrawSprite(img + total_offset, HasBit(img, PALETTE_MODIFIER_COLOUR) ? pal : PAL_NONE, x, y);
2960  }
2961 
2962  if (roadtype == ROADTYPE_TRAM) {
2963  DrawSprite(SPR_TRAMWAY_TRAM + (t->ground.sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
2964  }
2965 
2966  /* Default waypoint has no railtype specific sprites */
2967  DrawRailTileSeqInGUI(x, y, t, st == STATION_WAYPOINT ? 0 : total_offset, 0, pal);
2968 }
2969 
2970 static int GetSlopePixelZ_Station(TileIndex tile, uint x, uint y)
2971 {
2972  return GetTileMaxPixelZ(tile);
2973 }
2974 
2975 static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
2976 {
2977  return FlatteningFoundation(tileh);
2978 }
2979 
2980 static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
2981 {
2982  td->owner[0] = GetTileOwner(tile);
2983  if (IsDriveThroughStopTile(tile)) {
2984  Owner road_owner = INVALID_OWNER;
2985  Owner tram_owner = INVALID_OWNER;
2986  RoadTypes rts = GetRoadTypes(tile);
2987  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
2988  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
2989 
2990  /* Is there a mix of owners? */
2991  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
2992  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
2993  uint i = 1;
2994  if (road_owner != INVALID_OWNER) {
2995  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2996  td->owner[i] = road_owner;
2997  i++;
2998  }
2999  if (tram_owner != INVALID_OWNER) {
3000  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
3001  td->owner[i] = tram_owner;
3002  }
3003  }
3004  }
3006 
3007  if (HasStationTileRail(tile)) {
3008  const StationSpec *spec = GetStationSpec(tile);
3009 
3010  if (spec != NULL) {
3012  td->station_name = spec->name;
3013 
3014  if (spec->grf_prop.grffile != NULL) {
3015  const GRFConfig *gc = GetGRFConfig(spec->grf_prop.grffile->grfid);
3016  td->grf = gc->GetName();
3017  }
3018  }
3019 
3020  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
3021  td->rail_speed = rti->max_speed;
3022  td->railtype = rti->strings.name;
3023  }
3024 
3025  if (IsAirport(tile)) {
3026  const AirportSpec *as = Station::GetByTile(tile)->airport.GetSpec();
3028  td->airport_name = as->name;
3029 
3030  const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
3031  td->airport_tile_name = ats->name;
3032 
3033  if (as->grf_prop.grffile != NULL) {
3034  const GRFConfig *gc = GetGRFConfig(as->grf_prop.grffile->grfid);
3035  td->grf = gc->GetName();
3036  } else if (ats->grf_prop.grffile != NULL) {
3037  const GRFConfig *gc = GetGRFConfig(ats->grf_prop.grffile->grfid);
3038  td->grf = gc->GetName();
3039  }
3040  }
3041 
3042  StringID str;
3043  switch (GetStationType(tile)) {
3044  default: NOT_REACHED();
3045  case STATION_RAIL: str = STR_LAI_STATION_DESCRIPTION_RAILROAD_STATION; break;
3046  case STATION_AIRPORT:
3047  str = (IsHangar(tile) ? STR_LAI_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_LAI_STATION_DESCRIPTION_AIRPORT);
3048  break;
3049  case STATION_TRUCK: str = STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
3050  case STATION_BUS: str = STR_LAI_STATION_DESCRIPTION_BUS_STATION; break;
3051  case STATION_OILRIG: str = STR_INDUSTRY_NAME_OIL_RIG; break;
3052  case STATION_DOCK: str = STR_LAI_STATION_DESCRIPTION_SHIP_DOCK; break;
3053  case STATION_BUOY: str = STR_LAI_STATION_DESCRIPTION_BUOY; break;
3054  case STATION_WAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT; break;
3055  }
3056  td->str = str;
3057 }
3058 
3059 
3060 static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
3061 {
3062  TrackBits trackbits = TRACK_BIT_NONE;
3063 
3064  switch (mode) {
3065  case TRANSPORT_RAIL:
3066  if (HasStationRail(tile) && !IsStationTileBlocked(tile)) {
3067  trackbits = TrackToTrackBits(GetRailStationTrack(tile));
3068  }
3069  break;
3070 
3071  case TRANSPORT_WATER:
3072  /* buoy is coded as a station, it is always on open water */
3073  if (IsBuoy(tile)) {
3074  trackbits = TRACK_BIT_ALL;
3075  /* remove tracks that connect NE map edge */
3076  if (TileX(tile) == 0) trackbits &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
3077  /* remove tracks that connect NW map edge */
3078  if (TileY(tile) == 0) trackbits &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
3079  }
3080  break;
3081 
3082  case TRANSPORT_ROAD:
3083  if ((GetRoadTypes(tile) & sub_mode) != 0 && IsRoadStop(tile)) {
3084  DiagDirection dir = GetRoadStopDir(tile);
3085  Axis axis = DiagDirToAxis(dir);
3086 
3087  if (side != INVALID_DIAGDIR) {
3088  if (axis != DiagDirToAxis(side) || (IsStandardRoadStopTile(tile) && dir != side)) break;
3089  }
3090 
3091  trackbits = AxisToTrackBits(axis);
3092  }
3093  break;
3094 
3095  default:
3096  break;
3097  }
3098 
3100 }
3101 
3102 
3103 static void TileLoop_Station(TileIndex tile)
3104 {
3105  /* FIXME -- GetTileTrackStatus_Station -> animated stationtiles
3106  * hardcoded.....not good */
3107  switch (GetStationType(tile)) {
3108  case STATION_AIRPORT:
3109  AirportTileAnimationTrigger(Station::GetByTile(tile), tile, AAT_TILELOOP);
3110  break;
3111 
3112  case STATION_DOCK:
3113  if (!IsTileFlat(tile)) break; // only handle water part
3114  FALLTHROUGH;
3115 
3116  case STATION_OILRIG: //(station part)
3117  case STATION_BUOY:
3118  TileLoop_Water(tile);
3119  break;
3120 
3121  default: break;
3122  }
3123 }
3124 
3125 
3126 static void AnimateTile_Station(TileIndex tile)
3127 {
3128  if (HasStationRail(tile)) {
3129  AnimateStationTile(tile);
3130  return;
3131  }
3132 
3133  if (IsAirport(tile)) {
3134  AnimateAirportTile(tile);
3135  }
3136 }
3137 
3138 
3139 static bool ClickTile_Station(TileIndex tile)
3140 {
3141  const BaseStation *bst = BaseStation::GetByTile(tile);
3142 
3143  if (bst->facilities & FACIL_WAYPOINT) {
3145  } else if (IsHangar(tile)) {
3146  const Station *st = Station::From(bst);
3148  } else {
3150  }
3151  return true;
3152 }
3153 
3154 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
3155 {
3156  if (v->type == VEH_TRAIN) {
3157  StationID station_id = GetStationIndex(tile);
3158  if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
3159  if (!IsRailStation(tile) || !v->IsFrontEngine()) return VETSB_CONTINUE;
3160 
3161  int station_ahead;
3162  int station_length;
3163  int stop = GetTrainStopLocation(station_id, tile, Train::From(v), &station_ahead, &station_length);
3164 
3165  /* Stop whenever that amount of station ahead + the distance from the
3166  * begin of the platform to the stop location is longer than the length
3167  * of the platform. Station ahead 'includes' the current tile where the
3168  * vehicle is on, so we need to subtract that. */
3169  if (stop + station_ahead - (int)TILE_SIZE >= station_length) return VETSB_CONTINUE;
3170 
3172 
3173  x &= 0xF;
3174  y &= 0xF;
3175 
3176  if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
3177  if (y == TILE_SIZE / 2) {
3178  if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
3179  stop &= TILE_SIZE - 1;
3180 
3181  if (x == stop) {
3182  return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); // enter station
3183  } else if (x < stop) {
3185  uint16 spd = max(0, (stop - x) * 20 - 15);
3186  if (spd < v->cur_speed) v->cur_speed = spd;
3187  }
3188  }
3189  } else if (v->type == VEH_ROAD) {
3190  RoadVehicle *rv = RoadVehicle::From(v);
3191  if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) {
3192  if (IsRoadStop(tile) && rv->IsFrontEngine()) {
3193  /* Attempt to allocate a parking bay in a road stop */
3195  }
3196  }
3197  }
3198 
3199  return VETSB_CONTINUE;
3200 }
3201 
3207 {
3208  /* Collect cargoes accepted since the last big tick. */
3209  CargoTypes cargoes = 0;
3210  for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
3211  if (HasBit(st->goods[cid].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cid);
3212  }
3213 
3214  /* Anything to do? */
3215  if (cargoes == 0) return;
3216 
3217  /* Loop over all houses in the catchment. */
3218  Rect r = st->GetCatchmentRect();
3219  TileArea ta(TileXY(r.left, r.top), TileXY(r.right, r.bottom));
3220  TILE_AREA_LOOP(tile, ta) {
3221  if (IsTileType(tile, MP_HOUSE)) {
3222  WatchedCargoCallback(tile, cargoes);
3223  }
3224  }
3225 }
3226 
3234 {
3235  if (!st->IsInUse()) {
3236  if (++st->delete_ctr >= 8) delete st;
3237  return false;
3238  }
3239 
3240  if (Station::IsExpected(st)) {
3242 
3243  for (CargoID i = 0; i < NUM_CARGO; i++) {
3244  ClrBit(Station::From(st)->goods[i].status, GoodsEntry::GES_ACCEPTED_BIGTICK);
3245  }
3246  }
3247 
3248 
3249  if ((st->facilities & FACIL_WAYPOINT) == 0) UpdateStationAcceptance(Station::From(st), true);
3250 
3251  return true;
3252 }
3253 
3254 static inline void byte_inc_sat(byte *p)
3255 {
3256  byte b = *p + 1;
3257  if (b != 0) *p = b;
3258 }
3259 
3266 static void TruncateCargo(const CargoSpec *cs, GoodsEntry *ge, uint amount = UINT_MAX)
3267 {
3268  /* If truncating also punish the source stations' ratings to
3269  * decrease the flow of incoming cargo. */
3270 
3271  StationCargoAmountMap waiting_per_source;
3272  ge->cargo.Truncate(amount, &waiting_per_source);
3273  for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
3274  Station *source_station = Station::GetIfValid(i->first);
3275  if (source_station == NULL) continue;
3276 
3277  GoodsEntry &source_ge = source_station->goods[cs->Index()];
3278  source_ge.max_waiting_cargo = max(source_ge.max_waiting_cargo, i->second);
3279  }
3280 }
3281 
3282 static void UpdateStationRating(Station *st)
3283 {
3284  bool waiting_changed = false;
3285 
3286  byte_inc_sat(&st->time_since_load);
3287  byte_inc_sat(&st->time_since_unload);
3288 
3289  const CargoSpec *cs;
3290  FOR_ALL_CARGOSPECS(cs) {
3291  GoodsEntry *ge = &st->goods[cs->Index()];
3292  /* Slowly increase the rating back to his original level in the case we
3293  * didn't deliver cargo yet to this station. This happens when a bribe
3294  * failed while you didn't moved that cargo yet to a station. */
3295  if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) {
3296  ge->rating++;
3297  }
3298 
3299  /* Only change the rating if we are moving this cargo */
3300  if (ge->HasRating()) {
3301  byte_inc_sat(&ge->time_since_pickup);
3302  if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) {
3304  ge->last_speed = 0;
3305  TruncateCargo(cs, ge);
3306  waiting_changed = true;
3307  continue;
3308  }
3309 
3310  bool skip = false;
3311  int rating = 0;
3312  uint waiting = ge->cargo.AvailableCount();
3313 
3314  /* num_dests is at least 1 if there is any cargo as
3315  * INVALID_STATION is also a destination.
3316  */
3317  uint num_dests = (uint)ge->cargo.Packets()->MapSize();
3318 
3319  /* Average amount of cargo per next hop, but prefer solitary stations
3320  * with only one or two next hops. They are allowed to have more
3321  * cargo waiting per next hop.
3322  * With manual cargo distribution waiting_avg = waiting / 2 as then
3323  * INVALID_STATION is the only destination.
3324  */
3325  uint waiting_avg = waiting / (num_dests + 1);
3326 
3328  /* Perform custom station rating. If it succeeds the speed, days in transit and
3329  * waiting cargo ratings must not be executed. */
3330 
3331  /* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
3332  uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
3333 
3334  uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
3335  /* Convert to the 'old' vehicle types */
3336  uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
3337  uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
3338  if (callback != CALLBACK_FAILED) {
3339  skip = true;
3340  rating = GB(callback, 0, 14);
3341 
3342  /* Simulate a 15 bit signed value */
3343  if (HasBit(callback, 14)) rating -= 0x4000;
3344  }
3345  }
3346 
3347  if (!skip) {
3348  int b = ge->last_speed - 85;
3349  if (b >= 0) rating += b >> 2;
3350 
3351  byte waittime = ge->time_since_pickup;
3352  if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2;
3353  (waittime > 21) ||
3354  (rating += 25, waittime > 12) ||
3355  (rating += 25, waittime > 6) ||
3356  (rating += 45, waittime > 3) ||
3357  (rating += 35, true);
3358 
3359  (rating -= 90, ge->max_waiting_cargo > 1500) ||
3360  (rating += 55, ge->max_waiting_cargo > 1000) ||
3361  (rating += 35, ge->max_waiting_cargo > 600) ||
3362  (rating += 10, ge->max_waiting_cargo > 300) ||
3363  (rating += 20, ge->max_waiting_cargo > 100) ||
3364  (rating += 10, true);
3365  }
3366 
3367  if (Company::IsValidID(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
3368 
3369  byte age = ge->last_age;
3370  (age >= 3) ||
3371  (rating += 10, age >= 2) ||
3372  (rating += 10, age >= 1) ||
3373  (rating += 13, true);
3374 
3375  {
3376  int or_ = ge->rating; // old rating
3377 
3378  /* only modify rating in steps of -2, -1, 0, 1 or 2 */
3379  ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
3380 
3381  /* if rating is <= 64 and more than 100 items waiting on average per destination,
3382  * remove some random amount of goods from the station */
3383  if (rating <= 64 && waiting_avg >= 100) {
3384  int dec = Random() & 0x1F;
3385  if (waiting_avg < 200) dec &= 7;
3386  waiting -= (dec + 1) * num_dests;
3387  waiting_changed = true;
3388  }
3389 
3390  /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
3391  if (rating <= 127 && waiting != 0) {
3392  uint32 r = Random();
3393  if (rating <= (int)GB(r, 0, 7)) {
3394  /* Need to have int, otherwise it will just overflow etc. */
3395  waiting = max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
3396  waiting_changed = true;
3397  }
3398  }
3399 
3400  /* At some point we really must cap the cargo. Previously this
3401  * was a strict 4095, but now we'll have a less strict, but
3402  * increasingly aggressive truncation of the amount of cargo. */
3403  static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
3404  static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
3405  static const uint MAX_WAITING_CARGO = 1 << 15;
3406 
3407  if (waiting > WAITING_CARGO_THRESHOLD) {
3408  uint difference = waiting - WAITING_CARGO_THRESHOLD;
3409  waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
3410 
3411  waiting = min(waiting, MAX_WAITING_CARGO);
3412  waiting_changed = true;
3413  }
3414 
3415  /* We can't truncate cargo that's already reserved for loading.
3416  * Thus StoredCount() here. */
3417  if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
3418  /* Feed back the exact own waiting cargo at this station for the
3419  * next rating calculation. */
3420  ge->max_waiting_cargo = 0;
3421 
3422  TruncateCargo(cs, ge, ge->cargo.AvailableCount() - waiting);
3423  } else {
3424  /* If the average number per next hop is low, be more forgiving. */
3425  ge->max_waiting_cargo = waiting_avg;
3426  }
3427  }
3428  }
3429  }
3430 
3431  StationID index = st->index;
3432  if (waiting_changed) {
3433  SetWindowDirty(WC_STATION_VIEW, index); // update whole window
3434  } else {
3435  SetWindowWidgetDirty(WC_STATION_VIEW, index, WID_SV_ACCEPT_RATING_LIST); // update only ratings list
3436  }
3437 }
3438 
3447 void RerouteCargo(Station *st, CargoID c, StationID avoid, StationID avoid2)
3448 {
3449  GoodsEntry &ge = st->goods[c];
3450 
3451  /* Reroute cargo in station. */
3452  ge.cargo.Reroute(UINT_MAX, &ge.cargo, avoid, avoid2, &ge);
3453 
3454  /* Reroute cargo staged to be transferred. */
3455  for (std::list<Vehicle *>::iterator it(st->loading_vehicles.begin()); it != st->loading_vehicles.end(); ++it) {
3456  for (Vehicle *v = *it; v != NULL; v = v->Next()) {
3457  if (v->cargo_type != c) continue;
3458  v->cargo.Reroute(UINT_MAX, &v->cargo, avoid, avoid2, &ge);
3459  }
3460  }
3461 }
3462 
3472 {
3473  for (CargoID c = 0; c < NUM_CARGO; ++c) {
3474  const bool auto_distributed = (_settings_game.linkgraph.GetDistributionType(c) != DT_MANUAL);
3475  GoodsEntry &ge = from->goods[c];
3477  if (lg == NULL) continue;
3478  Node node = (*lg)[ge.node];
3479  for (EdgeIterator it(node.Begin()); it != node.End();) {
3480  Edge edge = it->second;
3481  Station *to = Station::Get((*lg)[it->first].Station());
3482  assert(to->goods[c].node == it->first);
3483  ++it; // Do that before removing the edge. Anything else may crash.
3484  assert(_date >= edge.LastUpdate());
3485  uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3);
3486  if ((uint)(_date - edge.LastUpdate()) > timeout) {
3487  bool updated = false;
3488 
3489  if (auto_distributed) {
3490  /* Have all vehicles refresh their next hops before deciding to
3491  * remove the node. */
3492  OrderList *l;
3493  SmallVector<Vehicle *, 32> vehicles;
3494  FOR_ALL_ORDER_LISTS(l) {
3495  bool found_from = false;
3496  bool found_to = false;
3497  for (Order *order = l->GetFirstOrder(); order != NULL; order = order->next) {
3498  if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_IMPLICIT)) continue;
3499  if (order->GetDestination() == from->index) {
3500  found_from = true;
3501  if (found_to) break;
3502  } else if (order->GetDestination() == to->index) {
3503  found_to = true;
3504  if (found_from) break;
3505  }
3506  }
3507  if (!found_to || !found_from) continue;
3508  *(vehicles.Append()) = l->GetFirstSharedVehicle();
3509  }
3510 
3511  Vehicle **iter = vehicles.Begin();
3512  while (iter != vehicles.End()) {
3513  Vehicle *v = *iter;
3514 
3515  LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted.
3516  if (edge.LastUpdate() == _date) {
3517  updated = true;
3518  break;
3519  }
3520 
3521  Vehicle *next_shared = v->NextShared();
3522  if (next_shared) {
3523  *iter = next_shared;
3524  ++iter;
3525  } else {
3526  vehicles.Erase(iter);
3527  }
3528 
3529  if (iter == vehicles.End()) iter = vehicles.Begin();
3530  }
3531  }
3532 
3533  if (!updated) {
3534  /* If it's still considered dead remove it. */
3535  node.RemoveEdge(to->goods[c].node);
3536  ge.flows.DeleteFlows(to->index);
3537  RerouteCargo(from, c, to->index, from->index);
3538  }
3539  } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) {
3540  edge.Restrict();
3541  ge.flows.RestrictFlows(to->index);
3542  RerouteCargo(from, c, to->index, from->index);
3543  } else if (edge.LastRestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastRestrictedUpdate()) > timeout) {
3544  edge.Release();
3545  }
3546  }
3547  assert(_date >= lg->LastCompression());
3548  if ((uint)(_date - lg->LastCompression()) > LinkGraph::COMPRESSION_INTERVAL) {
3549  lg->Compress();
3550  }
3551  }
3552 }
3553 
3563 void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, EdgeUpdateMode mode)
3564 {
3565  GoodsEntry &ge1 = st->goods[cargo];
3566  Station *st2 = Station::Get(next_station_id);
3567  GoodsEntry &ge2 = st2->goods[cargo];
3568  LinkGraph *lg = NULL;
3569  if (ge1.link_graph == INVALID_LINK_GRAPH) {
3570  if (ge2.link_graph == INVALID_LINK_GRAPH) {
3572  lg = new LinkGraph(cargo);
3574  ge2.link_graph = lg->index;
3575  ge2.node = lg->AddNode(st2);
3576  } else {
3577  DEBUG(misc, 0, "Can't allocate link graph");
3578  }
3579  } else {
3580  lg = LinkGraph::Get(ge2.link_graph);
3581  }
3582  if (lg) {
3583  ge1.link_graph = lg->index;
3584  ge1.node = lg->AddNode(st);
3585  }
3586  } else if (ge2.link_graph == INVALID_LINK_GRAPH) {
3587  lg = LinkGraph::Get(ge1.link_graph);
3588  ge2.link_graph = lg->index;
3589  ge2.node = lg->AddNode(st2);
3590  } else {
3591  lg = LinkGraph::Get(ge1.link_graph);
3592  if (ge1.link_graph != ge2.link_graph) {
3593  LinkGraph *lg2 = LinkGraph::Get(ge2.link_graph);
3594  if (lg->Size() < lg2->Size()) {
3596  lg2->Merge(lg); // Updates GoodsEntries of lg
3597  lg = lg2;
3598  } else {
3600  lg->Merge(lg2); // Updates GoodsEntries of lg2
3601  }
3602  }
3603  }
3604  if (lg != NULL) {
3605  (*lg)[ge1.node].UpdateEdge(ge2.node, capacity, usage, mode);
3606  }
3607 }
3608 
3615 void IncreaseStats(Station *st, const Vehicle *front, StationID next_station_id)
3616 {
3617  for (const Vehicle *v = front; v != NULL; v = v->Next()) {
3618  if (v->refit_cap > 0) {
3619  /* The cargo count can indeed be higher than the refit_cap if
3620  * wagons have been auto-replaced and subsequently auto-
3621  * refitted to a higher capacity. The cargo gets redistributed
3622  * among the wagons in that case.
3623  * As usage is not such an important figure anyway we just
3624  * ignore the additional cargo then.*/
3625  IncreaseStats(st, v->cargo_type, next_station_id, v->refit_cap,
3627  }
3628  }
3629 }
3630 
3631 /* called for every station each tick */
3632 static void StationHandleSmallTick(BaseStation *st)
3633 {
3634  if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
3635 
3636  byte b = st->delete_ctr + 1;
3637  if (b >= STATION_RATING_TICKS) b = 0;
3638  st->delete_ctr = b;
3639 
3640  if (b == 0) UpdateStationRating(Station::From(st));
3641 }
3642 
3643 void OnTick_Station()
3644 {
3645  if (_game_mode == GM_EDITOR) return;
3646 
3647  BaseStation *st;
3648  FOR_ALL_BASE_STATIONS(st) {
3649  StationHandleSmallTick(st);
3650 
3651  /* Clean up the link graph about once a week. */
3652  if (Station::IsExpected(st) && (_tick_counter + st->index) % STATION_LINKGRAPH_TICKS == 0) {
3654  };
3655 
3656  /* Run STATION_ACCEPTANCE_TICKS = 250 tick interval trigger for station animation.
3657  * Station index is included so that triggers are not all done
3658  * at the same time. */
3659  if ((_tick_counter + st->index) % STATION_ACCEPTANCE_TICKS == 0) {
3660  /* Stop processing this station if it was deleted */
3661  if (!StationHandleBigTick(st)) continue;
3662  TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
3663  if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
3664  }
3665  }
3666 }
3667 
3670 {
3671  Station *st;
3672 
3673  FOR_ALL_STATIONS(st) {
3674  for (CargoID i = 0; i < NUM_CARGO; i++) {
3675  GoodsEntry *ge = &st->goods[i];
3678  }
3679  }
3680 }
3681 
3682 
3683 void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
3684 {
3685  Station *st;
3686 
3687  FOR_ALL_STATIONS(st) {
3688  if (st->owner == owner &&
3689  DistanceManhattan(tile, st->xy) <= radius) {
3690  for (CargoID i = 0; i < NUM_CARGO; i++) {
3691  GoodsEntry *ge = &st->goods[i];
3692 
3693  if (ge->status != 0) {
3694  ge->rating = Clamp(ge->rating + amount, 0, 255);
3695  }
3696  }
3697  }
3698  }
3699 }
3700 
3701 static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
3702 {
3703  /* We can't allocate a CargoPacket? Then don't do anything
3704  * at all; i.e. just discard the incoming cargo. */
3705  if (!CargoPacket::CanAllocateItem()) return 0;
3706 
3707  GoodsEntry &ge = st->goods[type];
3708  amount += ge.amount_fract;
3709  ge.amount_fract = GB(amount, 0, 8);
3710 
3711  amount >>= 8;
3712  /* No new "real" cargo item yet. */
3713  if (amount == 0) return 0;
3714 
3715  StationID next = ge.GetVia(st->index);
3716  ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id), next);
3717  LinkGraph *lg = NULL;
3718  if (ge.link_graph == INVALID_LINK_GRAPH) {
3720  lg = new LinkGraph(type);
3722  ge.link_graph = lg->index;
3723  ge.node = lg->AddNode(st);
3724  } else {
3725  DEBUG(misc, 0, "Can't allocate link graph");
3726  }
3727  } else {
3728  lg = LinkGraph::Get(ge.link_graph);
3729  }
3730  if (lg != NULL) (*lg)[ge.node].UpdateSupply(amount);
3731 
3732  if (!ge.HasRating()) {
3735  }
3736 
3738  TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
3739  AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
3740 
3742  st->MarkTilesDirty(true);
3743  return amount;
3744 }
3745 
3746 static bool IsUniqueStationName(const char *name)
3747 {
3748  const Station *st;
3749 
3750  FOR_ALL_STATIONS(st) {
3751  if (st->name != NULL && strcmp(st->name, name) == 0) return false;
3752  }
3753 
3754  return true;
3755 }
3756 
3766 CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
3767 {
3768  Station *st = Station::GetIfValid(p1);
3769  if (st == NULL) return CMD_ERROR;
3770 
3771  CommandCost ret = CheckOwnership(st->owner);
3772  if (ret.Failed()) return ret;
3773 
3774  bool reset = StrEmpty(text);
3775 
3776  if (!reset) {
3778  if (!IsUniqueStationName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
3779  }
3780 
3781  if (flags & DC_EXEC) {
3782  free(st->name);
3783  st->name = reset ? NULL : stredup(text);
3784 
3785  st->UpdateVirtCoord();
3787  }
3788 
3789  return CommandCost();
3790 }
3791 
3798 void FindStationsAroundTiles(const TileArea &location, StationList *stations)
3799 {
3800  /* area to search = producer plus station catchment radius */
3802 
3803  uint x = TileX(location.tile);
3804  uint y = TileY(location.tile);
3805 
3806  uint min_x = (x > max_rad) ? x - max_rad : 0;
3807  uint max_x = x + location.w + max_rad;
3808  uint min_y = (y > max_rad) ? y - max_rad : 0;
3809  uint max_y = y + location.h + max_rad;
3810 
3811  if (min_x == 0 && _settings_game.construction.freeform_edges) min_x = 1;
3812  if (min_y == 0 && _settings_game.construction.freeform_edges) min_y = 1;
3813  if (max_x >= MapSizeX()) max_x = MapSizeX() - 1;
3814  if (max_y >= MapSizeY()) max_y = MapSizeY() - 1;
3815 
3816  for (uint cy = min_y; cy < max_y; cy++) {
3817  for (uint cx = min_x; cx < max_x; cx++) {
3818  TileIndex cur_tile = TileXY(cx, cy);
3819  if (!IsTileType(cur_tile, MP_STATION)) continue;
3820 
3821  Station *st = Station::GetByTile(cur_tile);
3822  /* st can be NULL in case of waypoints */
3823  if (st == NULL) continue;
3824 
3826  int rad = st->GetCatchmentRadius();
3827  int rad_x = cx - x;
3828  int rad_y = cy - y;
3829 
3830  if (rad_x < -rad || rad_x >= rad + location.w) continue;
3831  if (rad_y < -rad || rad_y >= rad + location.h) continue;
3832  }
3833 
3834  /* Insert the station in the set. This will fail if it has
3835  * already been added.
3836  */
3837  stations->Include(st);
3838  }
3839  }
3840 }
3841 
3847 {
3848  if (this->tile != INVALID_TILE) {
3849  FindStationsAroundTiles(*this, &this->stations);
3850  this->tile = INVALID_TILE;
3851  }
3852  return &this->stations;
3853 }
3854 
3855 uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
3856 {
3857  /* Return if nothing to do. Also the rounding below fails for 0. */
3858  if (amount == 0) return 0;
3859 
3860  Station *st1 = NULL; // Station with best rating
3861  Station *st2 = NULL; // Second best station
3862  uint best_rating1 = 0; // rating of st1
3863  uint best_rating2 = 0; // rating of st2
3864 
3865  for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
3866  Station *st = *st_iter;
3867 
3868  /* Is the station reserved exclusively for somebody else? */
3869  if (st->owner != OWNER_NONE && st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
3870 
3871  if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
3872 
3873  if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) continue; // Selectively servicing stations, and not this one
3874 
3875  if (IsCargoInClass(type, CC_PASSENGERS)) {
3876  if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
3877  } else {
3878  if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
3879  }
3880 
3881  /* This station can be used, add it to st1/st2 */
3882  if (st1 == NULL || st->goods[type].rating >= best_rating1) {
3883  st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
3884  } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
3885  st2 = st; best_rating2 = st->goods[type].rating;
3886  }
3887  }
3888 
3889  /* no stations around at all? */
3890  if (st1 == NULL) return 0;
3891 
3892  /* From now we'll calculate with fractal cargo amounts.
3893  * First determine how much cargo we really have. */
3894  amount *= best_rating1 + 1;
3895 
3896  if (st2 == NULL) {
3897  /* only one station around */
3898  return UpdateStationWaiting(st1, type, amount, source_type, source_id);
3899  }
3900 
3901  /* several stations around, the best two (highest rating) are in st1 and st2 */
3902  assert(st1 != NULL);
3903  assert(st2 != NULL);
3904  assert(best_rating1 != 0 || best_rating2 != 0);
3905 
3906  /* Then determine the amount the worst station gets. We do it this way as the
3907  * best should get a bonus, which in this case is the rounding difference from
3908  * this calculation. In reality that will mean the bonus will be pretty low.
3909  * Nevertheless, the best station should always get the most cargo regardless
3910  * of rounding issues. */
3911  uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
3912  assert(worst_cargo <= (amount - worst_cargo));
3913 
3914  /* And then send the cargo to the stations! */
3915  uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
3916  /* These two UpdateStationWaiting's can't be in the statement as then the order
3917  * of execution would be undefined and that could cause desyncs with callbacks. */
3918  return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
3919 }
3920 
3921 void BuildOilRig(TileIndex tile)
3922 {
3923  if (!Station::CanAllocateItem()) {
3924  DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
3925  return;
3926  }
3927 
3928  Station *st = new Station(tile);
3929  st->town = ClosestTownFromTile(tile, UINT_MAX);
3930 
3931  st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
3932 
3933  assert(IsTileType(tile, MP_INDUSTRY));
3934  DeleteAnimatedTile(tile);
3935  MakeOilrig(tile, st->index, GetWaterClass(tile));
3936 
3937  st->owner = OWNER_NONE;
3938  st->airport.type = AT_OILRIG;
3939  st->airport.Add(tile);
3940  st->dock_tile = tile;
3942  st->build_date = _date;
3943 
3944  st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
3945 
3946  st->UpdateVirtCoord();
3947  UpdateStationAcceptance(st, false);
3949 }
3950 
3951 void DeleteOilRig(TileIndex tile)
3952 {
3953  Station *st = Station::GetByTile(tile);
3954 
3955  MakeWaterKeepingClass(tile, OWNER_NONE);
3956 
3957  st->dock_tile = INVALID_TILE;
3958  st->airport.Clear();
3959  st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK);
3960  st->airport.flags = 0;
3961 
3962  st->rect.AfterRemoveTile(st, tile);
3963 
3964  st->UpdateVirtCoord();
3966  if (!st->IsInUse()) delete st;
3967 }
3968 
3969 static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
3970 {
3971  if (IsRoadStopTile(tile)) {
3972  for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
3973  /* Update all roadtypes, no matter if they are present */
3974  if (GetRoadOwner(tile, rt) == old_owner) {
3975  if (HasTileRoadType(tile, rt)) {
3976  /* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
3977  Company::Get(old_owner)->infrastructure.road[rt] -= 2;
3978  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2;
3979  }
3980  SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
3981  }
3982  }
3983  }
3984 
3985  if (!IsTileOwner(tile, old_owner)) return;
3986 
3987  if (new_owner != INVALID_OWNER) {
3988  /* Update company infrastructure counts. Only do it here
3989  * if the new owner is valid as otherwise the clear
3990  * command will do it for us. No need to dirty windows
3991  * here, we'll redraw the whole screen anyway.*/
3992  Company *old_company = Company::Get(old_owner);
3993  Company *new_company = Company::Get(new_owner);
3994 
3995  /* Update counts for underlying infrastructure. */
3996  switch (GetStationType(tile)) {
3997  case STATION_RAIL:
3998  case STATION_WAYPOINT:
3999  if (!IsStationTileBlocked(tile)) {
4000  old_company->infrastructure.rail[GetRailType(tile)]--;
4001  new_company->infrastructure.rail[GetRailType(tile)]++;
4002  }
4003  break;
4004 
4005  case STATION_BUS:
4006  case STATION_TRUCK:
4007  /* Road stops were already handled above. */
4008  break;
4009 
4010  case STATION_BUOY:
4011  case STATION_DOCK:
4012  if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
4013  old_company->infrastructure.water--;
4014  new_company->infrastructure.water++;
4015  }
4016  break;
4017 
4018  default:
4019  break;
4020  }
4021 
4022  /* Update station tile count. */
4023  if (!IsBuoy(tile) && !IsAirport(tile)) {
4024  old_company->infrastructure.station--;
4025  new_company->infrastructure.station++;
4026  }
4027 
4028  /* for buoys, owner of tile is owner of water, st->owner == OWNER_NONE */
4029  SetTileOwner(tile, new_owner);
4031  } else {
4032  if (IsDriveThroughStopTile(tile)) {
4033  /* Remove the drive-through road stop */
4034  DoCommand(tile, 1 | 1 << 8, (GetStationType(tile) == STATION_TRUCK) ? ROADSTOP_TRUCK : ROADSTOP_BUS, DC_EXEC | DC_BANKRUPT, CMD_REMOVE_ROAD_STOP);
4035  assert(IsTileType(tile, MP_ROAD));
4036  /* Change owner of tile and all roadtypes */
4037  ChangeTileOwner(tile, old_owner, new_owner);
4038  } else {
4040  /* Set tile owner of water under (now removed) buoy and dock to OWNER_NONE.
4041  * Update owner of buoy if it was not removed (was in orders).
4042  * Do not update when owned by OWNER_WATER (sea and rivers). */
4043  if ((IsTileType(tile, MP_WATER) || IsBuoyTile(tile)) && IsTileOwner(tile, old_owner)) SetTileOwner(tile, OWNER_NONE);
4044  }
4045  }
4046 }
4047 
4057 {
4058  /* Yeah... water can always remove stops, right? */
4059  if (_current_company == OWNER_WATER) return true;
4060 
4061  RoadTypes rts = GetRoadTypes(tile);
4062  if (HasBit(rts, ROADTYPE_TRAM)) {
4063  Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
4064  if (tram_owner != OWNER_NONE && CheckOwnership(tram_owner).Failed()) return false;
4065  }
4066  if (HasBit(rts, ROADTYPE_ROAD)) {
4067  Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
4068  if (road_owner != OWNER_TOWN) {
4069  if (road_owner != OWNER_NONE && CheckOwnership(road_owner).Failed()) return false;
4070  } else {
4071  if (CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags).Failed()) return false;
4072  }
4073  }
4074 
4075  return true;
4076 }
4077 
4085 {
4086  if (flags & DC_AUTO) {
4087  switch (GetStationType(tile)) {
4088  default: break;
4089  case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
4090  case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
4091  case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
4092  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);
4093  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);
4094  case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
4095  case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
4096  case STATION_OILRIG:
4097  SetDParam(1, STR_INDUSTRY_NAME_OIL_RIG);
4098  return_cmd_error(STR_ERROR_GENERIC_OBJECT_IN_THE_WAY);
4099  }
4100  }
4101 
4102  switch (GetStationType(tile)) {
4103  case STATION_RAIL: return RemoveRailStation(tile, flags);
4104  case STATION_WAYPOINT: return RemoveRailWaypoint(tile, flags);
4105  case STATION_AIRPORT: return RemoveAirport(tile, flags);
4106  case STATION_TRUCK:
4107  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4108  return_cmd_error(STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
4109  }
4110  return RemoveRoadStop(tile, flags);
4111  case STATION_BUS:
4112  if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
4113  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
4114  }
4115  return RemoveRoadStop(tile, flags);
4116  case STATION_BUOY: return RemoveBuoy(tile, flags);
4117  case STATION_DOCK: return RemoveDock(tile, flags);
4118  default: break;
4119  }
4120 
4121  return CMD_ERROR;
4122 }
4123 
4124 static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
4125 {
4127  /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
4128  * TTDP does not call it.
4129  */
4130  if (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) {
4131  switch (GetStationType(tile)) {
4132  case STATION_WAYPOINT:
4133  case STATION_RAIL: {
4134  DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
4135  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4136  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4137  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4138  }
4139 
4140  case STATION_AIRPORT:
4141  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4142 
4143  case STATION_TRUCK:
4144  case STATION_BUS: {
4145  DiagDirection direction = GetRoadStopDir(tile);
4146  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
4147  if (IsDriveThroughStopTile(tile)) {
4148  if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
4149  }
4150  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
4151  }
4152 
4153  default: break;
4154  }
4155  }
4156  }
4157  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
4158 }
4159 
4165 uint FlowStat::GetShare(StationID st) const
4166 {
4167  uint32 prev = 0;
4168  for (SharesMap::const_iterator it = this->shares.begin(); it != this->shares.end(); ++it) {
4169  if (it->second == st) {
4170  return it->first - prev;
4171  } else {
4172  prev = it->first;
4173  }
4174  }
4175  return 0;
4176 }
4177 
4184 StationID FlowStat::GetVia(StationID excluded, StationID excluded2) const
4185 {
4186  if (this->unrestricted == 0) return INVALID_STATION;
4187  assert(!this->shares.empty());
4188  SharesMap::const_iterator it = this->shares.upper_bound(RandomRange(this->unrestricted));
4189  assert(it != this->shares.end() && it->first <= this->unrestricted);
4190  if (it->second != excluded && it->second != excluded2) return it->second;
4191 
4192  /* We've hit one of the excluded stations.
4193  * Draw another share, from outside its range. */
4194 
4195  uint end = it->first;
4196  uint begin = (it == this->shares.begin() ? 0 : (--it)->first);
4197  uint interval = end - begin;
4198  if (interval >= this->unrestricted) return INVALID_STATION; // Only one station in the map.
4199  uint new_max = this->unrestricted - interval;
4200  uint rand = RandomRange(new_max);
4201  SharesMap::const_iterator it2 = (rand < begin) ? this->shares.upper_bound(rand) :
4202  this->shares.upper_bound(rand + interval);
4203  assert(it2 != this->shares.end() && it2->first <= this->unrestricted);
4204  if (it2->second != excluded && it2->second != excluded2) return it2->second;
4205 
4206  /* We've hit the second excluded station.
4207  * Same as before, only a bit more complicated. */
4208 
4209  uint end2 = it2->first;
4210  uint begin2 = (it2 == this->shares.begin() ? 0 : (--it2)->first);
4211  uint interval2 = end2 - begin2;
4212  if (interval2 >= new_max) return INVALID_STATION; // Only the two excluded stations in the map.
4213  new_max -= interval2;
4214  if (begin > begin2) {
4215  Swap(begin, begin2);
4216  Swap(end, end2);
4217  Swap(interval, interval2);
4218  }
4219  rand = RandomRange(new_max);
4220  SharesMap::const_iterator it3 = this->shares.upper_bound(this->unrestricted);
4221  if (rand < begin) {
4222  it3 = this->shares.upper_bound(rand);
4223  } else if (rand < begin2 - interval) {
4224  it3 = this->shares.upper_bound(rand + interval);
4225  } else {
4226  it3 = this->shares.upper_bound(rand + interval + interval2);
4227  }
4228  assert(it3 != this->shares.end() && it3->first <= this->unrestricted);
4229  return it3->second;
4230 }
4231 
4238 {
4239  assert(!this->shares.empty());
4240  SharesMap new_shares;
4241  uint i = 0;
4242  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4243  new_shares[++i] = it->second;
4244  if (it->first == this->unrestricted) this->unrestricted = i;
4245  }
4246  this->shares.swap(new_shares);
4247  assert(!this->shares.empty() && this->unrestricted <= (--this->shares.end())->first);
4248 }
4249 
4256 void FlowStat::ChangeShare(StationID st, int flow)
4257 {
4258  /* We assert only before changing as afterwards the shares can actually
4259  * be empty. In that case the whole flow stat must be deleted then. */
4260  assert(!this->shares.empty());
4261 
4262  uint removed_shares = 0;
4263  uint added_shares = 0;
4264  uint last_share = 0;
4265  SharesMap new_shares;
4266  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4267  if (it->second == st) {
4268  if (flow < 0) {
4269  uint share = it->first - last_share;
4270  if (flow == INT_MIN || (uint)(-flow) >= share) {
4271  removed_shares += share;
4272  if (it->first <= this->unrestricted) this->unrestricted -= share;
4273  if (flow != INT_MIN) flow += share;
4274  last_share = it->first;
4275  continue; // remove the whole share
4276  }
4277  removed_shares += (uint)(-flow);
4278  } else {
4279  added_shares += (uint)(flow);
4280  }
4281  if (it->first <= this->unrestricted) this->unrestricted += flow;
4282 
4283  /* If we don't continue above the whole flow has been added or
4284  * removed. */
4285  flow = 0;
4286  }
4287  new_shares[it->first + added_shares - removed_shares] = it->second;
4288  last_share = it->first;
4289  }
4290  if (flow > 0) {
4291  new_shares[last_share + (uint)flow] = st;
4292  if (this->unrestricted < last_share) {
4293  this->ReleaseShare(st);
4294  } else {
4295  this->unrestricted += flow;
4296  }
4297  }
4298  this->shares.swap(new_shares);
4299 }
4300 
4306 void FlowStat::RestrictShare(StationID st)
4307 {
4308  assert(!this->shares.empty());
4309  uint flow = 0;
4310  uint last_share = 0;
4311  SharesMap new_shares;
4312  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4313  if (flow == 0) {
4314  if (it->first > this->unrestricted) return; // Not present or already restricted.
4315  if (it->second == st) {
4316  flow = it->first - last_share;
4317  this->unrestricted -= flow;
4318  } else {
4319  new_shares[it->first] = it->second;
4320  }
4321  } else {
4322  new_shares[it->first - flow] = it->second;
4323  }
4324  last_share = it->first;
4325  }
4326  if (flow == 0) return;
4327  new_shares[last_share + flow] = st;
4328  this->shares.swap(new_shares);
4329  assert(!this->shares.empty());
4330 }
4331 
4337 void FlowStat::ReleaseShare(StationID st)
4338 {
4339  assert(!this->shares.empty());
4340  uint flow = 0;
4341  uint next_share = 0;
4342  bool found = false;
4343  for (SharesMap::reverse_iterator it(this->shares.rbegin()); it != this->shares.rend(); ++it) {
4344  if (it->first < this->unrestricted) return; // Note: not <= as the share may hit the limit.
4345  if (found) {
4346  flow = next_share - it->first;
4347  this->unrestricted += flow;
4348  break;
4349  } else {
4350  if (it->first == this->unrestricted) return; // !found -> Limit not hit.
4351  if (it->second == st) found = true;
4352  }
4353  next_share = it->first;
4354  }
4355  if (flow == 0) return;
4356  SharesMap new_shares;
4357  new_shares[flow] = st;
4358  for (SharesMap::iterator it(this->shares.begin()); it != this->shares.end(); ++it) {
4359  if (it->second != st) {
4360  new_shares[flow + it->first] = it->second;
4361  } else {
4362  flow = 0;
4363  }
4364  }
4365  this->shares.swap(new_shares);
4366  assert(!this->shares.empty());
4367 }
4368 
4374 void FlowStat::ScaleToMonthly(uint runtime)
4375 {
4376  assert(runtime > 0);
4377  SharesMap new_shares;
4378  uint share = 0;
4379  for (SharesMap::iterator i = this->shares.begin(); i != this->shares.end(); ++i) {
4380  share = max(share + 1, i->first * 30 / runtime);
4381  new_shares[share] = i->second;
4382  if (this->unrestricted == i->first) this->unrestricted = share;
4383  }
4384  this->shares.swap(new_shares);
4385 }
4386 
4393 void FlowStatMap::AddFlow(StationID origin, StationID via, uint flow)
4394 {
4395  FlowStatMap::iterator origin_it = this->find(origin);
4396  if (origin_it == this->end()) {
4397  this->insert(std::make_pair(origin, FlowStat(via, flow)));
4398  } else {
4399  origin_it->second.ChangeShare(via, flow);
4400  assert(!origin_it->second.GetShares()->empty());
4401  }
4402 }
4403 
4412 void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow)
4413 {
4414  FlowStatMap::iterator prev_it = this->find(origin);
4415  if (prev_it == this->end()) {
4416  FlowStat fs(via, flow);
4417  fs.AppendShare(INVALID_STATION, flow);
4418  this->insert(std::make_pair(origin, fs));
4419  } else {
4420  prev_it->second.ChangeShare(via, flow);
4421  prev_it->second.ChangeShare(INVALID_STATION, flow);
4422  assert(!prev_it->second.GetShares()->empty());
4423  }
4424 }
4425 
4431 {
4432  for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
4433  FlowStat &fs = i->second;
4434  uint local = fs.GetShare(INVALID_STATION);
4435  if (local > INT_MAX) { // make sure it fits in an int
4436  fs.ChangeShare(self, -INT_MAX);
4437  fs.ChangeShare(INVALID_STATION, -INT_MAX);
4438  local -= INT_MAX;
4439  }
4440  fs.ChangeShare(self, -(int)local);
4441  fs.ChangeShare(INVALID_STATION, -(int)local);
4442 
4443  /* If the local share is used up there must be a share for some
4444  * remote station. */
4445  assert(!fs.GetShares()->empty());
4446  }
4447 }
4448 
4456 {
4457  StationIDStack ret;
4458  for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
4459  FlowStat &s_flows = f_it->second;
4460  s_flows.ChangeShare(via, INT_MIN);
4461  if (s_flows.GetShares()->empty()) {
4462  ret.Push(f_it->first);
4463  this->erase(f_it++);
4464  } else {
4465  ++f_it;
4466  }
4467  }
4468  return ret;
4469 }
4470 
4475 void FlowStatMap::RestrictFlows(StationID via)
4476 {
4477  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4478  it->second.RestrictShare(via);
4479  }
4480 }
4481 
4486 void FlowStatMap::ReleaseFlows(StationID via)
4487 {
4488  for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
4489  it->second.ReleaseShare(via);
4490  }
4491 }
4492 
4498 {
4499  uint ret = 0;
4500  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4501  ret += (--(i->second.GetShares()->end()))->first;
4502  }
4503  return ret;
4504 }
4505 
4511 uint FlowStatMap::GetFlowVia(StationID via) const
4512 {
4513  uint ret = 0;
4514  for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
4515  ret += i->second.GetShare(via);
4516  }
4517  return ret;
4518 }
4519 
4525 uint FlowStatMap::GetFlowFrom(StationID from) const
4526 {
4527  FlowStatMap::const_iterator i = this->find(from);
4528  if (i == this->end()) return 0;
4529  return (--(i->second.GetShares()->end()))->first;
4530 }
4531 
4538 uint FlowStatMap::GetFlowFromVia(StationID from, StationID via) const
4539 {
4540  FlowStatMap::const_iterator i = this->find(from);
4541  if (i == this->end()) return 0;
4542  return i->second.GetShare(via);
4543 }
4544 
4545 extern const TileTypeProcs _tile_type_station_procs = {
4546  DrawTile_Station, // draw_tile_proc
4547  GetSlopePixelZ_Station, // get_slope_z_proc
4548  ClearTile_Station, // clear_tile_proc
4549  NULL, // add_accepted_cargo_proc
4550  GetTileDesc_Station, // get_tile_desc_proc
4551  GetTileTrackStatus_Station, // get_tile_track_status_proc
4552  ClickTile_Station, // click_tile_proc
4553  AnimateTile_Station, // animate_tile_proc
4554  TileLoop_Station, // tile_loop_proc
4555  ChangeTileOwner_Station, // change_tile_owner_proc
4556  NULL, // add_produced_cargo_proc
4557  VehicleEnter_Station, // vehicle_enter_tile_proc
4558  GetFoundation_Station, // get_foundation_proc
4559  TerraformTile_Station, // terraform_tile_proc
4560 };
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:48
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:3201
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:514
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:47
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:2179
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:46
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:3319
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:59
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:2270
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:55
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:1100
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:1517
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:86
#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:58
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:1146
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:34
this bit is set when a recolouring process is in action
Definition: sprites.h:1520
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:3215
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:1580
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:659
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:112
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:54
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:56
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:91
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
void AfterStationTileSetChange(bool adding, StationType type)
After adding/removing tiles to station, update some station-related stuff.
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:88
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:57
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:834
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:3301
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.