OpenTTD Source  20241108-master-g80f628063a
newgrf_roadstop.cpp
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 "roadstop_base.h"
14 #include "newgrf_roadstop.h"
15 #include "newgrf_class_func.h"
16 #include "newgrf_cargo.h"
17 #include "newgrf_roadtype.h"
18 #include "gfx_type.h"
19 #include "company_func.h"
20 #include "road.h"
21 #include "window_type.h"
23 #include "town.h"
24 #include "viewport_func.h"
25 #include "newgrf_animation_base.h"
26 #include "newgrf_sound.h"
27 
28 #include "safeguards.h"
29 
30 template <>
32 {
33  /* Set up initial data */
34  RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_DEFAULT))->name = STR_STATION_CLASS_DFLT;
35  RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_DEFAULT))->Insert(nullptr);
36  RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_WAYPOINT))->name = STR_STATION_CLASS_WAYP;
37  RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_WAYPOINT))->Insert(nullptr);
38 }
39 
40 template <>
41 bool RoadStopClass::IsUIAvailable(uint) const
42 {
43  return true;
44 }
45 
46 /* Instantiate RoadStopClass. */
48 
49 static const uint NUM_ROADSTOPSPECS_PER_STATION = 63;
50 
52 {
53  if (this->st == nullptr) return 0;
54 
55  uint32_t bits = this->st->random_bits;
56  if (this->tile != INVALID_TILE && Station::IsExpected(this->st)) {
57  bits |= Station::From(this->st)->GetRoadStopRandomBits(this->tile) << 16;
58  }
59  return bits;
60 }
61 
63 {
64  return this->st == nullptr ? 0 : this->st->waiting_triggers;
65 }
66 
67 uint32_t RoadStopScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
68 {
69  auto get_road_type_variable = [&](RoadTramType rtt) -> uint32_t {
70  RoadType rt;
71  if (this->tile == INVALID_TILE) {
72  rt = (GetRoadTramType(this->roadtype) == rtt) ? this->roadtype : INVALID_ROADTYPE;
73  } else {
74  rt = GetRoadType(this->tile, rtt);
75  }
76  if (rt == INVALID_ROADTYPE) {
77  return 0xFFFFFFFF;
78  } else {
80  }
81  };
82 
83  switch (variable) {
84  /* View/rotation */
85  case 0x40: return this->view;
86 
87  /* Stop type: 0: bus, 1: truck, 2: waypoint */
88  case 0x41:
89  if (this->type == STATION_BUS) return 0;
90  if (this->type == STATION_TRUCK) return 1;
91  return 2;
92 
93  /* Terrain type */
94  case 0x42: return this->tile == INVALID_TILE ? 0 : (GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile, TCX_NORMAL));
95 
96  /* Road type */
97  case 0x43: return get_road_type_variable(RTT_ROAD);
98 
99  /* Tram type */
100  case 0x44: return get_road_type_variable(RTT_TRAM);
101 
102  /* Town zone and Manhattan distance of closest town */
103  case 0x45: {
104  if (this->tile == INVALID_TILE) return HZB_TOWN_EDGE << 16;
105  const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
106  return t != nullptr ? (GetTownRadiusGroup(t, this->tile) << 16 | ClampTo<uint16_t>(DistanceManhattan(this->tile, t->xy))) : HZB_TOWN_EDGE << 16;
107  }
108 
109  /* Get square of Euclidian distance of closest town */
110  case 0x46: {
111  if (this->tile == INVALID_TILE) return 0;
112  const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
113  return t != nullptr ? DistanceSquare(this->tile, t->xy) : 0;
114  }
115 
116  /* Company information */
117  case 0x47: return GetCompanyInfo(this->st == nullptr ? _current_company : this->st->owner);
118 
119  /* Animation frame */
120  case 0x49: return this->tile == INVALID_TILE ? 0 : this->st->GetRoadStopAnimationFrame(this->tile);
121 
122  /* Misc info */
123  case 0x50: {
124  uint32_t result = 0;
125  if (this->tile == INVALID_TILE) {
126  SetBit(result, 4);
127  }
128  return result;
129  }
130 
131  /* Variables which use the parameter */
132  /* Variables 0x60 to 0x65 and 0x69 are handled separately below */
133 
134  /* Animation frame of nearby tile */
135  case 0x66: {
136  if (this->tile == INVALID_TILE) return UINT_MAX;
137  TileIndex tile = this->tile;
138  if (parameter != 0) tile = GetNearbyTile(parameter, tile);
139  return (IsAnyRoadStopTile(tile) && GetStationIndex(tile) == this->st->index) ? this->st->GetRoadStopAnimationFrame(tile) : UINT_MAX;
140  }
141 
142  /* Land info of nearby tile */
143  case 0x67: {
144  if (this->tile == INVALID_TILE) return 0;
145  TileIndex tile = this->tile;
146  if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
147  return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8);
148  }
149 
150  /* Road stop info of nearby tiles */
151  case 0x68: {
152  if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
153  TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
154 
155  if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
156 
157  uint32_t grfid = this->st->roadstop_speclist[GetCustomRoadStopSpecIndex(this->tile)].grfid;
158  bool same_orientation = GetStationGfx(this->tile) == GetStationGfx(nearby_tile);
159  bool same_station = GetStationIndex(nearby_tile) == this->st->index;
160  uint32_t res = GetStationGfx(nearby_tile) << 12 | !same_orientation << 11 | !!same_station << 10;
161  StationType type = GetStationType(nearby_tile);
162  if (type == STATION_TRUCK) res |= (1 << 16);
163  if (type == STATION_ROADWAYPOINT) res |= (2 << 16);
164  if (type == this->type) SetBit(res, 20);
165 
166  if (IsCustomRoadStopSpecIndex(nearby_tile)) {
167  const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
168  res |= 1 << (sm.grfid != grfid ? 9 : 8) | ClampTo<uint8_t>(sm.localidx);
169  }
170  return res;
171  }
172 
173  /* GRFID of nearby road stop tiles */
174  case 0x6A: {
175  if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
176  TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
177 
178  if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
179  if (!IsCustomRoadStopSpecIndex(nearby_tile)) return 0;
180 
181  const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
182  return sm.grfid;
183  }
184 
185  /* 16 bit road stop ID of nearby tiles */
186  case 0x6B: {
187  if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
188  TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
189 
190  if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
191  if (!IsCustomRoadStopSpecIndex(nearby_tile)) return 0xFFFE;
192 
193  uint32_t grfid = this->st->roadstop_speclist[GetCustomRoadStopSpecIndex(this->tile)].grfid;
194 
195  const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
196  if (sm.grfid == grfid) {
197  return sm.localidx;
198  }
199 
200  return 0xFFFE;
201  }
202 
203  case 0xF0: return this->st == nullptr ? 0 : this->st->facilities; // facilities
204 
205  case 0xFA: return ClampTo<uint16_t>((this->st == nullptr ? TimerGameCalendar::date : this->st->build_date) - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // build date
206  }
207 
208  if (this->st != nullptr) return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
209 
210  available = false;
211  return UINT_MAX;
212 }
213 
215 {
216  if (group == nullptr) return nullptr;
217 
218  return group->loading[0];
219 }
220 
221 RoadStopResolverObject::RoadStopResolverObject(const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8_t view,
222  CallbackID callback, uint32_t param1, uint32_t param2)
223  : ResolverObject(roadstopspec->grf_prop.grffile, callback, param1, param2), roadstop_scope(*this, st, roadstopspec, tile, roadtype, type, view)
224 {
226 
227  if (st == nullptr) {
228  /* No station, so we are in a purchase list */
230  } else if (Station::IsExpected(st)) {
231  const Station *station = Station::From(st);
232  /* Pick the first cargo that we have waiting */
233  for (const CargoSpec *cs : CargoSpec::Iterate()) {
234  if (roadstopspec->grf_prop.spritegroup[cs->Index()] != nullptr &&
235  station->goods[cs->Index()].cargo.TotalCount() > 0) {
236  ctype = cs->Index();
237  break;
238  }
239  }
240  }
241 
242  if (roadstopspec->grf_prop.spritegroup[ctype] == nullptr) {
244  }
245 
246  /* Remember the cargo type we've picked */
247  this->roadstop_scope.cargo_type = ctype;
248  this->root_spritegroup = roadstopspec->grf_prop.spritegroup[ctype];
249 }
250 
251 TownScopeResolver *RoadStopResolverObject::GetTown()
252 {
253  if (!this->town_scope.has_value()) {
254  Town *t;
255  if (this->roadstop_scope.st != nullptr) {
256  t = this->roadstop_scope.st->town;
257  } else {
258  t = ClosestTownFromTile(this->roadstop_scope.tile, UINT_MAX);
259  }
260  if (t == nullptr) return nullptr;
261  this->town_scope.emplace(*this, t, this->roadstop_scope.st == nullptr);
262  }
263  return &*this->town_scope;
264 }
265 
266 uint16_t GetRoadStopCallback(CallbackID callback, uint32_t param1, uint32_t param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8_t view)
267 {
268  RoadStopResolverObject object(roadstopspec, st, tile, roadtype, type, view, callback, param1, param2);
269  return object.ResolveCallback();
270 }
271 
281 void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view)
282 {
283  assert(roadtype != INVALID_ROADTYPE);
284  assert(spec != nullptr);
285 
286  const RoadTypeInfo *rti = GetRoadTypeInfo(roadtype);
287  RoadStopResolverObject object(spec, nullptr, INVALID_TILE, roadtype, type, view);
288  const SpriteGroup *group = object.Resolve();
289  if (group == nullptr || group->type != SGT_TILELAYOUT) return;
290  const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(nullptr);
291 
292  PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
293 
294  SpriteID image = dts->ground.sprite;
295  PaletteID pal = dts->ground.pal;
296 
297  RoadStopDrawMode draw_mode;
298  if (HasBit(spec->flags, RSF_DRAW_MODE_REGISTER)) {
299  draw_mode = static_cast<RoadStopDrawMode>(GetRegister(0x100));
300  } else {
301  draw_mode = spec->draw_mode;
302  }
303 
304  if (type == STATION_ROADWAYPOINT) {
305  DrawSprite(SPR_ROAD_PAVED_STRAIGHT_X, PAL_NONE, x, y);
306  if ((draw_mode & ROADSTOP_DRAW_MODE_WAYP_GROUND) && GB(image, 0, SPRITE_WIDTH) != 0) {
307  DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
308  }
309  } else if (GB(image, 0, SPRITE_WIDTH) != 0) {
310  DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
311  }
312 
313  if (view >= 4) {
314  /* Drive-through stop */
315  uint sprite_offset = 5 - view;
316 
317  /* Road underlay takes precedence over tram */
318  if (type == STATION_ROADWAYPOINT || draw_mode & ROADSTOP_DRAW_MODE_OVERLAY) {
319  if (rti->UsesOverlay()) {
321  DrawSprite(ground + sprite_offset, PAL_NONE, x, y);
322 
324  if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y);
325  } else if (RoadTypeIsTram(roadtype)) {
326  DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
327  }
328  }
329  } else {
330  /* Bay stop */
331  if ((draw_mode & ROADSTOP_DRAW_MODE_ROAD) && rti->UsesOverlay()) {
333  DrawSprite(ground + view, PAL_NONE, x, y);
334  }
335  }
336 
337  DrawCommonTileSeqInGUI(x, y, dts, 0, 0, palette, true);
338 }
339 
341 uint16_t GetAnimRoadStopCallback(CallbackID callback, uint32_t param1, uint32_t param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, int)
342 {
343  return GetRoadStopCallback(callback, param1, param2, roadstopspec, st, tile, INVALID_ROADTYPE, GetStationType(tile), GetStationGfx(tile));
344 }
345 
347  static uint8_t Get(BaseStation *st, TileIndex tile) { return st->GetRoadStopAnimationFrame(tile); }
348  static bool Set(BaseStation *st, TileIndex tile, uint8_t frame) { return st->SetRoadStopAnimationFrame(tile, frame); }
349 };
350 
353  static const CallbackID cb_animation_speed = CBID_STATION_ANIMATION_SPEED;
354  static const CallbackID cb_animation_next_frame = CBID_STATION_ANIM_NEXT_FRAME;
355 
356  static const RoadStopCallbackMask cbm_animation_speed = CBM_ROAD_STOP_ANIMATION_SPEED;
357  static const RoadStopCallbackMask cbm_animation_next_frame = CBM_ROAD_STOP_ANIMATION_NEXT_FRAME;
358 };
359 
360 void AnimateRoadStopTile(TileIndex tile)
361 {
362  const RoadStopSpec *ss = GetRoadStopSpec(tile);
363  if (ss == nullptr) return;
364 
366 }
367 
368 void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoID cargo_type)
369 {
370  /* Get Station if it wasn't supplied */
371  if (st == nullptr) st = BaseStation::GetByTile(trigger_tile);
372 
373  /* Check the cached animation trigger bitmask to see if we need
374  * to bother with any further processing. */
375  if (!HasBit(st->cached_roadstop_anim_triggers, trigger)) return;
376 
377  uint16_t random_bits = Random();
378  auto process_tile = [&](TileIndex cur_tile) {
379  const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
380  if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
381  CargoID cargo;
382  if (!IsValidCargoID(cargo_type)) {
383  cargo = INVALID_CARGO;
384  } else {
385  cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
386  }
387  RoadStopAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, cur_tile, (random_bits << 16) | Random(), (uint8_t)trigger | (cargo << 8));
388  }
389  };
390 
391  if (trigger == SAT_NEW_CARGO || trigger == SAT_CARGO_TAKEN || trigger == SAT_250_TICKS) {
392  for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
393  process_tile(tile_data.tile);
394  }
395  } else {
396  process_tile(trigger_tile);
397  }
398 }
399 
409 {
410  if (st == nullptr) st = Station::GetByTile(tile);
411 
412  /* Check the cached cargo trigger bitmask to see if we need
413  * to bother with any further processing. */
414  if (st->cached_roadstop_cargo_triggers == 0) return;
415  if (IsValidCargoID(cargo_type) && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
416 
417  SetBit(st->waiting_triggers, trigger);
418 
419  uint32_t whole_reseed = 0;
420 
421  /* Bitmask of completely empty cargo types to be matched. */
422  CargoTypes empty_mask = (trigger == RSRT_CARGO_TAKEN) ? GetEmptyMask(st) : 0;
423 
424  uint32_t used_triggers = 0;
425  auto process_tile = [&](TileIndex cur_tile) {
426  const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
427  if (ss == nullptr) return;
428 
429  /* Cargo taken "will only be triggered if all of those
430  * cargo types have no more cargo waiting." */
431  if (trigger == RSRT_CARGO_TAKEN) {
432  if ((ss->cargo_triggers & ~empty_mask) != 0) return;
433  }
434 
435  if (!IsValidCargoID(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
436  RoadStopResolverObject object(ss, st, cur_tile, INVALID_ROADTYPE, GetStationType(cur_tile), GetStationGfx(cur_tile));
437  object.waiting_triggers = st->waiting_triggers;
438 
439  const SpriteGroup *group = object.Resolve();
440  if (group == nullptr) return;
441 
442  used_triggers |= object.used_triggers;
443 
444  uint32_t reseed = object.GetReseedSum();
445  if (reseed != 0) {
446  whole_reseed |= reseed;
447  reseed >>= 16;
448 
449  /* Set individual tile random bits */
450  uint8_t random_bits = st->GetRoadStopRandomBits(cur_tile);
451  random_bits &= ~reseed;
452  random_bits |= Random() & reseed;
453  st->SetRoadStopRandomBits(cur_tile, random_bits);
454 
455  MarkTileDirtyByTile(cur_tile);
456  }
457  }
458  };
459  if (trigger == RSRT_NEW_CARGO || trigger == RSRT_CARGO_TAKEN) {
460  for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
461  process_tile(tile_data.tile);
462  }
463  } else {
464  process_tile(tile);
465  }
466 
467  /* Update whole station random bits */
468  st->waiting_triggers &= ~used_triggers;
469  if ((whole_reseed & 0xFFFF) != 0) {
470  st->random_bits &= ~whole_reseed;
471  st->random_bits |= Random() & whole_reseed;
472  }
473 }
474 
482 {
483  for (const auto &cls : RoadStopClass::Classes()) {
484  /* Ignore the waypoint class. */
485  if (IsWaypointClass(cls)) continue;
486  /* Ignore the default class with only the default station. */
487  if (cls.Index() == ROADSTOP_CLASS_DFLT && cls.GetSpecCount() == 1) continue;
488  if (GetIfClassHasNewStopsByType(&cls, rs, roadtype)) return true;
489  }
490  return false;
491 }
492 
500 bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopType rs, RoadType roadtype)
501 {
502  for (const auto spec : roadstopclass->Specs()) {
503  if (GetIfStopIsForType(spec, rs, roadtype)) return true;
504  }
505  return false;
506 }
507 
515 bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs, RoadType roadtype)
516 {
517  // The roadstopspec is nullptr, must be the default station, always return true.
518  if (roadstopspec == nullptr) return true;
519 
520  if (HasBit(roadstopspec->flags, RSF_BUILD_MENU_ROAD_ONLY) && !RoadTypeIsRoad(roadtype)) return false;
521  if (HasBit(roadstopspec->flags, RSF_BUILD_MENU_TRAM_ONLY) && !RoadTypeIsTram(roadtype)) return false;
522 
523  if (roadstopspec->stop_type == ROADSTOPTYPE_ALL) return true;
524 
525  switch (rs) {
526  case ROADSTOP_BUS:
527  if (roadstopspec->stop_type == ROADSTOPTYPE_PASSENGER) return true;
528  break;
529 
530  case ROADSTOP_TRUCK:
531  if (roadstopspec->stop_type == ROADSTOPTYPE_FREIGHT) return true;
532  break;
533 
534  default:
535  NOT_REACHED();
536  }
537  return false;
538 }
539 
540 const RoadStopSpec *GetRoadStopSpec(TileIndex t)
541 {
542  if (!IsCustomRoadStopSpecIndex(t)) return nullptr;
543 
544  const BaseStation *st = BaseStation::GetByTile(t);
545  uint specindex = GetCustomRoadStopSpecIndex(t);
546  return specindex < st->roadstop_speclist.size() ? st->roadstop_speclist[specindex].spec : nullptr;
547 }
548 
549 int AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec)
550 {
551  uint i;
552 
553  if (statspec == nullptr || st == nullptr) return 0;
554 
555  /* Try to find the same spec and return that one */
556  for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
557  if (st->roadstop_speclist[i].spec == statspec) return i;
558  }
559 
560  /* Try to find an unused spec slot */
561  for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
562  if (st->roadstop_speclist[i].spec == nullptr && st->roadstop_speclist[i].grfid == 0) break;
563  }
564 
565  if (i == NUM_ROADSTOPSPECS_PER_STATION) {
566  /* Full, give up */
567  return -1;
568  }
569 
570  if (exec) {
571  if (i >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(i + 1);
572  st->roadstop_speclist[i].spec = statspec;
573  st->roadstop_speclist[i].grfid = statspec->grf_prop.grffile->grfid;
574  st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id;
575 
577  }
578 
579  return i;
580 }
581 
582 void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex)
583 {
584  /* specindex of 0 (default) is never freeable */
585  if (specindex == 0) return;
586 
587  /* Check custom road stop tiles if the specindex is still in use */
588  for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
589  if (GetCustomRoadStopSpecIndex(tile_data.tile) == specindex) {
590  return;
591  }
592  }
593 
594  /* This specindex is no longer in use, so deallocate it */
595  st->roadstop_speclist[specindex].spec = nullptr;
596  st->roadstop_speclist[specindex].grfid = 0;
597  st->roadstop_speclist[specindex].localidx = 0;
598 
599  /* If this was the highest spec index, reallocate */
600  if (specindex == st->roadstop_speclist.size() - 1) {
601  size_t num_specs;
602  for (num_specs = st->roadstop_speclist.size() - 1; num_specs > 0; num_specs--) {
603  if (st->roadstop_speclist[num_specs].grfid != 0) break;
604  }
605 
606  if (num_specs > 0) {
607  st->roadstop_speclist.resize(num_specs + 1);
608  } else {
609  st->roadstop_speclist.clear();
612  return;
613  }
614  }
615 
617 }
618 
624 {
627 
628  /* Combine animation trigger bitmask for all road stop specs
629  * of this station. */
630  for (const auto &sm : GetStationSpecList<RoadStopSpec>(st)) {
631  if (sm.spec == nullptr) continue;
632  st->cached_roadstop_anim_triggers |= sm.spec->animation.triggers;
633  st->cached_roadstop_cargo_triggers |= sm.spec->cargo_triggers;
634  }
635 }
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
Struct containing information relating to NewGRF classes for stations and airports.
Definition: newgrf_class.h:26
std::span< Tspec *const > Specs() const
Get read-only span of specs of this class.
Definition: newgrf_class.h:58
static std::span< NewGRFClass< Tspec, Tindex, Tmax > const > Classes()
Get read-only span of all classes of this type.
Definition: newgrf_class.h:64
StringID name
Name of this class.
Definition: newgrf_class.h:49
bool IsUIAvailable(uint index) const
Check whether the spec will be available to the user at some point in time.
void Insert(Tspec *spec)
Insert a spec into the class, and update its index.
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
static void InsertDefaults()
Initialise the defaults.
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
Definition: cargopacket.h:607
static Date date
Current date in days (day counter).
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
Functions related to debugging.
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:988
Types related to the graphics and/or input devices.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
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:2057
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition: map.cpp:163
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:146
static constexpr CargoID SG_DEFAULT
Default type used when no more-specific cargo matches.
Definition: newgrf_cargo.h:23
static constexpr CargoID SG_PURCHASE
Used in purchase lists before an item exists.
Definition: newgrf_cargo.h:24
static constexpr CargoID SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
Definition: newgrf_cargo.h:25
Function implementations related to NewGRF animation.
StationAnimationTrigger
Animation triggers for station.
@ SAT_CARGO_TAKEN
Trigger station when cargo is completely taken.
@ SAT_NEW_CARGO
Trigger station on new cargo arrival.
@ SAT_250_TICKS
Trigger station every 250 ticks.
CallbackID
List of implemented NewGRF callbacks.
@ CBID_STATION_ANIMATION_SPEED
Called to indicate how long the current animation frame should last.
@ CBID_STATION_ANIM_START_STOP
Called for periodically starting or stopping the animation.
@ CBID_STATION_ANIM_NEXT_FRAME
Called to determine station tile next animation frame.
RoadStopCallbackMask
Callback masks for road stops.
@ CBM_ROAD_STOP_ANIMATION_SPEED
Customize the animation speed of the road stop.
@ CBM_ROAD_STOP_ANIMATION_NEXT_FRAME
Use a custom next frame callback.
Cargo support for NewGRFs.
Implementation of the NewGRF class' functions.
uint32_t GetCompanyInfo(CompanyID owner, const Livery *l)
Returns company information like in vehicle var 43 or station var 43.
uint32_t GetNearbyTileInformation(TileIndex tile, bool grf_version8)
Common part of station var 0x67, house var 0x62, indtile var 0x60, industry var 0x62.
uint32_t GetTerrainType(TileIndex tile, TileContext context)
Function used by houses (and soon industries) to get information on type of "terrain" the tile it is ...
TileIndex GetNearbyTile(uint8_t parameter, TileIndex tile, bool signed_offsets, Axis axis)
Get the tile at the given offset.
@ TCX_NORMAL
Nothing special.
NewGRF definitions and structures for road stops.
RoadStopDrawMode
Different draw modes to disallow rendering of some parts of the stop or road.
@ ROADSTOP_DRAW_MODE_ROAD
Bay stops: Draw the road itself.
@ ROADSTOP_DRAW_MODE_OVERLAY
Drive-through stops: Draw the road overlay, e.g. pavement.
@ ROADSTOP_DRAW_MODE_WAYP_GROUND
Waypoints: Draw the sprite layout ground tile (on top of the road)
RoadStopRandomTrigger
@ RSRT_CARGO_TAKEN
Trigger roadstop when cargo is completely taken.
@ RSRT_NEW_CARGO
Trigger roadstop on arrival of new cargo.
bool IsWaypointClass(const RoadStopClass &cls)
Test if a RoadStopClass is the waypoint class.
@ ROADSTOP_CLASS_DFLT
Default road stop class.
void RoadStopUpdateCachedTriggers(BaseStation *st)
Update the cached animation trigger bitmask for a station.
@ ROADSTOPTYPE_FREIGHT
This RoadStop is for freight (truck) stops.
@ ROADSTOPTYPE_ALL
This RoadStop is for both types of station road stops.
@ ROADSTOPTYPE_PASSENGER
This RoadStop is for passenger (bus) stops.
bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopType rs, RoadType roadtype)
Checks if the given RoadStopClass has any specs assigned to it, compatible with the given RoadStopTyp...
void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view)
Draw representation of a road stop tile for GUI purposes.
@ RSF_CB141_RANDOM_BITS
Callback 141 needs random bits.
@ RSF_DRAW_MODE_REGISTER
Read draw mode from register 0x100.
@ RSF_BUILD_MENU_ROAD_ONLY
Only show in the road build menu (not tram).
@ RSF_BUILD_MENU_TRAM_ONLY
Only show in the tram build menu (not road).
bool GetIfNewStopsByType(RoadStopType rs, RoadType roadtype)
Checks if there's any new stations by a specific RoadStopType.
bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs, RoadType roadtype)
Checks if the given RoadStopSpec is compatible with the given RoadStopType.
void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type=INVALID_CARGO)
Trigger road stop randomisation.
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
Perform a reverse roadtype lookup to get the GRF internal ID.
NewGRF handling of road types.
Functions related to NewGRF provided sounds.
uint32_t GetRegister(uint i)
Gets the value of a so-called newgrf "register".
Road specific functions.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:227
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition: road.h:61
@ ROTSG_ROADSTOP
Required: Bay stop surface.
Definition: road.h:70
@ ROTSG_GROUND
Required: Main group of ground images.
Definition: road.h:62
RoadType
The different roadtypes we support.
Definition: road_type.h:25
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition: road_type.h:30
Base class for roadstops.
A number of safeguards to prevent using unsafe methods.
void DrawCommonTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t orig_offset, uint32_t newgrf_offset, PaletteID default_palette, bool child_offset_is_unsigned)
Draws a tile sprite sequence in the GUI.
Definition: sprite.cpp:92
PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition: sprite.h:168
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
Definition: sprites.h:1535
Base classes/functions for stations.
CargoTypes GetEmptyMask(const Station *st)
Get a mask of the cargo types that are empty at the station.
StationType GetStationType(Tile t)
Get the station type of this tile.
Definition: station_map.h:44
StationGfx GetStationGfx(Tile t)
Get the station graphics of this tile.
Definition: station_map.h:68
uint GetCustomRoadStopSpecIndex(Tile t)
Get the custom road stop spec for this tile.
Definition: station_map.h:678
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
bool IsCustomRoadStopSpecIndex(Tile t)
Is there a custom road stop spec on this tile?
Definition: station_map.h:654
bool IsAnyRoadStopTile(Tile t)
Is tile t a road stop station?
Definition: station_map.h:256
RoadStopType
Types of RoadStops.
Definition: station_type.h:45
@ ROADSTOP_BUS
A standard stop for buses.
Definition: station_type.h:46
@ ROADSTOP_TRUCK
A standard stop for trucks.
Definition: station_type.h:47
StationType
Station types.
Definition: station_type.h:31
Definition of base types and functions in a cross-platform compatible way.
static void AnimateTile(const RoadStopSpec *spec, BaseStation *obj, TileIndex tile, bool random_animation, int extra_data=0)
Animate a single tile.
static void ChangeAnimationFrame(CallbackID cb, const RoadStopSpec *spec, BaseStation *obj, TileIndex tile, uint32_t random_bits, uint32_t trigger, int extra_data=0)
Check a callback to determine what the next animation step is and execute that step.
uint16_t triggers
The triggers that trigger animation.
Base class for all station-ish types.
virtual uint32_t GetNewGRFVariable(const struct ResolverObject &object, uint8_t variable, uint8_t parameter, bool &available) const =0
Helper function to get a NewGRF variable that isn't implemented by the base class.
StationFacility facilities
The facilities that this station has.
std::vector< SpecMapping< RoadStopSpec > > roadstop_speclist
List of road stop specs of this station.
uint8_t cached_roadstop_anim_triggers
NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing sh...
Owner owner
The owner of this station.
Town * town
The town this station is associated with.
CargoTypes cached_roadstop_cargo_triggers
NOSAVE: Combined cargo trigger bitmask for road stops.
uint16_t random_bits
Random bits assigned to this station.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
std::vector< RoadStopTileData > custom_roadstop_tile_data
List of custom road stop tile data.
uint8_t waiting_triggers
Waiting triggers (NewGRF) for this station.
TimerGameCalendar::Date build_date
Date of construction.
Specification of a cargo type.
Definition: cargotype.h:71
static IterateWrapper Iterate(size_t from=0)
Returns an iterable ensemble of all valid CargoSpec.
Definition: cargotype.h:190
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:58
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:59
uint16_t local_id
id defined by the grf file for this entity
const struct GRFFile * grffile
grf file that introduced this entity
std::array< const struct SpriteGroup *, Tcnt > spritegroup
pointers to the different sprites of the entity
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoID -> local ID)
Definition: newgrf.h:131
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:210
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:25
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
std::vector< const SpriteGroup * > loading
List of loading groups (can be SpriteIDs or Callback results)
Interface for SpriteGroup-s to access the gamestate.
const GRFFile * grffile
GRFFile the resolved SpriteGroup belongs to.
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
Helper class for animation control.
Road stop resolver.
const SpriteGroup * ResolveReal(const RealSpriteGroup *group) const override
Get the real sprites of the grf.
std::optional< TownScopeResolver > town_scope
The town scope resolver (created on the first call).
RoadStopScopeResolver roadstop_scope
The stop scope resolver.
uint8_t view
Station axis.
uint32_t GetTriggers() const override
Get the triggers.
RoadType roadtype
Road type (used when no tile)
StationType type
Station type.
const struct RoadStopSpec * roadstopspec
Station (type) specification.
CargoID cargo_type
Type of cargo of the station.
struct BaseStation * st
Instance of the station.
TileIndex tile
Tile of the station.
uint32_t GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const override
Get a variable value.
uint32_t GetRandomBits() const override
Get a few random bits.
Road stop specification.
CargoTypes cargo_triggers
Bitmask of cargo types which cause trigger re-randomizing.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
ResolverObject & ro
Surrounding resolver object.
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
static Station * From(BaseStation *st)
Converts a BaseStation to SpecializedStation with type checking.
virtual const SpriteGroup * Resolve([[maybe_unused]] ResolverObject &object) const
Base sprite group resolver.
Station data structure.
Definition: station_base.h:439
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:468
Action 2 sprite layout for houses, industry tiles, objects and airport tiles.
Scope resolver for a town.
Definition: newgrf_town.h:22
Town data structure.
Definition: town.h:54
TileIndex xy
town center tile
Definition: town.h:55
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition: tile_map.h:279
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
Definition of the game-calendar-timer.
Base of the town class.
HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile)
Returns the bit corresponding to the town zone of the specified tile.
Definition: town_cmd.cpp:2447
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:3870
Functions related to (drawing on) viewports.
Types related to windows.