OpenTTD
newgrf_station.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "debug.h"
12 #include "station_base.h"
13 #include "waypoint_base.h"
14 #include "roadstop_base.h"
15 #include "newgrf_cargo.h"
16 #include "newgrf_station.h"
17 #include "newgrf_spritegroup.h"
18 #include "newgrf_sound.h"
19 #include "newgrf_railtype.h"
20 #include "town.h"
21 #include "newgrf_town.h"
22 #include "company_func.h"
23 #include "tunnelbridge_map.h"
24 #include "newgrf_animation_base.h"
25 #include "newgrf_class_func.h"
26 
27 #include "safeguards.h"
28 
29 
30 template <typename Tspec, typename Tid, Tid Tmax>
32 {
33  /* Set up initial data */
34  classes[0].global_id = 'DFLT';
35  classes[0].name = STR_STATION_CLASS_DFLT;
36  classes[0].Insert(nullptr);
37 
38  classes[1].global_id = 'WAYP';
39  classes[1].name = STR_STATION_CLASS_WAYP;
40  classes[1].Insert(nullptr);
41 }
42 
43 template <typename Tspec, typename Tid, Tid Tmax>
45 {
46  return true;
47 }
48 
50 
51 static const uint NUM_STATIONSSPECS_PER_STATION = 255;
52 
53 enum TriggerArea {
54  TA_TILE,
55  TA_PLATFORM,
56  TA_WHOLE,
57 };
58 
59 struct ETileArea : TileArea {
60  ETileArea(const BaseStation *st, TileIndex tile, TriggerArea ta)
61  {
62  switch (ta) {
63  default: NOT_REACHED();
64 
65  case TA_TILE:
66  this->tile = tile;
67  this->w = 1;
68  this->h = 1;
69  break;
70 
71  case TA_PLATFORM: {
72  TileIndex start, end;
73  Axis axis = GetRailStationAxis(tile);
75 
76  for (end = tile; IsRailStationTile(end + delta) && IsCompatibleTrainStationTile(end + delta, tile); end += delta) { /* Nothing */ }
77  for (start = tile; IsRailStationTile(start - delta) && IsCompatibleTrainStationTile(start - delta, tile); start -= delta) { /* Nothing */ }
78 
79  this->tile = start;
80  this->w = TileX(end) - TileX(start) + 1;
81  this->h = TileY(end) - TileY(start) + 1;
82  break;
83  }
84 
85  case TA_WHOLE:
86  st->GetTileArea(this, Station::IsExpected(st) ? STATION_RAIL : STATION_WAYPOINT);
87  break;
88  }
89  }
90 };
91 
92 
105 uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, int y, bool centred)
106 {
107  uint32 retval = 0;
108 
109  if (axis == AXIS_X) {
110  Swap(platforms, length);
111  Swap(x, y);
112  }
113 
114  if (centred) {
115  x -= platforms / 2;
116  y -= length / 2;
117  x = Clamp(x, -8, 7);
118  y = Clamp(y, -8, 7);
119  SB(retval, 0, 4, y & 0xF);
120  SB(retval, 4, 4, x & 0xF);
121  } else {
122  SB(retval, 0, 4, min(15, y));
123  SB(retval, 4, 4, min(15, length - y - 1));
124  SB(retval, 8, 4, min(15, x));
125  SB(retval, 12, 4, min(15, platforms - x - 1));
126  }
127  SB(retval, 16, 4, min(15, length));
128  SB(retval, 20, 4, min(15, platforms));
129  SB(retval, 24, 4, tile);
130 
131  return retval;
132 }
133 
134 
143 static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
144 {
145  byte orig_type = 0;
146  Axis orig_axis = AXIS_X;
147  StationID sid = GetStationIndex(tile);
148 
149  if (check_type) orig_type = GetCustomStationSpecIndex(tile);
150  if (check_axis) orig_axis = GetRailStationAxis(tile);
151 
152  for (;;) {
153  TileIndex new_tile = TILE_ADD(tile, delta);
154 
155  if (!IsTileType(new_tile, MP_STATION) || GetStationIndex(new_tile) != sid) break;
156  if (!HasStationRail(new_tile)) break;
157  if (check_type && GetCustomStationSpecIndex(new_tile) != orig_type) break;
158  if (check_axis && GetRailStationAxis(new_tile) != orig_axis) break;
159 
160  tile = new_tile;
161  }
162  return tile;
163 }
164 
165 
166 static uint32 GetPlatformInfoHelper(TileIndex tile, bool check_type, bool check_axis, bool centred)
167 {
168  int tx = TileX(tile);
169  int ty = TileY(tile);
170  int sx = TileX(FindRailStationEnd(tile, TileDiffXY(-1, 0), check_type, check_axis));
171  int sy = TileY(FindRailStationEnd(tile, TileDiffXY( 0, -1), check_type, check_axis));
172  int ex = TileX(FindRailStationEnd(tile, TileDiffXY( 1, 0), check_type, check_axis)) + 1;
173  int ey = TileY(FindRailStationEnd(tile, TileDiffXY( 0, 1), check_type, check_axis)) + 1;
174 
175  tx -= sx; ex -= sx;
176  ty -= sy; ey -= sy;
177 
178  return GetPlatformInfo(GetRailStationAxis(tile), GetStationGfx(tile), ex, ey, tx, ty, centred);
179 }
180 
181 
182 static uint32 GetRailContinuationInfo(TileIndex tile)
183 {
184  /* Tile offsets and exit dirs for X axis */
185  static const Direction x_dir[8] = { DIR_SW, DIR_NE, DIR_SE, DIR_NW, DIR_S, DIR_E, DIR_W, DIR_N };
186  static const DiagDirection x_exits[8] = { DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SW, DIAGDIR_NE };
187 
188  /* Tile offsets and exit dirs for Y axis */
189  static const Direction y_dir[8] = { DIR_SE, DIR_NW, DIR_SW, DIR_NE, DIR_S, DIR_W, DIR_E, DIR_N };
190  static const DiagDirection y_exits[8] = { DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SE, DIAGDIR_NW };
191 
192  Axis axis = GetRailStationAxis(tile);
193 
194  /* Choose appropriate lookup table to use */
195  const Direction *dir = axis == AXIS_X ? x_dir : y_dir;
196  const DiagDirection *diagdir = axis == AXIS_X ? x_exits : y_exits;
197 
198  uint32 res = 0;
199  uint i;
200 
201  for (i = 0; i < lengthof(x_dir); i++, dir++, diagdir++) {
202  TileIndex neighbour_tile = tile + TileOffsByDir(*dir);
203  TrackBits trackbits = TrackStatusToTrackBits(GetTileTrackStatus(neighbour_tile, TRANSPORT_RAIL, 0));
204  if (trackbits != TRACK_BIT_NONE) {
205  /* If there is any track on the tile, set the bit in the second byte */
206  SetBit(res, i + 8);
207 
208  /* With tunnels and bridges the tile has tracks, but they are not necessarily connected
209  * with the next tile because the ramp is not going in the right direction. */
210  if (IsTileType(neighbour_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(neighbour_tile) != *diagdir) {
211  continue;
212  }
213 
214  /* If any track reaches our exit direction, set the bit in the lower byte */
215  if (trackbits & DiagdirReachesTracks(*diagdir)) SetBit(res, i);
216  }
217  }
218 
219  return res;
220 }
221 
222 
223 /* Station Resolver Functions */
224 /* virtual */ uint32 StationScopeResolver::GetRandomBits() const
225 {
226  return (this->st == nullptr ? 0 : this->st->random_bits) | (this->tile == INVALID_TILE ? 0 : GetStationTileRandomBits(this->tile) << 16);
227 }
228 
229 
230 /* virtual */ uint32 StationScopeResolver::GetTriggers() const
231 {
232  return this->st == nullptr ? 0 : this->st->waiting_triggers;
233 }
234 
235 
241 static struct {
242  uint32 v40;
243  uint32 v41;
244  uint32 v45;
245  uint32 v46;
246  uint32 v47;
247  uint32 v49;
248  uint8 valid;
249 } _svc;
250 
257 {
258  if (this->town_scope == nullptr) {
259  Town *t = nullptr;
260  if (this->station_scope.st != nullptr) {
261  t = this->station_scope.st->town;
262  } else if (this->station_scope.tile != INVALID_TILE) {
263  t = ClosestTownFromTile(this->station_scope.tile, UINT_MAX);
264  }
265  if (t == nullptr) return nullptr;
266  this->town_scope = new TownScopeResolver(*this, t, this->station_scope.st == nullptr);
267  }
268  return this->town_scope;
269 }
270 
271 /* virtual */ uint32 StationScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
272 {
273  if (this->st == nullptr) {
274  /* Station does not exist, so we're in a purchase list or the land slope check callback. */
275  switch (variable) {
276  case 0x40:
277  case 0x41:
278  case 0x46:
279  case 0x47:
280  case 0x49: return 0x2110000; // Platforms, tracks & position
281  case 0x42: return 0; // Rail type (XXX Get current type from GUI?)
282  case 0x43: return GetCompanyInfo(_current_company); // Station owner
283  case 0x44: return 2; // PBS status
284  case 0x67: // Land info of nearby tile
285  if (this->axis != INVALID_AXIS && this->tile != INVALID_TILE) {
286  TileIndex tile = this->tile;
287  if (parameter != 0) tile = GetNearbyTile(parameter, tile, true, this->axis); // only perform if it is required
288 
289  Slope tileh = GetTileSlope(tile);
290  bool swap = (this->axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
291 
292  return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
293  }
294  break;
295 
296  case 0xFA: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // Build date, clamped to a 16 bit value
297  }
298 
299  *available = false;
300  return UINT_MAX;
301  }
302 
303  switch (variable) {
304  /* Calculated station variables */
305  case 0x40:
306  if (!HasBit(_svc.valid, 0)) { _svc.v40 = GetPlatformInfoHelper(this->tile, false, false, false); SetBit(_svc.valid, 0); }
307  return _svc.v40;
308 
309  case 0x41:
310  if (!HasBit(_svc.valid, 1)) { _svc.v41 = GetPlatformInfoHelper(this->tile, true, false, false); SetBit(_svc.valid, 1); }
311  return _svc.v41;
312 
313  case 0x42: return GetTerrainType(this->tile) | (GetReverseRailTypeTranslation(GetRailType(this->tile), this->statspec->grf_prop.grffile) << 8);
314  case 0x43: return GetCompanyInfo(this->st->owner); // Station owner
315  case 0x44: return HasStationReservation(this->tile) ? 7 : 4; // PBS status
316  case 0x45:
317  if (!HasBit(_svc.valid, 2)) { _svc.v45 = GetRailContinuationInfo(this->tile); SetBit(_svc.valid, 2); }
318  return _svc.v45;
319 
320  case 0x46:
321  if (!HasBit(_svc.valid, 3)) { _svc.v46 = GetPlatformInfoHelper(this->tile, false, false, true); SetBit(_svc.valid, 3); }
322  return _svc.v46;
323 
324  case 0x47:
325  if (!HasBit(_svc.valid, 4)) { _svc.v47 = GetPlatformInfoHelper(this->tile, true, false, true); SetBit(_svc.valid, 4); }
326  return _svc.v47;
327 
328  case 0x49:
329  if (!HasBit(_svc.valid, 5)) { _svc.v49 = GetPlatformInfoHelper(this->tile, false, true, false); SetBit(_svc.valid, 5); }
330  return _svc.v49;
331 
332  case 0x4A: // Animation frame of tile
333  return GetAnimationFrame(this->tile);
334 
335  /* Variables which use the parameter */
336  /* Variables 0x60 to 0x65 and 0x69 are handled separately below */
337  case 0x66: { // Animation frame of nearby tile
338  TileIndex tile = this->tile;
339  if (parameter != 0) tile = GetNearbyTile(parameter, tile);
340  return this->st->TileBelongsToRailStation(tile) ? GetAnimationFrame(tile) : UINT_MAX;
341  }
342 
343  case 0x67: { // Land info of nearby tile
344  Axis axis = GetRailStationAxis(this->tile);
345  TileIndex tile = this->tile;
346  if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
347 
348  Slope tileh = GetTileSlope(tile);
349  bool swap = (axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
350 
351  return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
352  }
353 
354  case 0x68: { // Station info of nearby tiles
355  TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
356 
357  if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
358 
359  uint32 grfid = this->st->speclist[GetCustomStationSpecIndex(this->tile)].grfid;
360  bool perpendicular = GetRailStationAxis(this->tile) != GetRailStationAxis(nearby_tile);
361  bool same_station = this->st->TileBelongsToRailStation(nearby_tile);
362  uint32 res = GB(GetStationGfx(nearby_tile), 1, 2) << 12 | !!perpendicular << 11 | !!same_station << 10;
363 
364  if (IsCustomStationSpecIndex(nearby_tile)) {
365  const StationSpecList ssl = BaseStation::GetByTile(nearby_tile)->speclist[GetCustomStationSpecIndex(nearby_tile)];
366  res |= 1 << (ssl.grfid != grfid ? 9 : 8) | ssl.localidx;
367  }
368  return res;
369  }
370 
371  /* General station variables */
372  case 0x82: return 50;
373  case 0x84: return this->st->string_id;
374  case 0x86: return 0;
375  case 0xF0: return this->st->facilities;
376  case 0xFA: return Clamp(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
377  }
378 
379  return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
380 }
381 
382 uint32 Station::GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const
383 {
384  switch (variable) {
385  case 0x48: { // Accepted cargo types
386  CargoID cargo_type;
387  uint32 value = 0;
388 
389  for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
390  if (HasBit(this->goods[cargo_type].status, GoodsEntry::GES_ACCEPTANCE)) SetBit(value, cargo_type);
391  }
392  return value;
393  }
394 
395  case 0x8A: return this->had_vehicle_of_type;
396  case 0xF1: return (this->airport.tile != INVALID_TILE) ? this->airport.GetSpec()->ttd_airport_type : ATP_TTDP_LARGE;
397  case 0xF2: return (this->truck_stops != nullptr) ? this->truck_stops->status : 0;
398  case 0xF3: return (this->bus_stops != nullptr) ? this->bus_stops->status : 0;
399  case 0xF6: return this->airport.flags;
400  case 0xF7: return GB(this->airport.flags, 8, 8);
401  }
402 
403  /* Handle cargo variables with parameter, 0x60 to 0x65 and 0x69 */
404  if ((variable >= 0x60 && variable <= 0x65) || variable == 0x69) {
405  CargoID c = GetCargoTranslation(parameter, object.grffile);
406 
407  if (c == CT_INVALID) {
408  switch (variable) {
409  case 0x62: return 0xFFFFFFFF;
410  case 0x64: return 0xFF00;
411  default: return 0;
412  }
413  }
414  const GoodsEntry *ge = &this->goods[c];
415 
416  switch (variable) {
417  case 0x60: return min(ge->cargo.TotalCount(), 4095);
418  case 0x61: return ge->HasVehicleEverTriedLoading() ? ge->time_since_pickup : 0;
419  case 0x62: return ge->HasRating() ? ge->rating : 0xFFFFFFFF;
420  case 0x63: return ge->cargo.DaysInTransit();
421  case 0x64: return ge->HasVehicleEverTriedLoading() ? ge->last_speed | (ge->last_age << 8) : 0xFF00;
422  case 0x65: return GB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1) << 3;
423  case 0x69: {
424  assert_compile((int)GoodsEntry::GES_EVER_ACCEPTED + 1 == (int)GoodsEntry::GES_LAST_MONTH);
425  assert_compile((int)GoodsEntry::GES_EVER_ACCEPTED + 2 == (int)GoodsEntry::GES_CURRENT_MONTH);
426  assert_compile((int)GoodsEntry::GES_EVER_ACCEPTED + 3 == (int)GoodsEntry::GES_ACCEPTED_BIGTICK);
427  return GB(ge->status, GoodsEntry::GES_EVER_ACCEPTED, 4);
428  }
429  }
430  }
431 
432  /* Handle cargo variables (deprecated) */
433  if (variable >= 0x8C && variable <= 0xEC) {
434  const GoodsEntry *g = &this->goods[GB(variable - 0x8C, 3, 4)];
435  switch (GB(variable - 0x8C, 0, 3)) {
436  case 0: return g->cargo.TotalCount();
437  case 1: return GB(min(g->cargo.TotalCount(), 4095), 0, 4) | (GB(g->status, GoodsEntry::GES_ACCEPTANCE, 1) << 7);
438  case 2: return g->time_since_pickup;
439  case 3: return g->rating;
440  case 4: return g->cargo.Source();
441  case 5: return g->cargo.DaysInTransit();
442  case 6: return g->last_speed;
443  case 7: return g->last_age;
444  }
445  }
446 
447  DEBUG(grf, 1, "Unhandled station variable 0x%X", variable);
448 
449  *available = false;
450  return UINT_MAX;
451 }
452 
453 uint32 Waypoint::GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const
454 {
455  switch (variable) {
456  case 0x48: return 0; // Accepted cargo types
457  case 0x8A: return HVOT_WAYPOINT;
458  case 0xF1: return 0; // airport type
459  case 0xF2: return 0; // truck stop status
460  case 0xF3: return 0; // bus stop status
461  case 0xF6: return 0; // airport flags
462  case 0xF7: return 0; // airport flags cont.
463  }
464 
465  /* Handle cargo variables with parameter, 0x60 to 0x65 */
466  if (variable >= 0x60 && variable <= 0x65) {
467  return 0;
468  }
469 
470  /* Handle cargo variables (deprecated) */
471  if (variable >= 0x8C && variable <= 0xEC) {
472  switch (GB(variable - 0x8C, 0, 3)) {
473  case 3: return INITIAL_STATION_RATING;
474  case 4: return INVALID_STATION;
475  default: return 0;
476  }
477  }
478 
479  DEBUG(grf, 1, "Unhandled station variable 0x%X", variable);
480 
481  *available = false;
482  return UINT_MAX;
483 }
484 
485 /* virtual */ const SpriteGroup *StationResolverObject::ResolveReal(const RealSpriteGroup *group) const
486 {
487  if (this->station_scope.st == nullptr || this->station_scope.statspec->cls_id == STAT_CLASS_WAYP) {
488  return group->loading[0];
489  }
490 
491  uint cargo = 0;
492  const Station *st = Station::From(this->station_scope.st);
493 
494  switch (this->station_scope.cargo_type) {
495  case CT_INVALID:
496  case CT_DEFAULT_NA:
497  case CT_PURCHASE:
498  cargo = 0;
499  break;
500 
501  case CT_DEFAULT:
502  for (CargoID cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
503  cargo += st->goods[cargo_type].cargo.TotalCount();
504  }
505  break;
506 
507  default:
508  cargo = st->goods[this->station_scope.cargo_type].cargo.TotalCount();
509  break;
510  }
511 
512  if (HasBit(this->station_scope.statspec->flags, SSF_DIV_BY_STATION_SIZE)) cargo /= (st->train_station.w + st->train_station.h);
513  cargo = min(0xfff, cargo);
514 
515  if (cargo > this->station_scope.statspec->cargo_threshold) {
516  if (group->num_loading > 0) {
517  uint set = ((cargo - this->station_scope.statspec->cargo_threshold) * group->num_loading) / (4096 - this->station_scope.statspec->cargo_threshold);
518  return group->loading[set];
519  }
520  } else {
521  if (group->num_loaded > 0) {
522  uint set = (cargo * group->num_loaded) / (this->station_scope.statspec->cargo_threshold + 1);
523  return group->loaded[set];
524  }
525  }
526 
527  return group->loading[0];
528 }
529 
540  CallbackID callback, uint32 callback_param1, uint32 callback_param2)
541  : ResolverObject(statspec->grf_prop.grffile, callback, callback_param1, callback_param2),
542  station_scope(*this, statspec, st, tile), town_scope(nullptr)
543 {
544  /* Invalidate all cached vars */
545  _svc.valid = 0;
546 
547  CargoID ctype = CT_DEFAULT_NA;
548 
549  if (this->station_scope.st == nullptr) {
550  /* No station, so we are in a purchase list */
551  ctype = CT_PURCHASE;
552  } else if (Station::IsExpected(this->station_scope.st)) {
553  const Station *st = Station::From(this->station_scope.st);
554  /* Pick the first cargo that we have waiting */
555  const CargoSpec *cs;
556  FOR_ALL_CARGOSPECS(cs) {
557  if (this->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != nullptr &&
558  st->goods[cs->Index()].cargo.TotalCount() > 0) {
559  ctype = cs->Index();
560  break;
561  }
562  }
563  }
564 
565  if (this->station_scope.statspec->grf_prop.spritegroup[ctype] == nullptr) {
566  ctype = CT_DEFAULT;
567  }
568 
569  /* Remember the cargo type we've picked */
570  this->station_scope.cargo_type = ctype;
572 }
573 
574 StationResolverObject::~StationResolverObject()
575 {
576  delete this->town_scope;
577 }
578 
587 SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10)
588 {
589  StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, var10);
590  const SpriteGroup *group = object.Resolve();
591  if (group == nullptr || group->type != SGT_RESULT) return 0;
592  return group->GetResult() - 0x42D;
593 }
594 
604 SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
605 {
606  /* callback_param1 == 2 means we are resolving the foundation sprites. */
607  StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, 2, layout | (edge_info << 16));
608 
609  const SpriteGroup *group = object.Resolve();
610  if (group == nullptr || group->type != SGT_RESULT) return 0;
611 
612  /* Note: SpriteGroup::Resolve zeroes all registers, so register 0x100 is initialised to 0. (compatibility) */
613  return group->GetResult() + GetRegister(0x100);
614 }
615 
616 
617 uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile)
618 {
619  StationResolverObject object(statspec, st, tile, callback, param1, param2);
620  return object.ResolveCallback();
621 }
622 
633 CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, byte plat_len, byte numtracks)
634 {
635  TileIndexDiff diff = cur_tile - north_tile;
636  Slope slope = GetTileSlope(cur_tile);
637 
638  StationResolverObject object(statspec, nullptr, cur_tile, CBID_STATION_LAND_SLOPE_CHECK,
639  (slope << 4) | (slope ^ (axis == AXIS_Y && HasBit(slope, CORNER_W) != HasBit(slope, CORNER_E) ? SLOPE_EW : 0)),
640  (numtracks << 24) | (plat_len << 16) | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff)));
641  object.station_scope.axis = axis;
642 
643  uint16 cb_res = object.ResolveCallback();
644 
645  /* Failed callback means success. */
646  if (cb_res == CALLBACK_FAILED) return CommandCost();
647 
648  /* The meaning of bit 10 is inverted for a grf version < 8. */
649  if (statspec->grf_prop.grffile->grf_version < 8) ToggleBit(cb_res, 10);
650  return GetErrorMessageFromLocationCallbackResult(cb_res, statspec->grf_prop.grffile, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
651 }
652 
653 
661 int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec)
662 {
663  uint i;
664 
665  if (statspec == nullptr || st == nullptr) return 0;
666 
667  for (i = 1; i < st->num_specs && i < NUM_STATIONSSPECS_PER_STATION; i++) {
668  if (st->speclist[i].spec == nullptr && st->speclist[i].grfid == 0) break;
669  }
670 
671  if (i == NUM_STATIONSSPECS_PER_STATION) {
672  /* As final effort when the spec list is already full...
673  * try to find the same spec and return that one. This might
674  * result in slightly "wrong" (as per specs) looking stations,
675  * but it's fairly unlikely that one reaches the limit anyways.
676  */
677  for (i = 1; i < st->num_specs && i < NUM_STATIONSSPECS_PER_STATION; i++) {
678  if (st->speclist[i].spec == statspec) return i;
679  }
680 
681  return -1;
682  }
683 
684  if (exec) {
685  if (i >= st->num_specs) {
686  st->num_specs = i + 1;
687  st->speclist = ReallocT(st->speclist, st->num_specs);
688 
689  if (st->num_specs == 2) {
690  /* Initial allocation */
691  st->speclist[0].spec = nullptr;
692  st->speclist[0].grfid = 0;
693  st->speclist[0].localidx = 0;
694  }
695  }
696 
697  st->speclist[i].spec = statspec;
698  st->speclist[i].grfid = statspec->grf_prop.grffile->grfid;
699  st->speclist[i].localidx = statspec->grf_prop.local_id;
700 
702  }
703 
704  return i;
705 }
706 
707 
714 void DeallocateSpecFromStation(BaseStation *st, byte specindex)
715 {
716  /* specindex of 0 (default) is never freeable */
717  if (specindex == 0) return;
718 
719  ETileArea area = ETileArea(st, INVALID_TILE, TA_WHOLE);
720  /* Check all tiles over the station to check if the specindex is still in use */
721  TILE_AREA_LOOP(tile, area) {
722  if (st->TileBelongsToRailStation(tile) && GetCustomStationSpecIndex(tile) == specindex) {
723  return;
724  }
725  }
726 
727  /* This specindex is no longer in use, so deallocate it */
728  st->speclist[specindex].spec = nullptr;
729  st->speclist[specindex].grfid = 0;
730  st->speclist[specindex].localidx = 0;
731 
732  /* If this was the highest spec index, reallocate */
733  if (specindex == st->num_specs - 1) {
734  for (; st->speclist[st->num_specs - 1].grfid == 0 && st->num_specs > 1; st->num_specs--) {}
735 
736  if (st->num_specs > 1) {
737  st->speclist = ReallocT(st->speclist, st->num_specs);
738  } else {
739  free(st->speclist);
740  st->num_specs = 0;
741  st->speclist = nullptr;
742  st->cached_anim_triggers = 0;
743  st->cached_cargo_triggers = 0;
744  return;
745  }
746  }
747 
749 }
750 
761 bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station)
762 {
763  const DrawTileSprites *sprites = nullptr;
764  const RailtypeInfo *rti = GetRailTypeInfo(railtype);
765  PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
766  uint tile = 2;
767 
768  const StationSpec *statspec = StationClass::Get(sclass)->GetSpec(station);
769  if (statspec == nullptr) return false;
770 
772  uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0x2110000, 0, statspec, nullptr, INVALID_TILE);
773  if (callback != CALLBACK_FAILED) tile = callback;
774  }
775 
776  uint32 total_offset = rti->GetRailtypeSpriteOffset();
777  uint32 relocation = 0;
778  uint32 ground_relocation = 0;
779  const NewGRFSpriteLayout *layout = nullptr;
780  DrawTileSprites tmp_rail_layout;
781 
782  if (statspec->renderdata == nullptr) {
783  sprites = GetStationTileLayout(STATION_RAIL, tile + axis);
784  } else {
785  layout = &statspec->renderdata[(tile < statspec->tiles) ? tile + axis : (uint)axis];
786  if (!layout->NeedsPreprocessing()) {
787  sprites = layout;
788  layout = nullptr;
789  }
790  }
791 
792  if (layout != nullptr) {
793  /* Sprite layout which needs preprocessing */
794  bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND);
795  uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
796  uint8 var10;
797  FOR_EACH_SET_BIT(var10, var10_values) {
798  uint32 var10_relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, var10);
799  layout->ProcessRegisters(var10, var10_relocation, separate_ground);
800  }
801 
802  tmp_rail_layout.seq = layout->GetLayout(&tmp_rail_layout.ground);
803  sprites = &tmp_rail_layout;
804  total_offset = 0;
805  } else {
806  /* Simple sprite layout */
807  ground_relocation = relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, 0);
809  ground_relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, 1);
810  }
811  ground_relocation += rti->fallback_railtype;
812  }
813 
814  SpriteID image = sprites->ground.sprite;
815  PaletteID pal = sprites->ground.pal;
816  RailTrackOffset overlay_offset;
817  if (rti->UsesOverlay() && SplitGroundSpriteForOverlay(nullptr, &image, &overlay_offset)) {
819  DrawSprite(image, PAL_NONE, x, y);
820  DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
821  } else {
822  image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset;
823  if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation;
824  DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
825  }
826 
827  DrawRailTileSeqInGUI(x, y, sprites, total_offset, relocation, palette);
828 
829  return true;
830 }
831 
832 
833 const StationSpec *GetStationSpec(TileIndex t)
834 {
835  if (!IsCustomStationSpecIndex(t)) return nullptr;
836 
837  const BaseStation *st = BaseStation::GetByTile(t);
838  uint specindex = GetCustomStationSpecIndex(t);
839  return specindex < st->num_specs ? st->speclist[specindex].spec : nullptr;
840 }
841 
842 
850 {
851  const StationSpec *statspec = GetStationSpec(tile);
852 
853  return statspec != nullptr && HasBit(statspec->blocked, GetStationGfx(tile));
854 }
855 
863 {
864  const StationSpec *statspec = GetStationSpec(tile);
865  uint gfx = GetStationGfx(tile);
866  /* Default stations do not draw pylons under roofs (gfx >= 4) */
867  return statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4;
868 }
869 
877 {
878  const StationSpec *statspec = GetStationSpec(tile);
879  return statspec == nullptr || !HasBit(statspec->wires, GetStationGfx(tile));
880 }
881 
883 uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data)
884 {
885  return GetStationCallback(callback, param1, param2, statspec, st, tile);
886 }
887 
889 struct StationAnimationBase : public AnimationBase<StationAnimationBase, StationSpec, BaseStation, int, GetAnimStationCallback> {
890  static const CallbackID cb_animation_speed = CBID_STATION_ANIMATION_SPEED;
891  static const CallbackID cb_animation_next_frame = CBID_STATION_ANIM_NEXT_FRAME;
892 
893  static const StationCallbackMask cbm_animation_speed = CBM_STATION_ANIMATION_SPEED;
894  static const StationCallbackMask cbm_animation_next_frame = CBM_STATION_ANIMATION_NEXT_FRAME;
895 };
896 
897 void AnimateStationTile(TileIndex tile)
898 {
899  const StationSpec *ss = GetStationSpec(tile);
900  if (ss == nullptr) return;
901 
903 }
904 
905 void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type)
906 {
907  /* List of coverage areas for each animation trigger */
908  static const TriggerArea tas[] = {
909  TA_TILE, TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_WHOLE
910  };
911 
912  /* Get Station if it wasn't supplied */
913  if (st == nullptr) st = BaseStation::GetByTile(tile);
914 
915  /* Check the cached animation trigger bitmask to see if we need
916  * to bother with any further processing. */
917  if (!HasBit(st->cached_anim_triggers, trigger)) return;
918 
919  uint16 random_bits = Random();
920  ETileArea area = ETileArea(st, tile, tas[trigger]);
921 
922  /* Check all tiles over the station to check if the specindex is still in use */
923  TILE_AREA_LOOP(tile, area) {
924  if (st->TileBelongsToRailStation(tile)) {
925  const StationSpec *ss = GetStationSpec(tile);
926  if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
927  CargoID cargo;
928  if (cargo_type == CT_INVALID) {
929  cargo = CT_INVALID;
930  } else {
931  cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
932  }
933  StationAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, tile, (random_bits << 16) | Random(), (uint8)trigger | (cargo << 8));
934  }
935  }
936  }
937 }
938 
947 {
948  /* List of coverage areas for each animation trigger */
949  static const TriggerArea tas[] = {
950  TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
951  };
952 
953  /* Get Station if it wasn't supplied */
954  if (st == nullptr) st = Station::GetByTile(tile);
955 
956  /* Check the cached cargo trigger bitmask to see if we need
957  * to bother with any further processing. */
958  if (st->cached_cargo_triggers == 0) return;
959  if (cargo_type != CT_INVALID && !HasBit(st->cached_cargo_triggers, cargo_type)) return;
960 
961  uint32 whole_reseed = 0;
962  ETileArea area = ETileArea(st, tile, tas[trigger]);
963 
964  CargoTypes empty_mask = 0;
965  if (trigger == SRT_CARGO_TAKEN) {
966  /* Create a bitmask of completely empty cargo types to be matched */
967  for (CargoID i = 0; i < NUM_CARGO; i++) {
968  if (st->goods[i].cargo.TotalCount() == 0) {
969  SetBit(empty_mask, i);
970  }
971  }
972  }
973 
974  /* Store triggers now for var 5F */
975  SetBit(st->waiting_triggers, trigger);
976  uint32 used_triggers = 0;
977 
978  /* Check all tiles over the station to check if the specindex is still in use */
979  TILE_AREA_LOOP(tile, area) {
980  if (st->TileBelongsToRailStation(tile)) {
981  const StationSpec *ss = GetStationSpec(tile);
982  if (ss == nullptr) continue;
983 
984  /* Cargo taken "will only be triggered if all of those
985  * cargo types have no more cargo waiting." */
986  if (trigger == SRT_CARGO_TAKEN) {
987  if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
988  }
989 
990  if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
991  StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
992  object.waiting_triggers = st->waiting_triggers;
993 
994  const SpriteGroup *group = object.Resolve();
995  if (group == nullptr) continue;
996 
997  used_triggers |= object.used_triggers;
998 
999  uint32 reseed = object.GetReseedSum();
1000  if (reseed != 0) {
1001  whole_reseed |= reseed;
1002  reseed >>= 16;
1003 
1004  /* Set individual tile random bits */
1005  uint8 random_bits = GetStationTileRandomBits(tile);
1006  random_bits &= ~reseed;
1007  random_bits |= Random() & reseed;
1008  SetStationTileRandomBits(tile, random_bits);
1009 
1010  MarkTileDirtyByTile(tile);
1011  }
1012  }
1013  }
1014  }
1015 
1016  /* Update whole station random bits */
1017  st->waiting_triggers &= ~used_triggers;
1018  if ((whole_reseed & 0xFFFF) != 0) {
1019  st->random_bits &= ~whole_reseed;
1020  st->random_bits |= Random() & whole_reseed;
1021  }
1022 }
1023 
1029 {
1030  st->cached_anim_triggers = 0;
1031  st->cached_cargo_triggers = 0;
1032 
1033  /* Combine animation trigger bitmask for all station specs
1034  * of this station. */
1035  for (uint i = 0; i < st->num_specs; i++) {
1036  const StationSpec *ss = st->speclist[i].spec;
1037  if (ss != nullptr) {
1038  st->cached_anim_triggers |= ss->animation.triggers;
1040  }
1041  }
1042 }
1043 
Implementation of the NewGRF class&#39; functions.
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:275
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
Callback 141 needs random bits.
Trigger station when cargo is completely taken.
Use callback to select a sprite layout to use.
NewGRF handling of rail types.
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:304
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
static bool IsCustomStationSpecIndex(TileIndex t)
Is there a custom rail station spec on this tile?
Definition: station_map.h:469
Waypoint class.
void DeallocateSpecFromStation(BaseStation *st, byte specindex)
Deallocate a StationSpec from a Station.
Base class for roadstops.
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.
StationScopeResolver station_scope
The station scope resolver.
#define DAYS_TILL_ORIGINAL_BASE_YEAR
The offset in days from the &#39;_date == 0&#39; till &#39;ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)&#39;.
Definition: date_type.h:80
bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station)
Draw representation of a station tile for GUI purposes.
uint8 num_specs
Number of specs in the speclist.
int32 TileIndexDiff
An offset value between to tiles.
Definition: map_func.h:154
TownScopeResolver * GetTown()
Get the town scope associated with a station, if it exists.
static T ToggleBit(T &x, const uint8 y)
Toggles a bit in a variable.
Northwest.
West.
static byte GetAnimationFrame(TileIndex t)
Get the current animation frame.
Definition: tile_map.h:250
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...
bool CanStationTileHaveWires(TileIndex tile)
Check if a rail station tile shall have wires when electrified.
CargoID GetCargoTranslation(uint8 cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoID.
Interface for SpriteGroup-s to access the gamestate.
uint32 GetTerrainType(TileIndex tile, TileContext context)
Function used by houses (and soon industries) to get information on type of "terrain" the tile it is ...
Maximal number of cargo types in a game.
Definition: cargo_type.h:64
Set when cargo was delivered for final delivery during the current STATION_ACCEPTANCE_TICKS interval...
Definition: station_base.h:211
Specification of a cargo type.
Definition: cargotype.h:55
Station specification.
Set when cargo was delivered for final delivery this month.
Definition: station_base.h:205
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading...
Definition: cargopacket.h:526
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:205
TileArea train_station
Tile area the train &#39;station&#39; part covers.
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
uint DaysInTransit() const
Returns average number of days in transit for a cargo entity.
Definition: cargopacket.h:255
Set when using the callback resolve system, but not to resolve a callback.
Stores station stats for a single cargo.
Definition: station_base.h:170
#define INSTANTIATE_NEWGRF_CLASS_METHODS(name, Tspec, Tid, Tmax)
Force instantiation of the methods so we don&#39;t get linker errors.
uint32 GetRandomBits() const override
Get a few random bits.
const DrawTileSeqStruct * GetLayout(PalSpriteID *ground) const
Returns the result spritelayout after preprocessing.
virtual void GetTileArea(TileArea *ta, StationType type) const =0
Get the tile area for a given station type.
byte num_loaded
Number of loaded groups.
#define FOR_EACH_SET_BIT(bitpos_var, bitset_value)
Do an operation for each set set bit in a value.
Common return value for all commands.
Definition: command_type.h:23
uint32 reseed[VSG_END]
Collects bits to rerandomise while triggering triggers.
static void ChangeAnimationFrame(CallbackID cb, const StationSpec *spec, BaseStation *obj, TileIndex tile, uint32 random_bits, uint32 trigger, int extra_data=0)
Check a callback to determine what the next animation step is and execute that step.
bool IsUIAvailable(uint index) const
Check whether the spec will be available to the user at some point in time.
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:255
bool HasRating() const
Does this cargo have a rating at this station?
Definition: station_base.h:273
uint tiles
Number of tile layouts.
uint16 w
The width of the area.
Definition: tilearea_type.h:18
Use a custom next frame callback.
void StationUpdateCachedTriggers(BaseStation *st)
Update the cached animation trigger bitmask for a station.
CommandCost GetErrorMessageFromLocationCallbackResult(uint16 cb_res, const GRFFile *grffile, StringID default_error)
Get the error message from a shape/location/slope check callback result.
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:479
Southwest.
static void AnimateTile(const StationSpec *spec, BaseStation *obj, TileIndex tile, bool random_animation, int extra_data=0)
Animate a single tile.
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
static uint GetCustomStationSpecIndex(TileIndex t)
Get the custom station spec for this tile.
Definition: station_map.h:493
North.
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition: sprite.h:60
CargoTypes cargo_triggers
Bitmask of cargo types which cause trigger re-randomizing.
static Station * From(BaseStation *st)
Converts a BaseStation to SpecializedStation with type checking.
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:124
Callback done for each tile of a station to check the slope.
Station is a waypoint (NewGRF only!)
Definition: station_type.h:70
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
static bool HasStationRail(TileIndex t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint...
Definition: station_map.h:135
Invalid cargo type.
Definition: cargo_type.h:68
Set when cargo was delivered for final delivery last month.
Definition: station_base.h:199
Slope GetTileSlope(TileIndex tile, int *h)
Return the slope of a given tile inside the map.
Definition: tile_map.cpp:59
static bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile)
Check if a tile is a valid continuation to a railstation tile.
Definition: station_map.h:378
uint32 GetTriggers() const override
Get the triggers.
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:3488
static void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32 total_offset, uint32 newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition: sprite.h:99
Struct containing information relating to NewGRF classes for stations and airports.
Definition: newgrf_class.h:19
bool TileBelongsToRailStation(TileIndex tile) const override
Check whether a specific tile belongs to this station.
Definition: station_base.h:513
byte pylons
Bitmask of base tiles (0 - 7) which should contain elrail pylons.
SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10)
Resolve sprites for drawing a station tile.
static uint32 GetRegister(uint i)
Gets the value of a so-called newgrf "register".
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:341
virtual const SpriteGroup * Resolve(ResolverObject &object) const
Base sprite group resolver.
uint8 valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
Action 2 handling.
static void SetStationTileRandomBits(TileIndex t, byte random_bits)
Set the random bits for a station tile.
Definition: station_map.h:505
TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets, Axis axis)
Get the tile at the given offset.
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
Southeast.
const SpriteGroup ** loaded
List of loaded groups (can be SpriteIDs or Callback results)
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.
Called to indicate how long the current animation frame should last.
static struct @31 _svc
Station variable cache This caches &#39;expensive&#39; station variable lookups which iterate over several ti...
Customize the animation speed of the station.
static bool HasStationReservation(TileIndex t)
Get the reservation state of the rail station.
Definition: station_map.h:393
static bool IsRailStationTile(TileIndex t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:58
const SpriteGroup * ResolveReal(const RealSpriteGroup *group) const override
Get the real sprites of the grf.
East.
Southeast.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
byte status
Status of this cargo, see GoodsEntryStatus.
Definition: station_base.h:226
static bool HasStationTileRail(TileIndex t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint...
Definition: station_map.h:146
#define TILE_AREA_LOOP(var, ta)
A loop which iterates over the tiles of a TileArea.
int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec)
Allocate a StationSpec to a Station.
Definition of base types and functions in a cross-platform compatible way.
Function implementations related to NewGRF animation.
A number of safeguards to prevent using unsafe methods.
Scope resolver for a town.
Definition: newgrf_town.h:22
Direction
Defines the 8 directions on the map.
static PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition: sprite.h:168
Base of waypoints.
static Axis GetRailStationAxis(TileIndex t)
Get the rail direction of a rail station.
Definition: station_map.h:337
Called for periodically starting or stopping the animation.
uint32 used_triggers
Subset of cur_triggers, which actually triggered some rerandomisation. (scope independent) ...
void ProcessRegisters(uint8 resolved_var10, uint32 resolved_sprite, bool separate_ground) const
Evaluates the register modifiers and integrates them into the preprocessed sprite layout...
static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
Find the end of a railway station, from the tile, in the direction of delta.
Represents the covered area of e.g.
Definition: tilearea_type.h:16
static T * ReallocT(T *t_ptr, size_t num_elements)
Simplified reallocation function that allocates the specified number of elements of the given type...
Definition: alloc_func.hpp:111
TrackBits
Bitfield corresponding to Track.
Definition: track_type.h:38
Set when a sprite originates from an Action 1.
Definition: sprites.h:1524
StationSpecList * speclist
List of station specs of this station.
South.
StationCallbackMask
Callback masks for stations.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1938
byte wires
Bitmask of base tiles (0 - 7) which should contain elrail wires.
const SpriteGroup ** loading
List of loading groups (can be SpriteIDs or Callback results)
TownScopeResolver * town_scope
The town scope resolver (created on the first call).
uint8 cargo_map[NUM_CARGO]
Inverse cargo translation table (CargoID -> local ID)
Definition: newgrf.h:127
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
byte last_speed
Maximum speed (up to 255) of the last vehicle that tried to load this cargo.
Definition: station_base.h:246
uint8 cached_anim_triggers
NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen...
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
NewGRF supplied spritelayout.
static DiagDirection GetTunnelBridgeDirection(TileIndex t)
Get the direction pointing to the other end.
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
static StationGfx GetStationGfx(TileIndex t)
Get the station graphics of this tile.
Definition: station_map.h:68
east and west corner are raised
Definition: slope_type.h:59
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:589
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
static TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction...
Definition: track_func.h:581
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:17
byte flags
Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size...
SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
Resolve the sprites for custom station foundations.
StationAnimationTrigger
Animation triggers for station.
The X axis.
byte num_loading
Number of loading groups.
Transport by train.
Set when a vehicle ever delivered cargo to the station for final delivery.
Definition: station_base.h:193
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
CargoID cargo_type
Type of cargo of the station.
Functions related to companies.
const struct StationSpec * statspec
Station (type) specification.
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:28
No track.
Definition: track_type.h:39
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:59
Header file for NewGRF stations.
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
struct BaseStation * st
Instance of the station.
StationID Source() const
Returns source of the first cargo packet in this list.
Definition: cargopacket.h:497
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.
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:50
StationClassID
bool NeedsPreprocessing() const
Tests whether this spritelayout needs preprocessing by PrepareLayout() and ProcessRegisters(), or whether it can be used directly.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
uint32 GetNearbyTileInformation(TileIndex tile, bool grf_version8)
Common part of station var 0x67, house var 0x62, indtile var 0x60, industry var 0x62.
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
Use different sprite set for ground sprites.
Helper class for a unified approach to NewGRF animation.
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.
Cargo support for NewGRFs.
byte fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations...
Definition: rail.h:198
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:215
CargoTypes cached_cargo_triggers
NOSAVE: Combined cargo trigger bitmask.
Called to determine station tile next animation frame.
CallbackID callback
Callback being resolved.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data)
Wrapper for animation control, see GetStationCallback.
Slope
Enumeration for the slope-type.
Definition: slope_type.h:48
uint32 GetCompanyInfo(CompanyID owner, const Livery *l)
Returns company information like in vehicle var 43 or station var 43.
Maximum number of classes.
A tile of a station.
Definition: tile_type.h:46
Town data structure.
Definition: town.h:53
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
static TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition: track_func.h:371
Northwest.
bool CanStationTileHavePylons(TileIndex tile)
Check if a rail station tile shall have pylons when electrified.
Main group of ground images.
Definition: rail.h:49
static NewGRFClass * Get(Tid cls_id)
Get a particular class.
uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
Perform a reverse railtype lookup to get the GRF internal ID.
uint GetRailtypeSpriteOffset() const
Offset between the current railtype and normal rail.
Definition: rail.h:292
static TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition: map_func.h:355
Same as AT_LARGE.
Northeast.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:88
uint8 localidx
Station ID within GRF of station.
uint16 local_id
id defined by the grf file for this entity
static void InsertDefaults()
Initialise the defaults.
Functions that have tunnels and bridges in common.
static TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition: map_func.h:179
uint16 random_bits
Random bits assigned to this station.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
StationRandomTrigger
Randomisation triggers for stations.
RailTrackOffset
Offsets for sprites within an overlay/underlay set.
Definition: rail.h:67
const struct GRFFile * grffile
grf file that introduced this entity
CallbackID
List of implemented NewGRF callbacks.
Station resolver.
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Functions related to NewGRF provided sounds.
DiagDirection
Enumeration for diagonal directions.
Set when calling a randomizing trigger (almost undocumented).
byte callback_mask
Bitmask of station callbacks that have to be called.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
Base of the town class.
StationResolverObject(const StationSpec *statspec, BaseStation *st, TileIndex tile, CallbackID callback=CBID_NO_CALLBACK, uint32 callback_param1=0, uint32 callback_param2=0)
Resolver for stations.
Northeast, upper right on your monitor.
Functions to handle the town part of NewGRF towns.
Choose a sprite layout to draw, instead of the standard 0-7 range.
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
NewGRFSpriteLayout * renderdata
Array of tile layouts.
byte waiting_triggers
Waiting triggers (NewGRF) for this station.
Divide cargo amount by station size.
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
uint32 GetNewGRFVariable(const struct ResolverObject &object, byte variable, byte parameter, bool *available) const override
Helper function to get a NewGRF variable that isn&#39;t implemented by the base class.
static DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
#define TILE_ADD(x, y)
Adds to tiles together.
Definition: map_func.h:244
Flag for an invalid Axis.
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:23
static const uint NUM_STATIONSSPECS_PER_STATION
Maximum number of parts per station.
Base classes/functions for stations.
Date _date
Current date in days (day counter)
Definition: date.cpp:26
Helper class for animation control.
uint16 h
The height of the area.
Definition: tilearea_type.h:19
static byte GetStationTileRandomBits(TileIndex t)
Get the random bits of a station tile.
Definition: station_map.h:517
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override
Get a variable value.
Base class for all station-ish types.
Station data structure.
Definition: station_base.h:450
Axis
Allow incrementing of DiagDirDiff variables.
Set when the station accepts the cargo currently for final deliveries.
Definition: station_base.h:177
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:835
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:115
byte blocked
Bitmask of base tiles (0 - 7) which are blocked to trains.
uint32 grfid
GRF ID of this custom station.
Southwest.
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:24