OpenTTD Source 20250328-master-gc3457cd4c0
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_badge.h"
15#include "newgrf_roadstop.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"
26#include "newgrf_sound.h"
27
28#include "table/strings.h"
29
30#include "newgrf_class_func.h"
31
32#include "safeguards.h"
33
34template <>
36{
37 /* Set up initial data */
38 RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_DEFAULT))->name = STR_STATION_CLASS_DFLT;
39 RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_DEFAULT))->Insert(nullptr);
40 RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_WAYPOINT))->name = STR_STATION_CLASS_WAYP;
41 RoadStopClass::Get(RoadStopClass::Allocate(ROADSTOP_CLASS_LABEL_WAYPOINT))->Insert(nullptr);
42}
43
44template <>
45bool RoadStopClass::IsUIAvailable(uint) const
46{
47 return true;
48}
49
50/* Instantiate RoadStopClass. */
52
53static const uint NUM_ROADSTOPSPECS_PER_STATION = 63;
54
56{
57 if (this->st == nullptr) return 0;
58
59 uint32_t bits = this->st->random_bits;
60 if (this->tile != INVALID_TILE && Station::IsExpected(this->st)) {
61 bits |= Station::From(this->st)->GetRoadStopRandomBits(this->tile) << 16;
62 }
63 return bits;
64}
65
67{
68 return this->st == nullptr ? 0 : this->st->waiting_triggers;
69}
70
71uint32_t RoadStopScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
72{
73 auto get_road_type_variable = [&](RoadTramType rtt) -> uint32_t {
74 RoadType rt;
75 if (this->tile == INVALID_TILE) {
76 rt = (GetRoadTramType(this->roadtype) == rtt) ? this->roadtype : INVALID_ROADTYPE;
77 } else {
78 rt = GetRoadType(this->tile, rtt);
79 }
80 if (rt == INVALID_ROADTYPE) {
81 return 0xFFFFFFFF;
82 } else {
84 }
85 };
86
87 switch (variable) {
88 /* View/rotation */
89 case 0x40: return this->view;
90
91 /* Stop type: 0: bus, 1: truck, 2: waypoint */
92 case 0x41:
93 if (this->type == StationType::Bus) return 0;
94 if (this->type == StationType::Truck) return 1;
95 return 2;
96
97 /* Terrain type */
98 case 0x42: return this->tile == INVALID_TILE ? 0 : (GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile, TCX_NORMAL));
99
100 /* Road type */
101 case 0x43: return get_road_type_variable(RTT_ROAD);
102
103 /* Tram type */
104 case 0x44: return get_road_type_variable(RTT_TRAM);
105
106 /* Town zone and Manhattan distance of closest town */
107 case 0x45: {
108 if (this->tile == INVALID_TILE) return HZB_TOWN_EDGE << 16;
109 const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
110 return t != nullptr ? (GetTownRadiusGroup(t, this->tile) << 16 | ClampTo<uint16_t>(DistanceManhattan(this->tile, t->xy))) : HZB_TOWN_EDGE << 16;
111 }
112
113 /* Get square of Euclidean distance of closest town */
114 case 0x46: {
115 if (this->tile == INVALID_TILE) return 0;
116 const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
117 return t != nullptr ? DistanceSquare(this->tile, t->xy) : 0;
118 }
119
120 /* Company information */
121 case 0x47: return GetCompanyInfo(this->st == nullptr ? _current_company : this->st->owner);
122
123 /* Animation frame */
124 case 0x49: return this->tile == INVALID_TILE ? 0 : this->st->GetRoadStopAnimationFrame(this->tile);
125
126 /* Misc info */
127 case 0x50: {
128 uint32_t result = 0;
129 if (this->tile == INVALID_TILE) {
130 SetBit(result, 4);
131 }
132 return result;
133 }
134
135 /* Variables which use the parameter */
136 /* Variables 0x60 to 0x65 and 0x69 are handled separately below */
137
138 /* Animation frame of nearby tile */
139 case 0x66: {
140 if (this->tile == INVALID_TILE) return UINT_MAX;
141 TileIndex tile = this->tile;
142 if (parameter != 0) tile = GetNearbyTile(parameter, tile);
143 return (IsAnyRoadStopTile(tile) && GetStationIndex(tile) == this->st->index) ? this->st->GetRoadStopAnimationFrame(tile) : UINT_MAX;
144 }
145
146 /* Land info of nearby tile */
147 case 0x67: {
148 if (this->tile == INVALID_TILE) return 0;
149 TileIndex tile = this->tile;
150 if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
151 return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8);
152 }
153
154 /* Road stop info of nearby tiles */
155 case 0x68: {
156 if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
157 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
158
159 if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
160
161 uint32_t grfid = this->st->roadstop_speclist[GetCustomRoadStopSpecIndex(this->tile)].grfid;
162 bool same_orientation = GetStationGfx(this->tile) == GetStationGfx(nearby_tile);
163 bool same_station = GetStationIndex(nearby_tile) == this->st->index;
164 uint32_t res = GetStationGfx(nearby_tile) << 12 | !same_orientation << 11 | !!same_station << 10;
165 StationType type = GetStationType(nearby_tile);
166 if (type == StationType::Truck) res |= (1 << 16);
167 if (type == StationType::RoadWaypoint) res |= (2 << 16);
168 if (type == this->type) SetBit(res, 20);
169
170 if (IsCustomRoadStopSpecIndex(nearby_tile)) {
171 const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
172 res |= 1 << (sm.grfid != grfid ? 9 : 8) | ClampTo<uint8_t>(sm.localidx);
173 }
174 return res;
175 }
176
177 /* GRFID of nearby road stop tiles */
178 case 0x6A: {
179 if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
180 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
181
182 if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
183 if (!IsCustomRoadStopSpecIndex(nearby_tile)) return 0;
184
185 const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
186 return sm.grfid;
187 }
188
189 /* 16 bit road stop ID of nearby tiles */
190 case 0x6B: {
191 if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
192 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
193
194 if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
195 if (!IsCustomRoadStopSpecIndex(nearby_tile)) return 0xFFFE;
196
197 uint32_t grfid = this->st->roadstop_speclist[GetCustomRoadStopSpecIndex(this->tile)].grfid;
198
199 const auto &sm = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
200 if (sm.grfid == grfid) {
201 return sm.localidx;
202 }
203
204 return 0xFFFE;
205 }
206
207 case 0x7A: return GetBadgeVariableResult(*this->ro.grffile, this->roadstopspec->badges, parameter);
208
209 case 0xF0: return this->st == nullptr ? 0 : this->st->facilities.base(); // facilities
210
211 case 0xFA: return ClampTo<uint16_t>((this->st == nullptr ? TimerGameCalendar::date : this->st->build_date) - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // build date
212 }
213
214 if (this->st != nullptr) return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
215
216 available = false;
217 return UINT_MAX;
218}
219
221{
222 if (group == nullptr) return nullptr;
223
224 return group->loading[0];
225}
226
227RoadStopResolverObject::RoadStopResolverObject(const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8_t view,
228 CallbackID callback, uint32_t param1, uint32_t param2)
229 : ResolverObject(roadstopspec->grf_prop.grffile, callback, param1, param2), roadstop_scope(*this, st, roadstopspec, tile, roadtype, type, view)
230{
232
233 if (st == nullptr) {
234 /* No station, so we are in a purchase list */
236 this->root_spritegroup = roadstopspec->grf_prop.GetSpriteGroup(ctype);
237 } else if (Station::IsExpected(st)) {
238 const Station *station = Station::From(st);
239 /* Pick the first cargo that we have waiting */
240 for (const auto &[cargo, spritegroup] : roadstopspec->grf_prop.spritegroups) {
241 if (cargo < NUM_CARGO && station->goods[cargo].HasData() && station->goods[cargo].GetData().cargo.TotalCount() > 0) {
242 ctype = cargo;
243 this->root_spritegroup = spritegroup;
244 break;
245 }
246 }
247
248 if (this->root_spritegroup == nullptr) {
250 this->root_spritegroup = roadstopspec->grf_prop.GetSpriteGroup(ctype);
251 }
252 }
253
254 if (this->root_spritegroup == nullptr) {
256 this->root_spritegroup = roadstopspec->grf_prop.GetSpriteGroup(ctype);
257 }
258
259 /* Remember the cargo type we've picked */
260 this->roadstop_scope.cargo_type = ctype;
261}
262
263TownScopeResolver *RoadStopResolverObject::GetTown()
264{
265 if (!this->town_scope.has_value()) {
266 Town *t;
267 if (this->roadstop_scope.st != nullptr) {
268 t = this->roadstop_scope.st->town;
269 } else {
270 t = ClosestTownFromTile(this->roadstop_scope.tile, UINT_MAX);
271 }
272 if (t == nullptr) return nullptr;
273 this->town_scope.emplace(*this, t, this->roadstop_scope.st == nullptr);
274 }
275 return &*this->town_scope;
276}
277
278uint16_t GetRoadStopCallback(CallbackID callback, uint32_t param1, uint32_t param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8_t view)
279{
280 RoadStopResolverObject object(roadstopspec, st, tile, roadtype, type, view, callback, param1, param2);
281 return object.ResolveCallback();
282}
283
293void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view)
294{
295 assert(roadtype != INVALID_ROADTYPE);
296 assert(spec != nullptr);
297
298 const RoadTypeInfo *rti = GetRoadTypeInfo(roadtype);
299 RoadStopResolverObject object(spec, nullptr, INVALID_TILE, roadtype, type, view);
300 const SpriteGroup *group = object.Resolve();
301 if (group == nullptr || group->type != SGT_TILELAYOUT) return;
302 const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(nullptr);
303
304 PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
305
306 SpriteID image = dts->ground.sprite;
307 PaletteID pal = dts->ground.pal;
308
309 RoadStopDrawModes draw_mode;
310 if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
311 draw_mode = static_cast<RoadStopDrawMode>(GetRegister(0x100));
312 } else {
313 draw_mode = spec->draw_mode;
314 }
315
316 if (type == StationType::RoadWaypoint) {
317 DrawSprite(SPR_ROAD_PAVED_STRAIGHT_X, PAL_NONE, x, y);
318 if (draw_mode.Test(RoadStopDrawMode::WaypGround) && GB(image, 0, SPRITE_WIDTH) != 0) {
319 DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
320 }
321 } else if (GB(image, 0, SPRITE_WIDTH) != 0) {
322 DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
323 }
324
325 if (view >= 4) {
326 /* Drive-through stop */
327 uint sprite_offset = 5 - view;
328
329 /* Road underlay takes precedence over tram */
330 if (type == StationType::RoadWaypoint || draw_mode.Test(RoadStopDrawMode::Overlay)) {
331 if (rti->UsesOverlay()) {
333 DrawSprite(ground + sprite_offset, PAL_NONE, x, y);
334
336 if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y);
337 } else if (RoadTypeIsTram(roadtype)) {
338 DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
339 }
340 }
341 } else {
342 /* Bay stop */
343 if (draw_mode.Test(RoadStopDrawMode::Road) && rti->UsesOverlay()) {
345 DrawSprite(ground + view, PAL_NONE, x, y);
346 }
347 }
348
349 DrawCommonTileSeqInGUI(x, y, dts, 0, 0, palette, true);
350}
351
353uint16_t GetAnimRoadStopCallback(CallbackID callback, uint32_t param1, uint32_t param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, int)
354{
355 return GetRoadStopCallback(callback, param1, param2, roadstopspec, st, tile, INVALID_ROADTYPE, GetStationType(tile), GetStationGfx(tile));
356}
357
359 static uint8_t Get(BaseStation *st, TileIndex tile) { return st->GetRoadStopAnimationFrame(tile); }
360 static bool Set(BaseStation *st, TileIndex tile, uint8_t frame) { return st->SetRoadStopAnimationFrame(tile, frame); }
361};
362
371
372void AnimateRoadStopTile(TileIndex tile)
373{
374 const RoadStopSpec *ss = GetRoadStopSpec(tile);
375 if (ss == nullptr) return;
376
378}
379
380void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoType cargo_type)
381{
382 /* Get Station if it wasn't supplied */
383 if (st == nullptr) st = BaseStation::GetByTile(trigger_tile);
384
385 /* Check the cached animation trigger bitmask to see if we need
386 * to bother with any further processing. */
387 if (!HasBit(st->cached_roadstop_anim_triggers, trigger)) return;
388
389 uint16_t random_bits = Random();
390 auto process_tile = [&](TileIndex cur_tile) {
391 const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
392 if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
393 uint8_t local_cargo;
394 if (!IsValidCargoType(cargo_type)) {
395 local_cargo = UINT8_MAX;
396 } else {
397 local_cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
398 }
399 RoadStopAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, cur_tile, (random_bits << 16) | Random(), (uint8_t)trigger | (local_cargo << 8));
400 }
401 };
402
403 if (trigger == SAT_NEW_CARGO || trigger == SAT_CARGO_TAKEN || trigger == SAT_250_TICKS) {
404 for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
405 process_tile(tile_data.tile);
406 }
407 } else {
408 process_tile(trigger_tile);
409 }
410}
411
420void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoType cargo_type)
421{
422 if (st == nullptr) st = Station::GetByTile(tile);
423
424 /* Check the cached cargo trigger bitmask to see if we need
425 * to bother with any further processing. */
426 if (st->cached_roadstop_cargo_triggers == 0) return;
427 if (IsValidCargoType(cargo_type) && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
428
429 SetBit(st->waiting_triggers, trigger);
430
431 uint32_t whole_reseed = 0;
432
433 /* Bitmask of completely empty cargo types to be matched. */
434 CargoTypes empty_mask = (trigger == RSRT_CARGO_TAKEN) ? GetEmptyMask(st) : 0;
435
436 uint32_t used_triggers = 0;
437 auto process_tile = [&](TileIndex cur_tile) {
438 const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
439 if (ss == nullptr) return;
440
441 /* Cargo taken "will only be triggered if all of those
442 * cargo types have no more cargo waiting." */
443 if (trigger == RSRT_CARGO_TAKEN) {
444 if ((ss->cargo_triggers & ~empty_mask) != 0) return;
445 }
446
447 if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
448 RoadStopResolverObject object(ss, st, cur_tile, INVALID_ROADTYPE, GetStationType(cur_tile), GetStationGfx(cur_tile));
449 object.waiting_triggers = st->waiting_triggers;
450
451 const SpriteGroup *group = object.Resolve();
452 if (group == nullptr) return;
453
454 used_triggers |= object.used_triggers;
455
456 uint32_t reseed = object.GetReseedSum();
457 if (reseed != 0) {
458 whole_reseed |= reseed;
459 reseed >>= 16;
460
461 /* Set individual tile random bits */
462 uint8_t random_bits = st->GetRoadStopRandomBits(cur_tile);
463 random_bits &= ~reseed;
464 random_bits |= Random() & reseed;
465 st->SetRoadStopRandomBits(cur_tile, random_bits);
466
467 MarkTileDirtyByTile(cur_tile);
468 }
469 }
470 };
471 if (trigger == RSRT_NEW_CARGO || trigger == RSRT_CARGO_TAKEN) {
472 for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
473 process_tile(tile_data.tile);
474 }
475 } else {
476 process_tile(tile);
477 }
478
479 /* Update whole station random bits */
480 st->waiting_triggers &= ~used_triggers;
481 if ((whole_reseed & 0xFFFF) != 0) {
482 st->random_bits &= ~whole_reseed;
483 st->random_bits |= Random() & whole_reseed;
484 }
485}
486
493bool GetIfNewStopsByType(RoadStopType rs, RoadType roadtype)
494{
495 for (const auto &cls : RoadStopClass::Classes()) {
496 /* Ignore the waypoint class. */
497 if (IsWaypointClass(cls)) continue;
498 /* Ignore the default class with only the default station. */
499 if (cls.Index() == ROADSTOP_CLASS_DFLT && cls.GetSpecCount() == 1) continue;
500 if (GetIfClassHasNewStopsByType(&cls, rs, roadtype)) return true;
501 }
502 return false;
503}
504
512bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopType rs, RoadType roadtype)
513{
514 for (const auto spec : roadstopclass->Specs()) {
515 if (GetIfStopIsForType(spec, rs, roadtype)) return true;
516 }
517 return false;
518}
519
527bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs, RoadType roadtype)
528{
529 // The roadstopspec is nullptr, must be the default station, always return true.
530 if (roadstopspec == nullptr) return true;
531
532 if (roadstopspec->flags.Test(RoadStopSpecFlag::RoadOnly) && !RoadTypeIsRoad(roadtype)) return false;
533 if (roadstopspec->flags.Test(RoadStopSpecFlag::TramOnly) && !RoadTypeIsTram(roadtype)) return false;
534
535 if (roadstopspec->stop_type == ROADSTOPTYPE_ALL) return true;
536
537 switch (rs) {
539 if (roadstopspec->stop_type == ROADSTOPTYPE_PASSENGER) return true;
540 break;
541
543 if (roadstopspec->stop_type == ROADSTOPTYPE_FREIGHT) return true;
544 break;
545
546 default:
547 NOT_REACHED();
548 }
549 return false;
550}
551
552const RoadStopSpec *GetRoadStopSpec(TileIndex t)
553{
554 if (!IsCustomRoadStopSpecIndex(t)) return nullptr;
555
556 const BaseStation *st = BaseStation::GetByTile(t);
557 uint specindex = GetCustomRoadStopSpecIndex(t);
558 return specindex < st->roadstop_speclist.size() ? st->roadstop_speclist[specindex].spec : nullptr;
559}
560
561int AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec)
562{
563 uint i;
564
565 if (statspec == nullptr || st == nullptr) return 0;
566
567 /* Try to find the same spec and return that one */
568 for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
569 if (st->roadstop_speclist[i].spec == statspec) return i;
570 }
571
572 /* Try to find an unused spec slot */
573 for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
574 if (st->roadstop_speclist[i].spec == nullptr && st->roadstop_speclist[i].grfid == 0) break;
575 }
576
577 if (i == NUM_ROADSTOPSPECS_PER_STATION) {
578 /* Full, give up */
579 return -1;
580 }
581
582 if (exec) {
583 if (i >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(i + 1);
584 st->roadstop_speclist[i].spec = statspec;
585 st->roadstop_speclist[i].grfid = statspec->grf_prop.grfid;
586 st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id;
587
588 RoadStopUpdateCachedTriggers(st);
589 }
590
591 return i;
592}
593
594void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex)
595{
596 /* specindex of 0 (default) is never freeable */
597 if (specindex == 0) return;
598
599 /* Check custom road stop tiles if the specindex is still in use */
600 for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
601 if (GetCustomRoadStopSpecIndex(tile_data.tile) == specindex) {
602 return;
603 }
604 }
605
606 /* This specindex is no longer in use, so deallocate it */
607 st->roadstop_speclist[specindex].spec = nullptr;
608 st->roadstop_speclist[specindex].grfid = 0;
609 st->roadstop_speclist[specindex].localidx = 0;
610
611 /* If this was the highest spec index, reallocate */
612 if (specindex == st->roadstop_speclist.size() - 1) {
613 size_t num_specs;
614 for (num_specs = st->roadstop_speclist.size() - 1; num_specs > 0; num_specs--) {
615 if (st->roadstop_speclist[num_specs].grfid != 0) break;
616 }
617
618 if (num_specs > 0) {
619 st->roadstop_speclist.resize(num_specs + 1);
620 } else {
621 st->roadstop_speclist.clear();
624 return;
625 }
626 }
627
628 RoadStopUpdateCachedTriggers(st);
629}
630
635void RoadStopUpdateCachedTriggers(BaseStation *st)
636{
639
640 /* Combine animation trigger bitmask for all road stop specs
641 * of this station. */
642 for (const auto &sm : GetStationSpecList<RoadStopSpec>(st)) {
643 if (sm.spec == nullptr) continue;
644 st->cached_roadstop_anim_triggers |= sm.spec->animation.triggers;
645 st->cached_roadstop_cargo_triggers |= sm.spec->cargo_triggers;
646 }
647}
debug_inline constexpr 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.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
Struct containing information relating to NewGRF classes for stations and airports.
static std::span< NewGRFClass< Tspec, Tindex, Tmax > const > Classes()
Get read-only span of all classes of this type.
StringID name
Name of this class.
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.
std::span< Tspec *const > Specs() const
Get read-only span of specs of this class.
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.
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.
CompanyID _current_company
Company currently doing an action.
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:989
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:17
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
@ Random
Randomise borders.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:159
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition map.cpp:142
static constexpr CargoType SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoType SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoType SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
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.
uint32_t GetBadgeVariableResult(const GRFFile &grffile, std::span< const BadgeID > badges, uint32_t parameter)
Test for a matching badge in a list of badges, returning the number of matching bits.
Functions related to NewGRF badges.
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.
@ AnimationNextFrame
Use a custom next frame callback.
@ AnimationSpeed
Customize the animation speed of the road stop.
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.
@ Overlay
Drive-through stops: Draw the road overlay, e.g. pavement.
@ WaypGround
Waypoints: Draw the sprite layout ground tile (on top of the road)
@ Road
Bay stops: Draw the road itself.
bool IsWaypointClass(const RoadStopClass &cls)
Test if a RoadStopClass is the waypoint class.
RoadStopRandomTrigger
@ RSRT_CARGO_TAKEN
Trigger roadstop when cargo is completely taken.
@ RSRT_NEW_CARGO
Trigger roadstop on arrival of new cargo.
@ ROADSTOP_CLASS_DFLT
Default road stop class.
@ 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.
@ RoadOnly
Only show in the road build menu (not tram).
@ Cb141RandomBits
Callback 141 needs random bits.
@ TramOnly
Only show in the tram build menu (not road).
@ DrawModeRegister
Read draw mode from register 0x100.
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:230
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition road.h:52
@ ROTSG_ROADSTOP
Required: Bay stop surface.
Definition road.h:61
@ ROTSG_GROUND
Required: Main group of ground images.
Definition road.h:53
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
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:91
PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition sprite.h:174
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
Definition sprites.h:1539
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.
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?
bool IsAnyRoadStopTile(Tile t)
Is tile t a road stop station?
RoadStopType
Types of RoadStops.
@ Bus
A standard stop for buses.
@ Truck
A standard stop for trucks.
StationType
Station types.
Definition of base types and functions in a cross-platform compatible way.
Helper class for a unified approach to NewGRF animation.
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.
std::vector< SpecMapping< RoadStopSpec > > roadstop_speclist
List of road stop specs of this station.
StationFacilities facilities
The facilities that this station has.
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.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
CargoTypes cached_roadstop_cargo_triggers
NOSAVE: Combined cargo trigger bitmask for road stops.
uint16_t random_bits
Random bits assigned to this station.
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.
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:46
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:47
const struct GRFFile * grffile
grf file that introduced this entity
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoType -> local ID)
Definition newgrf.h:135
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
Tindex index
Index of this pool item.
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)
uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override
Get a variable value.
StationType type
Station type.
const struct RoadStopSpec * roadstopspec
Station (type) specification.
struct BaseStation * st
Instance of the station.
CargoType cargo_type
Type of cargo of the station.
TileIndex tile
Tile of the station.
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.
VariableGRFFileProps 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 * From(BaseStation *st)
Converts a BaseStation to SpecializedStation with type checking.
virtual const SpriteGroup * Resolve(ResolverObject &object) const
Base sprite group resolver.
Station data structure.
std::array< GoodsEntry, NUM_CARGO > goods
Goods at this station.
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:52
TileIndex xy
town center tile
Definition town.h:53
const struct SpriteGroup * GetSpriteGroup(size_t index) const
Get the SpriteGroup at the specified index.
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.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
Functions related to (drawing on) viewports.
Types related to windows.