OpenTTD Source 20250205-master-gfd85ab1e2c
newgrf_station.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "debug.h"
12#include "station_base.h"
13#include "waypoint_base.h"
14#include "roadstop_base.h"
15#include "newgrf_cargo.h"
16#include "newgrf_station.h"
17#include "newgrf_spritegroup.h"
18#include "newgrf_sound.h"
19#include "newgrf_railtype.h"
20#include "town.h"
21#include "newgrf_town.h"
22#include "company_func.h"
23#include "tunnelbridge_map.h"
25#include "newgrf_class_func.h"
27
28#include "safeguards.h"
29
30
31template <>
32/* static */ void StationClass::InsertDefaults()
33{
34 /* Set up initial data */
35 StationClass::Get(StationClass::Allocate(STATION_CLASS_LABEL_DEFAULT))->name = STR_STATION_CLASS_DFLT;
36 StationClass::Get(StationClass::Allocate(STATION_CLASS_LABEL_DEFAULT))->Insert(nullptr);
37 StationClass::Get(StationClass::Allocate(STATION_CLASS_LABEL_WAYPOINT))->name = STR_STATION_CLASS_WAYP;
38 StationClass::Get(StationClass::Allocate(STATION_CLASS_LABEL_WAYPOINT))->Insert(nullptr);
39}
40
41template <>
42bool StationClass::IsUIAvailable(uint) const
43{
44 return true;
45}
46
47/* Instantiate StationClass. */
49
50static const uint NUM_STATIONSSPECS_PER_STATION = 255;
51
52enum TriggerArea : uint8_t {
53 TA_TILE,
54 TA_PLATFORM,
55 TA_WHOLE,
56};
57
59 ETileArea(const BaseStation *st, TileIndex tile, TriggerArea ta)
60 {
61 switch (ta) {
62 default: NOT_REACHED();
63
64 case TA_TILE:
65 this->tile = tile;
66 this->w = 1;
67 this->h = 1;
68 break;
69
70 case TA_PLATFORM: {
71 TileIndex start, end;
72 Axis axis = GetRailStationAxis(tile);
73 TileIndexDiff delta = TileOffsByAxis(axis);
74
75 for (end = tile; IsRailStationTile(end + delta) && IsCompatibleTrainStationTile(end + delta, tile); end += delta) { /* Nothing */ }
76 for (start = tile; IsRailStationTile(start - delta) && IsCompatibleTrainStationTile(start - delta, tile); start -= delta) { /* Nothing */ }
77
78 this->tile = start;
79 this->w = TileX(end) - TileX(start) + 1;
80 this->h = TileY(end) - TileY(start) + 1;
81 break;
82 }
83
84 case TA_WHOLE:
85 st->GetTileArea(this, Station::IsExpected(st) ? StationType::Rail : StationType::RailWaypoint);
86 break;
87 }
88 }
89};
90
91
104uint32_t GetPlatformInfo(Axis axis, uint8_t tile, int platforms, int length, int x, int y, bool centred)
105{
106 uint32_t retval = 0;
107
108 if (axis == AXIS_X) {
109 Swap(platforms, length);
110 Swap(x, y);
111 }
112
113 if (centred) {
114 x -= platforms / 2;
115 y -= length / 2;
116 x = Clamp(x, -8, 7);
117 y = Clamp(y, -8, 7);
118 SB(retval, 0, 4, y & 0xF);
119 SB(retval, 4, 4, x & 0xF);
120 } else {
121 SB(retval, 0, 4, std::min(15, y));
122 SB(retval, 4, 4, std::min(15, length - y - 1));
123 SB(retval, 8, 4, std::min(15, x));
124 SB(retval, 12, 4, std::min(15, platforms - x - 1));
125 }
126 SB(retval, 16, 4, std::min(15, length));
127 SB(retval, 20, 4, std::min(15, platforms));
128 SB(retval, 24, 8, tile);
129
130 return retval;
131}
132
133
142static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
143{
144 uint8_t orig_type = 0;
145 Axis orig_axis = AXIS_X;
146 StationID sid = GetStationIndex(tile);
147
148 if (check_type) orig_type = GetCustomStationSpecIndex(tile);
149 if (check_axis) orig_axis = GetRailStationAxis(tile);
150
151 for (;;) {
152 TileIndex new_tile = TileAdd(tile, delta);
153
154 if (!IsTileType(new_tile, MP_STATION) || GetStationIndex(new_tile) != sid) break;
155 if (!HasStationRail(new_tile)) break;
156 if (check_type && GetCustomStationSpecIndex(new_tile) != orig_type) break;
157 if (check_axis && GetRailStationAxis(new_tile) != orig_axis) break;
158
159 tile = new_tile;
160 }
161 return tile;
162}
163
164
165static uint32_t GetPlatformInfoHelper(TileIndex tile, bool check_type, bool check_axis, bool centred)
166{
167 int tx = TileX(tile);
168 int ty = TileY(tile);
169 int sx = TileX(FindRailStationEnd(tile, TileDiffXY(-1, 0), check_type, check_axis));
170 int sy = TileY(FindRailStationEnd(tile, TileDiffXY( 0, -1), check_type, check_axis));
171 int ex = TileX(FindRailStationEnd(tile, TileDiffXY( 1, 0), check_type, check_axis)) + 1;
172 int ey = TileY(FindRailStationEnd(tile, TileDiffXY( 0, 1), check_type, check_axis)) + 1;
173
174 tx -= sx; ex -= sx;
175 ty -= sy; ey -= sy;
176
177 return GetPlatformInfo(GetRailStationAxis(tile), GetStationGfx(tile), ex, ey, tx, ty, centred);
178}
179
180
181static uint32_t GetRailContinuationInfo(TileIndex tile)
182{
183 /* Tile offsets and exit dirs for X axis */
184 static const Direction x_dir[8] = { DIR_SW, DIR_NE, DIR_SE, DIR_NW, DIR_S, DIR_E, DIR_W, DIR_N };
186
187 /* Tile offsets and exit dirs for Y axis */
188 static const Direction y_dir[8] = { DIR_SE, DIR_NW, DIR_SW, DIR_NE, DIR_S, DIR_W, DIR_E, DIR_N };
190
191 Axis axis = GetRailStationAxis(tile);
192
193 /* Choose appropriate lookup table to use */
194 const Direction *dir = axis == AXIS_X ? x_dir : y_dir;
195 const DiagDirection *diagdir = axis == AXIS_X ? x_exits : y_exits;
196
197 uint32_t res = 0;
198 uint i;
199
200 for (i = 0; i < lengthof(x_dir); i++, dir++, diagdir++) {
201 TileIndex neighbour_tile = tile + TileOffsByDir(*dir);
202 TrackBits trackbits = TrackStatusToTrackBits(GetTileTrackStatus(neighbour_tile, TRANSPORT_RAIL, 0));
203 if (trackbits != TRACK_BIT_NONE) {
204 /* If there is any track on the tile, set the bit in the second byte */
205 SetBit(res, i + 8);
206
207 /* With tunnels and bridges the tile has tracks, but they are not necessarily connected
208 * with the next tile because the ramp is not going in the right direction. */
209 if (IsTileType(neighbour_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(neighbour_tile) != *diagdir) {
210 continue;
211 }
212
213 /* If any track reaches our exit direction, set the bit in the lower byte */
214 if (trackbits & DiagdirReachesTracks(*diagdir)) SetBit(res, i);
215 }
216 }
217
218 return res;
219}
220
221
222/* Station Resolver Functions */
223/* virtual */ uint32_t StationScopeResolver::GetRandomBits() const
224{
225 return (this->st == nullptr ? 0 : this->st->random_bits) | (this->tile == INVALID_TILE ? 0 : GetStationTileRandomBits(this->tile) << 16);
226}
227
228
229/* virtual */ uint32_t StationScopeResolver::GetTriggers() const
230{
231 return this->st == nullptr ? 0 : this->st->waiting_triggers;
232}
233
234
240static struct {
241 uint32_t v40;
242 uint32_t v41;
243 uint32_t v45;
244 uint32_t v46;
245 uint32_t v47;
246 uint32_t v49;
247 uint8_t valid;
249
256{
257 if (!this->town_scope.has_value()) {
258 Town *t = nullptr;
259 if (this->station_scope.st != nullptr) {
260 t = this->station_scope.st->town;
261 } else if (this->station_scope.tile != INVALID_TILE) {
262 t = ClosestTownFromTile(this->station_scope.tile, UINT_MAX);
263 }
264 if (t == nullptr) return nullptr;
265 this->town_scope.emplace(*this, t, this->station_scope.st == nullptr);
266 }
267 return &*this->town_scope;
268}
269
270/* virtual */ uint32_t StationScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
271{
272 if (this->st == nullptr) {
273 /* Station does not exist, so we're in a purchase list or the land slope check callback. */
274 switch (variable) {
275 case 0x40:
276 case 0x41:
277 case 0x46:
278 case 0x47:
279 case 0x49: return 0x2110000; // Platforms, tracks & position
280 case 0x42: return 0; // Rail type (XXX Get current type from GUI?)
281 case 0x43: return GetCompanyInfo(_current_company); // Station owner
282 case 0x44: return 2; // PBS status
283 case 0x67: // Land info of nearby tile
284 if (this->axis != INVALID_AXIS && this->tile != INVALID_TILE) {
285 TileIndex tile = this->tile;
286 if (parameter != 0) tile = GetNearbyTile(parameter, tile, true, this->axis); // only perform if it is required
287
288 Slope tileh = GetTileSlope(tile);
289 bool swap = (this->axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
290
291 return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
292 }
293 break;
294
295 case 0xFA: return ClampTo<uint16_t>(TimerGameCalendar::date - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Build date, clamped to a 16 bit value
296 }
297
298 available = false;
299 return UINT_MAX;
300 }
301
302 switch (variable) {
303 /* Calculated station variables */
304 case 0x40:
305 if (!HasBit(_svc.valid, 0)) { _svc.v40 = GetPlatformInfoHelper(this->tile, false, false, false); SetBit(_svc.valid, 0); }
306 return _svc.v40;
307
308 case 0x41:
309 if (!HasBit(_svc.valid, 1)) { _svc.v41 = GetPlatformInfoHelper(this->tile, true, false, false); SetBit(_svc.valid, 1); }
310 return _svc.v41;
311
312 case 0x42: return GetTerrainType(this->tile) | (GetReverseRailTypeTranslation(GetRailType(this->tile), this->statspec->grf_prop.grffile) << 8);
313 case 0x43: return GetCompanyInfo(this->st->owner); // Station owner
314 case 0x44: return HasStationReservation(this->tile) ? 7 : 4; // PBS status
315 case 0x45:
316 if (!HasBit(_svc.valid, 2)) { _svc.v45 = GetRailContinuationInfo(this->tile); SetBit(_svc.valid, 2); }
317 return _svc.v45;
318
319 case 0x46:
320 if (!HasBit(_svc.valid, 3)) { _svc.v46 = GetPlatformInfoHelper(this->tile, false, false, true); SetBit(_svc.valid, 3); }
321 return _svc.v46;
322
323 case 0x47:
324 if (!HasBit(_svc.valid, 4)) { _svc.v47 = GetPlatformInfoHelper(this->tile, true, false, true); SetBit(_svc.valid, 4); }
325 return _svc.v47;
326
327 case 0x49:
328 if (!HasBit(_svc.valid, 5)) { _svc.v49 = GetPlatformInfoHelper(this->tile, false, true, false); SetBit(_svc.valid, 5); }
329 return _svc.v49;
330
331 case 0x4A: // Animation frame of tile
332 return GetAnimationFrame(this->tile);
333
334 /* Variables which use the parameter */
335 /* Variables 0x60 to 0x65 and 0x69 are handled separately below */
336 case 0x66: { // Animation frame of nearby tile
337 TileIndex tile = this->tile;
338 if (parameter != 0) tile = GetNearbyTile(parameter, tile);
339 return this->st->TileBelongsToRailStation(tile) ? GetAnimationFrame(tile) : UINT_MAX;
340 }
341
342 case 0x67: { // Land info of nearby tile
343 Axis axis = GetRailStationAxis(this->tile);
344 TileIndex tile = this->tile;
345 if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
346
347 Slope tileh = GetTileSlope(tile);
348 bool swap = (axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
349
350 return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0);
351 }
352
353 case 0x68: { // Station info of nearby tiles
354 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
355
356 if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
357
358 uint32_t grfid = this->st->speclist[GetCustomStationSpecIndex(this->tile)].grfid;
359 bool perpendicular = GetRailStationAxis(this->tile) != GetRailStationAxis(nearby_tile);
360 bool same_station = this->st->TileBelongsToRailStation(nearby_tile);
361 uint32_t res = GB(GetStationGfx(nearby_tile), 1, 2) << 12 | !!perpendicular << 11 | !!same_station << 10;
362
363 if (IsCustomStationSpecIndex(nearby_tile)) {
364 const auto &sm = BaseStation::GetByTile(nearby_tile)->speclist[GetCustomStationSpecIndex(nearby_tile)];
365 res |= 1 << (sm.grfid != grfid ? 9 : 8) | ClampTo<uint8_t>(sm.localidx);
366 }
367 return res;
368 }
369
370 case 0x6A: { // GRFID of nearby station tiles
371 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
372
373 if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
374 if (!IsCustomStationSpecIndex(nearby_tile)) return 0;
375
376 const auto &sm = BaseStation::GetByTile(nearby_tile)->speclist[GetCustomStationSpecIndex(nearby_tile)];
377 return sm.grfid;
378 }
379
380 case 0x6B: { // 16 bit Station ID of nearby tiles
381 TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
382
383 if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
384 if (!IsCustomStationSpecIndex(nearby_tile)) return 0xFFFE;
385
386 uint32_t grfid = this->st->speclist[GetCustomStationSpecIndex(this->tile)].grfid;
387
388 const auto &sm = BaseStation::GetByTile(nearby_tile)->speclist[GetCustomStationSpecIndex(nearby_tile)];
389 if (sm.grfid == grfid) {
390 return sm.localidx;
391 }
392
393 return 0xFFFE;
394 }
395
396 /* General station variables */
397 case 0x82: return 50;
398 case 0x84: return this->st->string_id;
399 case 0x86: return 0;
400 case 0xF0: return this->st->facilities;
401 case 0xFA: return ClampTo<uint16_t>(this->st->build_date - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR);
402 }
403
404 return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
405}
406
407uint32_t Station::GetNewGRFVariable(const ResolverObject &object, uint8_t variable, uint8_t parameter, bool &available) const
408{
409 switch (variable) {
410 case 0x48: { // Accepted cargo types
411 uint32_t value = GetAcceptanceMask(this);
412 return value;
413 }
414
415 case 0x8A: return this->had_vehicle_of_type;
416 case 0xF1: return (this->airport.tile != INVALID_TILE) ? this->airport.GetSpec()->ttd_airport_type : ATP_TTDP_LARGE;
417 case 0xF2: return (this->truck_stops != nullptr) ? this->truck_stops->status : 0;
418 case 0xF3: return (this->bus_stops != nullptr) ? this->bus_stops->status : 0;
419 case 0xF6: return this->airport.flags;
420 case 0xF7: return GB(this->airport.flags, 8, 8);
421 }
422
423 /* Handle cargo variables with parameter, 0x60 to 0x65 and 0x69 */
424 if ((variable >= 0x60 && variable <= 0x65) || variable == 0x69) {
425 CargoType c = GetCargoTranslation(parameter, object.grffile);
426
427 if (!IsValidCargoType(c)) {
428 switch (variable) {
429 case 0x62: return 0xFFFFFFFF;
430 case 0x64: return 0xFF00;
431 default: return 0;
432 }
433 }
434 const GoodsEntry *ge = &this->goods[c];
435
436 switch (variable) {
437 case 0x60: return ge->HasData() ? std::min(ge->GetData().cargo.TotalCount(), 4095u) : 0;
438 case 0x61: return ge->HasVehicleEverTriedLoading() ? ge->time_since_pickup : 0;
439 case 0x62: return ge->HasRating() ? ge->rating : 0xFFFFFFFF;
440 case 0x63: return ge->HasData() ? ge->GetData().cargo.PeriodsInTransit() : 0;
441 case 0x64: return ge->HasVehicleEverTriedLoading() ? ge->last_speed | (ge->last_age << 8) : 0xFF00;
442 case 0x65: return GB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1) << 3;
443 case 0x69: {
444 static_assert((int)GoodsEntry::GES_EVER_ACCEPTED + 1 == (int)GoodsEntry::GES_LAST_MONTH);
445 static_assert((int)GoodsEntry::GES_EVER_ACCEPTED + 2 == (int)GoodsEntry::GES_CURRENT_MONTH);
448 }
449 }
450 }
451
452 /* Handle cargo variables (deprecated) */
453 if (variable >= 0x8C && variable <= 0xEC) {
454 const GoodsEntry *g = &this->goods[GB(variable - 0x8C, 3, 4)];
455 switch (GB(variable - 0x8C, 0, 3)) {
456 case 0: return g->HasData() ? g->GetData().cargo.TotalCount() : 0;
457 case 1: return GB(g->HasData() ? std::min(g->GetData().cargo.TotalCount(), 4095u) : 0, 0, 4) | (GB(g->status, GoodsEntry::GES_ACCEPTANCE, 1) << 7);
458 case 2: return g->time_since_pickup;
459 case 3: return g->rating;
460 case 4: return g->HasData() ? g->GetData().cargo.GetFirstStation() : INVALID_STATION;
461 case 5: return g->HasData() ? g->GetData().cargo.PeriodsInTransit() : 0;
462 case 6: return g->last_speed;
463 case 7: return g->last_age;
464 }
465 }
466
467 Debug(grf, 1, "Unhandled station variable 0x{:X}", variable);
468
469 available = false;
470 return UINT_MAX;
471}
472
473uint32_t Waypoint::GetNewGRFVariable(const ResolverObject &, uint8_t variable, [[maybe_unused]] uint8_t parameter, bool &available) const
474{
475 switch (variable) {
476 case 0x48: return 0; // Accepted cargo types
477 case 0x8A: return HVOT_WAYPOINT;
478 case 0xF1: return 0; // airport type
479 case 0xF2: return 0; // truck stop status
480 case 0xF3: return 0; // bus stop status
481 case 0xF6: return 0; // airport flags
482 case 0xF7: return 0; // airport flags cont.
483 }
484
485 /* Handle cargo variables with parameter, 0x60 to 0x65 */
486 if (variable >= 0x60 && variable <= 0x65) {
487 return 0;
488 }
489
490 /* Handle cargo variables (deprecated) */
491 if (variable >= 0x8C && variable <= 0xEC) {
492 switch (GB(variable - 0x8C, 0, 3)) {
493 case 3: return INITIAL_STATION_RATING;
494 case 4: return INVALID_STATION;
495 default: return 0;
496 }
497 }
498
499 Debug(grf, 1, "Unhandled station variable 0x{:X}", variable);
500
501 available = false;
502 return UINT_MAX;
503}
504
505/* virtual */ const SpriteGroup *StationResolverObject::ResolveReal(const RealSpriteGroup *group) const
506{
507 if (this->station_scope.st == nullptr || !Station::IsExpected(this->station_scope.st)) {
508 return group->loading[0];
509 }
510
511 uint cargo = 0;
512 const Station *st = Station::From(this->station_scope.st);
513
514 switch (this->station_scope.cargo_type) {
515 case INVALID_CARGO:
518 cargo = 0;
519 break;
520
522 for (const GoodsEntry &ge : st->goods) {
523 if (!ge.HasData()) continue;
524 cargo += ge.GetData().cargo.TotalCount();
525 }
526 break;
527
528 default: {
529 const GoodsEntry &ge = st->goods[this->station_scope.cargo_type];
530 cargo = ge.HasData() ? ge.GetData().cargo.TotalCount() : 0;
531 break;
532 }
533 }
534
536 cargo = std::min(0xfffu, cargo);
537
538 if (cargo > this->station_scope.statspec->cargo_threshold) {
539 if (!group->loading.empty()) {
540 uint set = ((cargo - this->station_scope.statspec->cargo_threshold) * (uint)group->loading.size()) / (4096 - this->station_scope.statspec->cargo_threshold);
541 return group->loading[set];
542 }
543 } else {
544 if (!group->loaded.empty()) {
545 uint set = (cargo * (uint)group->loaded.size()) / (this->station_scope.statspec->cargo_threshold + 1);
546 return group->loaded[set];
547 }
548 }
549
550 return group->loading[0];
551}
552
554{
555 return GSF_STATIONS;
556}
557
559{
561}
562
573 CallbackID callback, uint32_t callback_param1, uint32_t callback_param2)
574 : ResolverObject(statspec->grf_prop.grffile, callback, callback_param1, callback_param2),
575 station_scope(*this, statspec, base_station, tile)
576{
577 /* Invalidate all cached vars */
578 _svc.valid = 0;
579
581
582 if (this->station_scope.st == nullptr) {
583 /* No station, so we are in a purchase list */
585 } else if (Station::IsExpected(this->station_scope.st)) {
586 const Station *st = Station::From(this->station_scope.st);
587 /* Pick the first cargo that we have waiting */
588 for (const CargoSpec *cs : CargoSpec::Iterate()) {
589 if (this->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != nullptr &&
590 st->goods[cs->Index()].HasData() && st->goods[cs->Index()].GetData().cargo.TotalCount() > 0) {
591 ctype = cs->Index();
592 break;
593 }
594 }
595 }
596
597 if (this->station_scope.statspec->grf_prop.spritegroup[ctype] == nullptr) {
599 }
600
601 /* Remember the cargo type we've picked */
602 this->station_scope.cargo_type = ctype;
604}
605
614SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32_t var10)
615{
616 StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, var10);
617 const SpriteGroup *group = object.Resolve();
618 if (group == nullptr || group->type != SGT_RESULT) return 0;
619 return group->GetResult() - 0x42D;
620}
621
631SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
632{
633 /* callback_param1 == 2 means we are resolving the foundation sprites. */
634 StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, 2, layout | (edge_info << 16));
635
636 const SpriteGroup *group = object.Resolve();
637 if (group == nullptr || group->type != SGT_RESULT) return 0;
638
639 /* Note: SpriteGroup::Resolve zeroes all registers, so register 0x100 is initialised to 0. (compatibility) */
640 return group->GetResult() + GetRegister(0x100);
641}
642
643
644uint16_t GetStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile)
645{
646 StationResolverObject object(statspec, st, tile, callback, param1, param2);
647 return object.ResolveCallback();
648}
649
660CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, uint8_t plat_len, uint8_t numtracks)
661{
662 TileIndex diff = cur_tile - north_tile;
663 Slope slope = GetTileSlope(cur_tile);
664
665 StationResolverObject object(statspec, nullptr, cur_tile, CBID_STATION_LAND_SLOPE_CHECK,
666 (slope << 4) | (slope ^ (axis == AXIS_Y && HasBit(slope, CORNER_W) != HasBit(slope, CORNER_E) ? SLOPE_EW : 0)),
667 (numtracks << 24) | (plat_len << 16) | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff)));
668 object.station_scope.axis = axis;
669
670 uint16_t cb_res = object.ResolveCallback();
671
672 /* Failed callback means success. */
673 if (cb_res == CALLBACK_FAILED) return CommandCost();
674
675 /* The meaning of bit 10 is inverted for a grf version < 8. */
676 if (statspec->grf_prop.grffile->grf_version < 8) ToggleBit(cb_res, 10);
677 return GetErrorMessageFromLocationCallbackResult(cb_res, statspec->grf_prop.grffile, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
678}
679
680
688int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec)
689{
690 uint i;
691
692 if (statspec == nullptr || st == nullptr) return 0;
693
694 for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) {
695 if (st->speclist[i].spec == nullptr && st->speclist[i].grfid == 0) break;
696 }
697
699 /* As final effort when the spec list is already full...
700 * try to find the same spec and return that one. This might
701 * result in slightly "wrong" (as per specs) looking stations,
702 * but it's fairly unlikely that one reaches the limit anyways.
703 */
704 for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) {
705 if (st->speclist[i].spec == statspec) return i;
706 }
707
708 return -1;
709 }
710
711 if (exec) {
712 if (i >= st->speclist.size()) st->speclist.resize(i + 1);
713 st->speclist[i].spec = statspec;
714 st->speclist[i].grfid = statspec->grf_prop.grfid;
715 st->speclist[i].localidx = statspec->grf_prop.local_id;
716
718 }
719
720 return i;
721}
722
723
730void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex)
731{
732 /* specindex of 0 (default) is never freeable */
733 if (specindex == 0) return;
734
735 ETileArea area = ETileArea(st, INVALID_TILE, TA_WHOLE);
736 /* Check all tiles over the station to check if the specindex is still in use */
737 for (TileIndex tile : area) {
738 if (st->TileBelongsToRailStation(tile) && GetCustomStationSpecIndex(tile) == specindex) {
739 return;
740 }
741 }
742
743 /* This specindex is no longer in use, so deallocate it */
744 st->speclist[specindex].spec = nullptr;
745 st->speclist[specindex].grfid = 0;
746 st->speclist[specindex].localidx = 0;
747
748 /* If this was the highest spec index, reallocate */
749 if (specindex == st->speclist.size() - 1) {
750 size_t num_specs;
751 for (num_specs = st->speclist.size() - 1; num_specs > 0; num_specs--) {
752 if (st->speclist[num_specs].grfid != 0) break;
753 }
754
755 if (num_specs > 0) {
756 st->speclist.resize(num_specs + 1);
757 } else {
758 st->speclist.clear();
759 st->cached_anim_triggers = 0;
760 st->cached_cargo_triggers = 0;
761 return;
762 }
763 }
764
766}
767
778bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station)
779{
780 const DrawTileSprites *sprites = nullptr;
781 const RailTypeInfo *rti = GetRailTypeInfo(railtype);
782 PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
783 uint tile = 2;
784
785 const StationSpec *statspec = StationClass::Get(sclass)->GetSpec(station);
786 if (statspec == nullptr) return false;
787
789 uint16_t callback = GetStationCallback(CBID_STATION_DRAW_TILE_LAYOUT, 0, 0, statspec, nullptr, INVALID_TILE);
790 if (callback != CALLBACK_FAILED) tile = callback & ~1;
791 }
792
793 uint32_t total_offset = rti->GetRailtypeSpriteOffset();
794 uint32_t relocation = 0;
795 uint32_t ground_relocation = 0;
796 const NewGRFSpriteLayout *layout = nullptr;
797 DrawTileSprites tmp_rail_layout;
798
799 if (statspec->renderdata.empty()) {
800 sprites = GetStationTileLayout(StationType::Rail, tile + axis);
801 } else {
802 layout = &statspec->renderdata[(tile < statspec->renderdata.size()) ? tile + axis : (uint)axis];
803 if (!layout->NeedsPreprocessing()) {
804 sprites = layout;
805 layout = nullptr;
806 }
807 }
808
809 if (layout != nullptr) {
810 /* Sprite layout which needs preprocessing */
811 bool separate_ground = statspec->flags.Test(StationSpecFlag::SeparateGround);
812 uint32_t var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground);
813 for (uint8_t var10 : SetBitIterator(var10_values)) {
814 uint32_t var10_relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, var10);
815 layout->ProcessRegisters(var10, var10_relocation, separate_ground);
816 }
817
818 tmp_rail_layout.seq = layout->GetLayout(&tmp_rail_layout.ground);
819 sprites = &tmp_rail_layout;
820 total_offset = 0;
821 } else {
822 /* Simple sprite layout */
823 ground_relocation = relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, 0);
825 ground_relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, 1);
826 }
827 ground_relocation += rti->fallback_railtype;
828 }
829
830 SpriteID image = sprites->ground.sprite;
831 PaletteID pal = sprites->ground.pal;
832 RailTrackOffset overlay_offset;
833 if (rti->UsesOverlay() && SplitGroundSpriteForOverlay(nullptr, &image, &overlay_offset)) {
835 DrawSprite(image, PAL_NONE, x, y);
836 DrawSprite(ground + overlay_offset, PAL_NONE, x, y);
837 } else {
838 image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset;
839 if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation;
840 DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
841 }
842
843 DrawRailTileSeqInGUI(x, y, sprites, total_offset, relocation, palette);
844
845 return true;
846}
847
848
849const StationSpec *GetStationSpec(TileIndex t)
850{
851 if (!IsCustomStationSpecIndex(t)) return nullptr;
852
853 const BaseStation *st = BaseStation::GetByTile(t);
854 uint specindex = GetCustomStationSpecIndex(t);
855 return specindex < st->speclist.size() ? st->speclist[specindex].spec : nullptr;
856}
857
859uint16_t GetAnimStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int)
860{
861 return GetStationCallback(callback, param1, param2, statspec, st, tile);
862}
863
872
873void AnimateStationTile(TileIndex tile)
874{
875 const StationSpec *ss = GetStationSpec(tile);
876 if (ss == nullptr) return;
877
879}
880
881void TriggerStationAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoType cargo_type)
882{
883 /* List of coverage areas for each animation trigger */
884 static const TriggerArea tas[] = {
885 TA_TILE, TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_WHOLE
886 };
887
888 /* Get Station if it wasn't supplied */
889 if (st == nullptr) st = BaseStation::GetByTile(trigger_tile);
890
891 /* Check the cached animation trigger bitmask to see if we need
892 * to bother with any further processing. */
893 if (!HasBit(st->cached_anim_triggers, trigger)) return;
894
895 uint16_t random_bits = Random();
896 ETileArea area = ETileArea(st, trigger_tile, tas[trigger]);
897
898 /* Check all tiles over the station to check if the specindex is still in use */
899 for (TileIndex tile : area) {
900 if (st->TileBelongsToRailStation(tile)) {
901 const StationSpec *ss = GetStationSpec(tile);
902 if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
903 CargoType cargo;
904 if (!IsValidCargoType(cargo_type)) {
905 cargo = INVALID_CARGO;
906 } else {
907 cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
908 }
909 StationAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, tile, (random_bits << 16) | GB(Random(), 0, 16), (uint8_t)trigger | (cargo << 8));
910 }
911 }
912 }
913}
914
923{
924 /* List of coverage areas for each animation trigger */
925 static const TriggerArea tas[] = {
926 TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
927 };
928
929 /* Get Station if it wasn't supplied */
930 if (st == nullptr) st = Station::GetByTile(trigger_tile);
931
932 /* Check the cached cargo trigger bitmask to see if we need
933 * to bother with any further processing. */
934 if (st->cached_cargo_triggers == 0) return;
935 if (IsValidCargoType(cargo_type) && !HasBit(st->cached_cargo_triggers, cargo_type)) return;
936
937 uint32_t whole_reseed = 0;
938 ETileArea area = ETileArea(st, trigger_tile, tas[trigger]);
939
940 /* Bitmask of completely empty cargo types to be matched. */
941 CargoTypes empty_mask = (trigger == SRT_CARGO_TAKEN) ? GetEmptyMask(st) : 0;
942
943 /* Store triggers now for var 5F */
944 SetBit(st->waiting_triggers, trigger);
945 uint32_t used_triggers = 0;
946
947 /* Check all tiles over the station to check if the specindex is still in use */
948 for (TileIndex tile : area) {
949 if (st->TileBelongsToRailStation(tile)) {
950 const StationSpec *ss = GetStationSpec(tile);
951 if (ss == nullptr) continue;
952
953 /* Cargo taken "will only be triggered if all of those
954 * cargo types have no more cargo waiting." */
955 if (trigger == SRT_CARGO_TAKEN) {
956 if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
957 }
958
959 if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
960 StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
961 object.waiting_triggers = st->waiting_triggers;
962
963 const SpriteGroup *group = object.Resolve();
964 if (group == nullptr) continue;
965
966 used_triggers |= object.used_triggers;
967
968 uint32_t reseed = object.GetReseedSum();
969 if (reseed != 0) {
970 whole_reseed |= reseed;
971 reseed >>= 16;
972
973 /* Set individual tile random bits */
974 uint8_t random_bits = GetStationTileRandomBits(tile);
975 random_bits &= ~reseed;
976 random_bits |= Random() & reseed;
977 SetStationTileRandomBits(tile, random_bits);
978
980 }
981 }
982 }
983 }
984
985 /* Update whole station random bits */
986 st->waiting_triggers &= ~used_triggers;
987 if ((whole_reseed & 0xFFFF) != 0) {
988 st->random_bits &= ~whole_reseed;
989 st->random_bits |= Random() & whole_reseed;
990 }
991}
992
998{
999 st->cached_anim_triggers = 0;
1000 st->cached_cargo_triggers = 0;
1001
1002 /* Combine animation trigger bitmask for all station specs
1003 * of this station. */
1004 for (const auto &sm : GetStationSpecList<StationSpec>(st)) {
1005 if (sm.spec == nullptr) continue;
1006 st->cached_anim_triggers |= sm.spec->animation.triggers;
1007 st->cached_cargo_triggers |= sm.spec->cargo_triggers;
1008 }
1009}
1010
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
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.
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:105
uint PeriodsInTransit() const
Returns average number of cargo aging periods in transit for a cargo entity.
Common return value for all commands.
constexpr bool Test(Tenum value) const
Test if the enum value is set.
Struct containing information relating to NewGRF classes for stations and airports.
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.
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.
const Tspec * GetSpec(uint index) const
Get a spec from the class at a given index.
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:117
uint8_t fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations.
Definition rail.h:191
uint GetRailtypeSpriteOffset() const
Offset between the current railtype and normal rail.
Definition rail.h:285
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
StationID GetFirstStation() const
Returns first station of the first cargo packet in this list.
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.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
Direction
Defines the 8 directions on the map.
@ DIR_SW
Southwest.
@ DIR_NW
Northwest.
@ DIR_N
North.
@ DIR_SE
Southeast.
@ DIR_S
South.
@ DIR_NE
Northeast.
@ DIR_W
West.
@ DIR_E
East.
Axis
Allow incrementing of DiagDirDiff variables.
@ INVALID_AXIS
Flag for an invalid Axis.
@ AXIS_X
The X axis.
@ AXIS_Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_SW
Southwest.
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
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.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
@ Random
Randomise borders.
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:389
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:555
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition map_func.h:457
TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition map_func.h:584
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:415
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
constexpr void Swap(T &a, T &b)
Type safe swap operation.
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.
GrfSpecFeature
Definition newgrf.h:68
@ ATP_TTDP_LARGE
Same as AT_LARGE.
Function implementations related to NewGRF animation.
StationAnimationTrigger
Animation triggers for station.
StationCallbackMask
Callback masks for stations.
@ DrawTileLayout
Use callback to select a tile layout to use when drawing.
@ AnimationNextFrame
Use a custom next frame callback.
@ AnimationSpeed
Customize the animation speed of the station.
CallbackID
List of implemented NewGRF callbacks.
@ CBID_STATION_DRAW_TILE_LAYOUT
Choose a tile layout to draw, instead of the standard range.
@ CBID_NO_CALLBACK
Set when using the callback resolve system, but not to resolve a callback.
@ CBID_STATION_ANIMATION_SPEED
Called to indicate how long the current animation frame should last.
@ CBID_RANDOM_TRIGGER
Set when calling a randomizing trigger (almost undocumented).
@ CBID_STATION_ANIM_START_STOP
Called for periodically starting or stopping the animation.
@ CBID_STATION_LAND_SLOPE_CHECK
Callback done for each tile of a station to check the slope.
@ CBID_STATION_ANIM_NEXT_FRAME
Called to determine station tile next animation frame.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Cargo support for NewGRFs.
Implementation of the NewGRF class' functions.
CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, const GRFFile *grffile, StringID default_error)
Get the error message from a shape/location/slope check callback result.
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.
uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
Perform a reverse railtype lookup to get the GRF internal ID.
SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of rail types.
Functions related to NewGRF provided sounds.
Action 2 handling.
uint32_t GetRegister(uint i)
Gets the value of a so-called newgrf "register".
int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec)
Allocate a StationSpec to a Station.
uint32_t GetPlatformInfo(Axis axis, uint8_t tile, int platforms, int length, int x, int y, bool centred)
Evaluate a tile's position within a station, and return the result in a bit-stuffed format.
static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
Find the end of a railway station, from the tile, in the direction of delta.
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32_t var10)
Resolve sprites for drawing a station tile.
static struct @17 _svc
Station variable cache This caches 'expensive' station variable lookups which iterate over several ti...
void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoType cargo_type)
Trigger station randomisation.
SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info)
Resolve the sprites for custom station foundations.
uint8_t valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
void StationUpdateCachedTriggers(BaseStation *st)
Update the cached animation trigger bitmask for a station.
bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station)
Draw representation of a station tile for GUI purposes.
void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex)
Deallocate a StationSpec from a Station.
static const uint NUM_STATIONSSPECS_PER_STATION
Maximum number of parts per station.
CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, uint8_t plat_len, uint8_t numtracks)
Check the slope of a tile of a new station.
uint16_t GetAnimStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int)
Wrapper for animation control, see GetStationCallback.
Header file for NewGRF stations.
@ Cb141RandomBits
Callback 141 needs random bits.
@ SeparateGround
Use different sprite set for ground sprites.
@ DivByStationSize
Divide cargo amount by station size.
StationRandomTrigger
Randomisation triggers for stations.
@ SRT_CARGO_TAKEN
Trigger station when cargo is completely taken.
StationClassID
Functions to handle the town part of NewGRF towns.
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:297
@ RTSG_GROUND
Main group of ground images.
Definition rail.h:42
RailTrackOffset
Offsets for sprites within an overlay/underlay set.
Definition rail.h:60
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:27
Base class for roadstops.
A number of safeguards to prevent using unsafe methods.
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:59
void DrawRailTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t total_offset, uint32_t newgrf_offset, PaletteID default_palette)
Draw tile sprite sequence in GUI with railroad specifics.
Definition sprite.h:99
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_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
Definition sprites.h:1545
Base classes/functions for stations.
CargoTypes GetEmptyMask(const Station *st)
Get a mask of the cargo types that are empty at the station.
const DrawTileSprites * GetStationTileLayout(StationType st, uint8_t gfx)
Get station tile layout for a station type and its station gfx.
CargoTypes GetAcceptanceMask(const Station *st)
Get a mask of the cargo types that the station accepts.
bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset)
Check whether a sprite is a track sprite, which can be replaced by a non-track ground sprite and a ra...
StationGfx GetStationGfx(Tile t)
Get the station graphics of this tile.
Definition station_map.h:68
bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile)
Check if a tile is a valid continuation to a railstation tile.
uint8_t GetStationTileRandomBits(Tile t)
Get the random bits of a station tile.
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
bool HasStationTileRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
uint GetCustomStationSpecIndex(Tile t)
Get the custom station spec for this tile.
void SetStationTileRandomBits(Tile t, uint8_t random_bits)
Set the random bits for a station tile.
Axis GetRailStationAxis(Tile t)
Get the rail direction of a rail station.
bool IsCustomStationSpecIndex(Tile t)
Is there a custom rail station spec on this tile?
bool HasStationRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
@ HVOT_WAYPOINT
Station is a waypoint (NewGRF only!)
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
TTDPAirportType ttd_airport_type
ttdpatch airport type (Small/Large/Helipad/Oilrig)
uint64_t flags
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
const AirportSpec * GetSpec() const
Get the AirportSpec that from the airport type of this airport.
Helper class for a unified approach to NewGRF animation.
static void AnimateTile(const StationSpec *spec, BaseStation *obj, TileIndex tile, bool random_animation, int extra_data=0)
Animate a single tile.
static void ChangeAnimationFrame(CallbackID cb, const StationSpec *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.
StringID string_id
Default name (town area) of station.
std::vector< SpecMapping< StationSpec > > speclist
List of rail station specs of this station.
uint8_t cached_anim_triggers
NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
TileArea train_station
Tile area the train 'station' part covers.
Owner owner
The owner of this station.
virtual void GetTileArea(TileArea *ta, StationType type) const =0
Get the tile area for a given station type.
Town * town
The town this station is associated with.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
virtual bool TileBelongsToRailStation(TileIndex tile) const =0
Check whether a specific tile belongs to this station.
uint16_t random_bits
Random bits assigned to this station.
uint8_t waiting_triggers
Waiting triggers (NewGRF) for this station.
TimerGameCalendar::Date build_date
Date of construction.
CargoTypes cached_cargo_triggers
NOSAVE: Combined cargo trigger bitmask.
Specification of a cargo type.
Definition cargotype.h:77
static IterateWrapper Iterate(size_t from=0)
Returns an iterable ensemble of all valid CargoSpec.
Definition cargotype.h:196
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:58
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition sprite.h:60
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 (CargoType -> local ID)
Definition newgrf.h:131
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Stores station stats for a single cargo.
bool HasRating() const
Does this cargo have a rating at this station?
uint8_t last_speed
Maximum speed (up to 255) of the last vehicle that tried to load this cargo.
uint8_t last_age
Age in years (up to 255) of the last vehicle that tried to load this cargo.
uint8_t time_since_pickup
Number of rating-intervals (up to 255) since the last vehicle tried to load this cargo.
debug_inline const GoodsEntryData & GetData() const
Get optional cargo packet/flow data.
bool HasVehicleEverTriedLoading() const
Reports whether a vehicle has ever tried to load the cargo at this station.
uint8_t rating
Station rating for this cargo.
uint8_t status
Status of this cargo, see GoodsEntryStatus.
@ GES_ACCEPTANCE
Set when the station accepts the cargo currently for final deliveries.
@ GES_LAST_MONTH
Set when cargo was delivered for final delivery last month.
@ GES_CURRENT_MONTH
Set when cargo was delivered for final delivery this month.
@ GES_EVER_ACCEPTED
Set when a vehicle ever delivered cargo to the station for final delivery.
@ GES_ACCEPTED_BIGTICK
Set when cargo was delivered for final delivery during the current STATION_ACCEPTANCE_TICKS interval.
debug_inline bool HasData() const
Test if this goods entry has optional cargo packet/flow data.
NewGRF supplied spritelayout.
uint32_t PrepareLayout(uint32_t orig_offset, uint32_t newgrf_ground_offset, uint32_t newgrf_offset, uint constr_stage, bool separate_ground) const
Prepares a sprite layout before resolving action-1-2-3 chains.
void ProcessRegisters(uint8_t resolved_var10, uint32_t resolved_sprite, bool separate_ground) const
Evaluates the register modifiers and integrates them into the preprocessed sprite layout.
bool NeedsPreprocessing() const
Tests whether this spritelayout needs preprocessing by PrepareLayout() and ProcessRegisters(),...
const DrawTileSeqStruct * GetLayout(PalSpriteID *ground) const
Returns the result spritelayout after preprocessing.
Represents the covered area of e.g.
uint16_t w
The width of the area.
TileIndex tile
The base tile of the area.
uint16_t h
The height of the area.
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
std::vector< const SpriteGroup * > loaded
List of loaded groups (can be SpriteIDs or Callback results)
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.
uint8_t status
Current status of the Stop,.
ResolverObject & ro
Surrounding resolver object.
Iterable ensemble of each set bit in a value.
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.
Helper class for animation control.
Station resolver.
StationScopeResolver station_scope
The station scope resolver.
uint32_t GetDebugID() const override
Get an identifier for the item being resolved.
TownScopeResolver * GetTown()
Get the town scope associated with a station, if it exists.
std::optional< TownScopeResolver > town_scope
The town scope resolver (created on the first call).
StationResolverObject(const StationSpec *statspec, BaseStation *st, TileIndex tile, CallbackID callback=CBID_NO_CALLBACK, uint32_t callback_param1=0, uint32_t callback_param2=0)
Resolver for stations.
const SpriteGroup * ResolveReal(const RealSpriteGroup *group) const override
Get the real sprites of the grf.
GrfSpecFeature GetFeature() const override
Get the feature number being resolved for.
CargoType cargo_type
Type of cargo of the station.
struct BaseStation * st
Instance of the station.
uint32_t GetTriggers() const override
Get the triggers.
uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override
Get a variable value.
uint32_t GetRandomBits() const override
Get a few random bits.
const struct StationSpec * statspec
Station (type) specification.
Axis axis
Station axis, used only for the slope check callback.
TileIndex tile
Tile of the station.
Station specification.
uint16_t cargo_threshold
Cargo threshold for choosing between little and lots of cargo.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
CargoTypes cargo_triggers
Bitmask of cargo types which cause trigger re-randomizing.
std::vector< NewGRFSpriteLayout > renderdata
Number of tile layouts.
StationCallbackMasks callback_mask
Bitmask of station callbacks that have to be called.
StationSpecFlags flags
Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size.
Station data structure.
RoadStop * bus_stops
All the road stops.
GoodsEntry goods[NUM_CARGO]
Goods at this station.
bool TileBelongsToRailStation(TileIndex tile) const override
Check whether a specific tile belongs to this station.
Airport airport
Tile area the airport covers.
RoadStop * truck_stops
All the truck stops.
Scope resolver for a town.
Definition newgrf_town.h:22
Town data structure.
Definition town.h:52
uint32_t GetNewGRFVariable(const struct ResolverObject &object, uint8_t variable, uint8_t parameter, bool &available) const override
Helper function to get a NewGRF variable that isn't implemented by the base class.
uint8_t GetAnimationFrame(Tile t)
Get the current animation frame.
Definition tile_map.h:250
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
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
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
Definition of the game-calendar-timer.
Base of the town class.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:573
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition track_func.h:363
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
@ TRACK_BIT_NONE
No track.
Definition track_type.h:36
@ TRANSPORT_RAIL
Transport by train.
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
Base of waypoints.