OpenTTD Source 20250528-master-g3aca5d62a8
newgrf_railtype.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"
12#include "debug.h"
13#include "newgrf_railtype.h"
14#include "newgrf_roadtype.h"
16#include "depot_base.h"
17#include "town.h"
18#include "tunnelbridge_map.h"
19
20#include "safeguards.h"
21
22/* virtual */ uint32_t RailTypeScopeResolver::GetRandomBits() const
23{
24 uint tmp = CountBits(this->tile.base() + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE);
25 return GB(tmp, 0, 2);
26}
27
28/* virtual */ uint32_t RailTypeScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
29{
30 if (this->tile == INVALID_TILE) {
31 switch (variable) {
32 case 0x40: return 0;
33 case 0x41: return 0;
34 case 0x42: return 0;
35 case 0x43: return TimerGameCalendar::date.base();
36 case 0x44: return to_underlying(HouseZone::TownEdge);
37 case 0x45: {
38 auto rt = GetRailTypeInfoIndex(this->rti);
39 uint8_t local = GetReverseRailTypeTranslation(rt, this->ro.grffile);
40 if (local == 0xFF) local = 0xFE;
41 return 0xFFFF | local << 16;
42 }
43 }
44 }
45
46 switch (variable) {
47 case 0x40: return GetTerrainType(this->tile, this->context);
48 case 0x41: return 0;
49 case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
50 case 0x43:
51 if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
52 return TimerGameCalendar::date.base();
53 case 0x44: {
54 const Town *t = nullptr;
55 if (IsRailDepotTile(this->tile)) {
56 t = Depot::GetByTile(this->tile)->town;
57 } else if (IsLevelCrossingTile(this->tile)) {
58 t = ClosestTownFromTile(this->tile, UINT_MAX);
59 }
60 return to_underlying(t != nullptr ? GetTownRadiusGroup(t, this->tile) : HouseZone::TownEdge);
61 }
62 case 0x45:
63 return GetTrackTypes(this->tile, ro.grffile);
64 }
65
66 Debug(grf, 1, "Unhandled rail type tile variable 0x{:X}", variable);
67
68 available = false;
69 return UINT_MAX;
70}
71
73{
74 return GSF_RAILTYPES;
75}
76
78{
79 return this->railtype_scope.rti->label;
80}
81
91RailTypeResolverObject::RailTypeResolverObject(const RailTypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32_t param1, uint32_t param2)
92 : ResolverObject(rti != nullptr ? rti->grffile[rtsg] : nullptr, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, rti, tile, context)
93{
94 this->root_spritegroup = rti != nullptr ? rti->group[rtsg] : nullptr;
95}
96
106SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
107{
108 assert(rtsg < RTSG_END);
109
110 if (rti->group[rtsg] == nullptr) return 0;
111
112 RailTypeResolverObject object(rti, tile, context, rtsg);
113 const auto *group = object.Resolve<ResultSpriteGroup>();
114 if (group == nullptr || group->num_sprites == 0) return 0;
115
116 if (num_results) *num_results = group->num_sprites;
117
118 return group->sprite;
119}
120
132{
133 if (rti->group[RTSG_SIGNALS] == nullptr) return 0;
134
135 uint32_t param1 = gui ? 0x10 : 0x00;
136 uint32_t param2 = (type << 16) | (var << 8) | state;
137 RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2);
138
139 const auto *group = object.Resolve<ResultSpriteGroup>();
140 if (group == nullptr || group->num_sprites == 0) return 0;
141
142 return group->sprite;
143}
144
151RailType GetRailTypeTranslation(uint8_t railtype, const GRFFile *grffile)
152{
153 if (grffile == nullptr || grffile->railtype_list.empty()) {
154 /* No railtype table present. Return railtype as-is (if valid), so it works for original railtypes. */
155 if (railtype >= RAILTYPE_END || GetRailTypeInfo(static_cast<RailType>(railtype))->label == 0) return INVALID_RAILTYPE;
156
157 return static_cast<RailType>(railtype);
158 } else {
159 /* Railtype table present, but invalid index, return invalid type. */
160 if (railtype >= grffile->railtype_list.size()) return INVALID_RAILTYPE;
161
162 /* Look up railtype including alternate labels. */
163 return GetRailTypeByLabel(grffile->railtype_list[railtype]);
164 }
165}
166
173uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
174{
175 /* No rail type table present, return rail type as-is */
176 if (grffile == nullptr || grffile->railtype_list.empty()) return railtype;
177
178 /* Look for a matching rail type label in the table */
179 RailTypeLabel label = GetRailTypeInfo(railtype)->label;
180
181 int idx = find_index(grffile->railtype_list, label);
182 if (idx >= 0) return idx;
183
184 /* If not found, return as invalid */
185 return 0xFF;
186}
187
188std::vector<LabelObject<RailTypeLabel>> _railtype_list;
189
195{
196 std::vector<RailType> railtype_conversion_map;
197 bool needs_conversion = false;
198
199 for (auto it = std::begin(_railtype_list); it != std::end(_railtype_list); ++it) {
200 RailType rt = GetRailTypeByLabel(it->label);
201 if (rt == INVALID_RAILTYPE) {
202 rt = RAILTYPE_RAIL;
203 }
204
205 railtype_conversion_map.push_back(rt);
206
207 /* Conversion is needed if the rail type is in a different position than the list. */
208 if (it->label != 0 && rt != std::distance(std::begin(_railtype_list), it)) needs_conversion = true;
209 }
210
211 if (!needs_conversion) return;
212
213 for (const auto t : Map::Iterate()) {
214 switch (GetTileType(t)) {
215 case MP_RAILWAY:
216 SetRailType(t, railtype_conversion_map[GetRailType(t)]);
217 break;
218
219 case MP_ROAD:
220 if (IsLevelCrossing(t)) {
221 SetRailType(t, railtype_conversion_map[GetRailType(t)]);
222 }
223 break;
224
225 case MP_STATION:
226 if (HasStationRail(t)) {
227 SetRailType(t, railtype_conversion_map[GetRailType(t)]);
228 }
229 break;
230
231 case MP_TUNNELBRIDGE:
233 SetRailType(t, railtype_conversion_map[GetRailType(t)]);
234 }
235 break;
236
237 default:
238 break;
239 }
240 }
241}
242
245{
246 _railtype_list.clear();
247
248 for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
249 _railtype_list.emplace_back(GetRailTypeInfo(rt)->label, 0);
250 }
251}
252
253void ClearRailTypeLabelList()
254{
255 _railtype_list.clear();
256}
constexpr uint CountBits(T value)
Counts the number of set bits 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.
This struct contains all the info that is needed to draw and construct tracks.
Definition rail.h:118
RailTypeLabel label
Unique 32 bit rail type identifier.
Definition rail.h:227
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
Definition rail.h:272
static Date date
Current date in days (day counter).
Some simple functions to help with accessing containers.
int find_index(Container const &container, typename Container::const_reference item)
Helper function to get the index of an item Consider using std::set, std::unordered_set or std::flat_...
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Base for all depots (except hangars)
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:17
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:424
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:414
GrfSpecFeature
Definition newgrf.h:69
@ CBID_NO_CALLBACK
Set when using the callback resolve system, but not to resolve a callback.
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 ...
TileContext
Context for tile accesses.
@ TCX_NORMAL
Nothing special.
SpriteID GetCustomSignalSprite(const RailTypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui)
Get the sprite to draw for a given signal.
void ConvertRailTypes()
Test if any saved rail type labels are different to the currently loaded rail types.
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.
void SetCurrentRailTypeLabelList()
Populate railtype label list with current values.
RailType GetRailTypeTranslation(uint8_t railtype, const GRFFile *grffile)
Translate an index to the GRF-local railtype-translation table into a RailType.
NewGRF handling of rail types.
uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
Perform a reverse railtype lookup to get the GRF internal ID.
uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile)
Variable 0x45 of road-/tram-/rail-types to query track types on a tile.
NewGRF handling of road types.
RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
Get the rail type for a given label.
Definition rail.cpp:313
RailType GetRailTypeInfoIndex(const RailTypeInfo *rti)
Returns the railtype for a Railtype information.
Definition rail.h:312
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
RailTypeSpriteGroup
Sprite groups for a railtype.
Definition rail.h:40
@ RTSG_SIGNALS
Signal images.
Definition rail.h:52
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
static debug_inline bool IsRailDepotTile(Tile t)
Is this tile rail tile and a rail depot?
Definition rail_map.h:105
void SetRailType(Tile t, RailType r)
Sets the rail type of the given tile.
Definition rail_map.h:125
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
@ RAILTYPE_BEGIN
Used for iterations.
Definition rail_type.h:26
@ RAILTYPE_END
Used for iterations.
Definition rail_type.h:31
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
@ RAILTYPE_RAIL
Standard non-electric rails.
Definition rail_type.h:27
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:79
bool IsCrossingBarred(Tile t)
Check if the level crossing is barred.
Definition road_map.h:400
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:69
A number of safeguards to prevent using unsafe methods.
SignalType
Type of signal, i.e.
Definition signal_type.h:23
SignalState
These are states in which a signal can be.
Definition signal_type.h:42
SignalVariant
Variant of the signal, i.e.
Definition signal_type.h:16
bool HasStationRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition of base types and functions in a cross-platform compatible way.
TimerGameCalendar::Date build_date
Date of construction.
Definition depot_base.h:26
Dynamic data of a loaded NewGRF.
Definition newgrf.h:115
std::vector< RailTypeLabel > railtype_list
Railtype translation table.
Definition newgrf.h:142
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:362
Resolver object for rail types.
GrfSpecFeature GetFeature() const override
Get the feature number being resolved for.
RailTypeResolverObject(const RailTypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32_t param1=0, uint32_t param2=0)
Resolver object for rail types.
uint32_t GetDebugID() const override
Get an identifier for the item being resolved.
RailTypeScopeResolver railtype_scope
Resolver for the railtype scope.
uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override
Get a variable value.
TileContext context
Are we resolving sprites for the upper halftile, or on a bridge?
uint32_t GetRandomBits() const override
Get a few random bits.
TileIndex tile
Tracktile. For track on a bridge this is the southern bridgehead.
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.
ResolverObject & ro
Surrounding resolver object.
Town data structure.
Definition town.h:52
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
static const uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ 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
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
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.
HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile)
Returns the bit corresponding to the town zone of the specified tile.
@ TRANSPORT_RAIL
Transport by train.
Functions that have tunnels and bridges in common.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...