OpenTTD Source 20241222-master-gc72542431a
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"
26#include "newgrf_sound.h"
27
28#include "safeguards.h"
29
30template <>
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
40template <>
41bool RoadStopClass::IsUIAvailable(uint) const
42{
43 return true;
44}
45
46/* Instantiate RoadStopClass. */
48
49static 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
67uint32_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
221RoadStopResolverObject::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
251TownScopeResolver *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
266uint16_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
281void 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
341uint16_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
359
360void AnimateRoadStopTile(TileIndex tile)
361{
362 const RoadStopSpec *ss = GetRoadStopSpec(tile);
363 if (ss == nullptr) return;
364
366}
367
368void 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
408void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type)
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
481bool GetIfNewStopsByType(RoadStopType rs, RoadType roadtype)
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
500bool 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
515bool 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
540const 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
549int 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.grfid;
574 st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id;
575
576 RoadStopUpdateCachedTriggers(st);
577 }
578
579 return i;
580}
581
582void 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
616 RoadStopUpdateCachedTriggers(st);
617}
618
623void RoadStopUpdateCachedTriggers(BaseStation *st)
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}
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 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.
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.
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
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: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.
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.
static constexpr CargoID SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoID 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.
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.
@ 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.
@ 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).
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.
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.
@ ROADSTOP_BUS
A standard stop for buses.
@ ROADSTOP_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.
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.
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.
Specification of a cargo type.
Definition cargotype.h:76
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
uint32_t grfid
grfid that introduced 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:130
StationCargoList cargo
The cargo packets of cargo waiting in this station.
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.
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.
CargoID cargo_type
Type of cargo of the station.
struct BaseStation * st
Instance 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.
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 * 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.
GoodsEntry goods[NUM_CARGO]
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: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.
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.