OpenTTD Source: src/newgrf_roadtype.cpp Source File

OpenTTD Source 15.0-RC2

newgrf_roadtype.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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "core/container_func.hpp"
12#include "debug.h"
13#include "newgrf_roadtype.h"
14#include "newgrf_railtype.h"
15#include "timer/timer_game_calendar.h"
16#include "depot_base.h"
17#include "town.h"
18#include "tunnelbridge_map.h"
19
20#include "safeguards.h"
21
34uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile)
35{
36 uint8_t road = 0xFF;
37 uint8_t tram = 0xFF;
38 if (MayHaveRoad(tile)) {
39 if (auto tt = GetRoadTypeRoad(tile); tt != INVALID_ROADTYPE) {
40 road = GetReverseRoadTypeTranslation(tt, grffile);
41 if (road == 0xFF) road = 0xFE;
42 }
43 if (auto tt = GetRoadTypeTram(tile); tt != INVALID_ROADTYPE) {
44 tram = GetReverseRoadTypeTranslation(tt, grffile);
45 if (tram == 0xFF) tram = 0xFE;
46 }
47 }
48 uint8_t rail = 0xFF;
49 if (auto tt = GetTileRailType(tile); tt != INVALID_RAILTYPE) {
50 rail = GetReverseRailTypeTranslation(tt, grffile);
51 if (rail == 0xFF) rail = 0xFE;
52 }
53 return road | tram << 8 | rail << 16;
54}
55
56/* virtual */ uint32_t RoadTypeScopeResolver::GetRandomBits() const
57{
58 uint tmp = CountBits(this->tile.base() + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE);
59 return GB(tmp, 0, 2);
60}
61
62/* virtual */ uint32_t RoadTypeScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
63{
64 if (this->tile == INVALID_TILE) {
65 switch (variable) {
66 case 0x40: return 0;
67 case 0x41: return 0;
68 case 0x42: return 0;
69 case 0x43: return TimerGameCalendar::date.base();
70 case 0x44: return to_underlying(HouseZone::TownEdge);
71 case 0x45: {
72 RoadType rt = this->rti->Index();
73 uint8_t local = GetReverseRoadTypeTranslation(rt, this->ro.grffile);
74 if (local == 0xFF) local = 0xFE;
75 if (RoadTypeIsRoad(rt)) {
76 return 0xFFFF00 | local;
77 } else {
78 return 0xFF00FF | local << 8;
79 }
80 }
81 }
82 }
83
84 switch (variable) {
85 case 0x40: return GetTerrainType(this->tile, this->context);
86 case 0x41: return 0;
87 case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
88 case 0x43:
89 if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
90 return TimerGameCalendar::date.base();
91 case 0x44: {
92 const Town *t = nullptr;
93 if (IsRoadDepotTile(this->tile)) {
94 t = Depot::GetByTile(this->tile)->town;
95 } else {
96 t = ClosestTownFromTile(this->tile, UINT_MAX);
97 }
98 return to_underlying(t != nullptr ? GetTownRadiusGroup(t, this->tile) : HouseZone::TownEdge);
99 }
100 case 0x45:
101 return GetTrackTypes(this->tile, ro.grffile);
102 }
103
104 Debug(grf, 1, "Unhandled road type tile variable 0x{:X}", variable);
105
106 available = false;
107 return UINT_MAX;
108}
109
110 GrfSpecFeature RoadTypeResolverObject::GetFeature() const
111{
112 RoadType rt = GetRoadTypeByLabel(this->roadtype_scope.rti->label, false);
113 switch (GetRoadTramType(rt)) {
114 case RTT_ROAD: return GSF_ROADTYPES;
115 case RTT_TRAM: return GSF_TRAMTYPES;
116 default: return GSF_INVALID;
117 }
118}
119
120uint32_t RoadTypeResolverObject::GetDebugID() const
121{
122 return this->roadtype_scope.rti->label;
123}
124
134RoadTypeResolverObject::RoadTypeResolverObject(const RoadTypeInfo *rti, TileIndex tile, TileContext context, RoadTypeSpriteGroup rtsg, uint32_t param1, uint32_t param2)
135 : ResolverObject(rti != nullptr ? rti->grffile[rtsg] : nullptr, CBID_NO_CALLBACK, param1, param2), roadtype_scope(*this, rti, tile, context)
136{
137 this->root_spritegroup = rti != nullptr ? rti->group[rtsg] : nullptr;
138}
139
149 SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
150{
151 assert(rtsg < ROTSG_END);
152
153 if (rti->group[rtsg] == nullptr) return 0;
154
155 RoadTypeResolverObject object(rti, tile, context, rtsg);
156 const auto *group = object.Resolve<ResultSpriteGroup>();
157 if (group == nullptr || group->num_sprites == 0) return 0;
158
159 if (num_results) *num_results = group->num_sprites;
160
161 return group->sprite;
162}
163
171 RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8_t tracktype, const GRFFile *grffile)
172{
173 /* Because OpenTTD mixes RoadTypes and TramTypes into the same type,
174 * the mapping of the original road- and tramtypes does not match the default GRF-local mapping.
175 * So, this function cannot provide any similar behavior to GetCargoTranslation() and GetRailTypeTranslation()
176 * when the GRF defines no translation table.
177 * But since there is only one default road/tram-type, this makes little sense anyway.
178 * So for GRF without translation table, we always return INVALID_ROADTYPE.
179 */
180
181 if (grffile == nullptr) return INVALID_ROADTYPE;
182
183 const auto &list = rtt == RTT_TRAM ? grffile->tramtype_list : grffile->roadtype_list;
184 if (tracktype >= list.size()) return INVALID_ROADTYPE;
185
186 /* Look up roadtype including alternate labels. */
187 RoadType result = GetRoadTypeByLabel(list[tracktype]);
188
189 /* Check whether the result is actually the wanted road/tram-type */
190 if (result != INVALID_ROADTYPE && GetRoadTramType(result) != rtt) return INVALID_ROADTYPE;
191
192 return result;
193}
194
201uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
202{
203 /* No road type table present, return road type as-is */
204 if (grffile == nullptr) return roadtype;
205
206 const std::vector<RoadTypeLabel> *list = RoadTypeIsRoad(roadtype) ? &grffile->roadtype_list : &grffile->tramtype_list;
207 if (list->empty()) return roadtype;
208
209 /* Look for a matching road type label in the table */
210 RoadTypeLabel label = GetRoadTypeInfo(roadtype)->label;
211
212 int index = find_index(*list, label);
213 if (index >= 0) return index;
214
215 /* If not found, return as invalid */
216 return 0xFF;
217}
218
219std::vector<LabelObject<RoadTypeLabel>> _roadtype_list;
220
225 void ConvertRoadTypes()
226{
227 std::vector<RoadType> roadtype_conversion_map;
228 bool needs_conversion = false;
229 for (auto it = std::begin(_roadtype_list); it != std::end(_roadtype_list); ++it) {
230 RoadType rt = GetRoadTypeByLabel(it->label);
231 if (rt == INVALID_ROADTYPE || GetRoadTramType(rt) != it->subtype) {
232 rt = it->subtype ? ROADTYPE_TRAM : ROADTYPE_ROAD;
233 }
234
235 roadtype_conversion_map.push_back(rt);
236
237 /* Conversion is needed if the road type is in a different position than the list. */
238 if (it->label != 0 && rt != std::distance(std::begin(_roadtype_list), it)) needs_conversion = true;
239 }
240 if (!needs_conversion) return;
241
242 for (TileIndex t : Map::Iterate()) {
243 switch (GetTileType(t)) {
244 case MP_ROAD:
245 if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
246 if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
247 break;
248
249 case MP_STATION:
250 if (IsAnyRoadStop(t)) {
251 if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
252 if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
253 }
254 break;
255
256 case MP_TUNNELBRIDGE:
257 if (GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD) {
258 if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]);
259 if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]);
260 }
261 break;
262
263 default:
264 break;
265 }
266 }
267}
268
270 void SetCurrentRoadTypeLabelList()
271{
272 _roadtype_list.clear();
273 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
274 _roadtype_list.emplace_back(GetRoadTypeInfo(rt)->label, GetRoadTramType(rt));
275 }
276}
277
278void ClearRoadTypeLabelList()
279{
280 _roadtype_list.clear();
281}
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition bitmath_func.hpp:238
RoadTypeInfo
Definition road.h:52
RoadTypeInfo::label
RoadTypeLabel label
Unique 32 bit road type identifier.
Definition road.h:121
RoadTypeInfo::Index
RoadType Index() const
Get the RoadType for this RoadTypeInfo.
Definition road.cpp:30
RoadTypeInfo::group
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
Definition road.h:166
TimerGameCalendar::date
static Date date
Current date in days (day counter).
Definition timer_game_calendar.h:33
container_func.hpp
Some simple functions to help with accessing containers.
find_index
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_...
Definition container_func.hpp:41
debug.h
Functions related to debugging.
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
depot_base.h
Base for all depots (except hangars)
to_underlying
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
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:437
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:427
GrfSpecFeature
GrfSpecFeature
Definition newgrf.h:68
GSF_INVALID
@ GSF_INVALID
An invalid spec feature.
Definition newgrf.h:99
CBID_NO_CALLBACK
@ CBID_NO_CALLBACK
Set when using the callback resolve system, but not to resolve a callback.
Definition newgrf_callbacks.h:24
GetTerrainType
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 ...
Definition newgrf_commons.cpp:336
TileContext
TileContext
Context for tile accesses.
Definition newgrf_commons.h:24
GetReverseRailTypeTranslation
uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile)
Perform a reverse railtype lookup to get the GRF internal ID.
Definition newgrf_railtype.cpp:173
newgrf_railtype.h
NewGRF handling of rail types.
SetCurrentRoadTypeLabelList
void SetCurrentRoadTypeLabelList()
Populate road type label list with current values.
Definition newgrf_roadtype.cpp:270
GetCustomRoadSprite
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
Definition newgrf_roadtype.cpp:149
ConvertRoadTypes
void ConvertRoadTypes()
Test if any saved road type labels are different to the currently loaded road types.
Definition newgrf_roadtype.cpp:225
GetReverseRoadTypeTranslation
uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
Perform a reverse roadtype lookup to get the GRF internal ID.
Definition newgrf_roadtype.cpp:201
GetTrackTypes
uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile)
Variable 0x45 of road-/tram-/rail-types to query track types on a tile.
Definition newgrf_roadtype.cpp:34
GetRoadTypeTranslation
RoadType GetRoadTypeTranslation(RoadTramType rtt, uint8_t tracktype, const GRFFile *grffile)
Translate an index to the GRF-local road/tramtype-translation table into a RoadType.
Definition newgrf_roadtype.cpp:171
newgrf_roadtype.h
NewGRF handling of road types.
GetReverseRoadTypeTranslation
uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
Perform a reverse roadtype lookup to get the GRF internal ID.
Definition newgrf_roadtype.cpp:201
GetTrackTypes
uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile)
Variable 0x45 of road-/tram-/rail-types to query track types on a tile.
Definition newgrf_roadtype.cpp:34
GetTileRailType
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition rail.cpp:37
INVALID_RAILTYPE
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
GetRoadTypeByLabel
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
Get the road type for a given label.
Definition road.cpp:265
GetRoadTypeInfo
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:215
RoadTypeSpriteGroup
RoadTypeSpriteGroup
Sprite groups for a roadtype.
Definition road.h:36
MayHaveRoad
bool MayHaveRoad(Tile t)
Test whether a tile can have road/tram types.
Definition road_map.cpp:21
SetRoadTypeRoad
void SetRoadTypeRoad(Tile t, RoadType rt)
Set the road road type of a tile.
Definition road_map.h:564
SetRoadTypeTram
void SetRoadTypeTram(Tile t, RoadType rt)
Set the tram road type of a tile.
Definition road_map.h:576
IsLevelCrossingTile
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition road_map.h:79
IsRoadDepotTile
static bool IsRoadDepotTile(Tile t)
Return whether a tile is a road depot tile.
Definition road_map.h:100
IsCrossingBarred
bool IsCrossingBarred(Tile t)
Check if the level crossing is barred.
Definition road_map.h:400
RoadTramType
RoadTramType
The different types of road type.
Definition road_type.h:37
RTT_ROAD
@ RTT_ROAD
Road road type.
Definition road_type.h:38
RTT_TRAM
@ RTT_TRAM
Tram road type.
Definition road_type.h:39
RoadType
RoadType
The different roadtypes we support.
Definition road_type.h:23
INVALID_ROADTYPE
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
ROADTYPE_TRAM
@ ROADTYPE_TRAM
Trams.
Definition road_type.h:26
ROADTYPE_ROAD
@ ROADTYPE_ROAD
Basic road type.
Definition road_type.h:25
ROADTYPE_END
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:27
ROADTYPE_BEGIN
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:24
safeguards.h
A number of safeguards to prevent using unsafe methods.
IsAnyRoadStop
bool IsAnyRoadStop(Tile t)
Is the station at t a road station?
Definition station_map.h:245
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
Depot::build_date
TimerGameCalendar::Date build_date
Date of construction.
Definition depot_base.h:26
GRFFile
Dynamic data of a loaded NewGRF.
Definition newgrf.h:114
GRFFile::roadtype_list
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
Definition newgrf.h:144
GRFFile::tramtype_list
std::vector< RoadTypeLabel > tramtype_list
Roadtype translation table (tram)
Definition newgrf.h:147
Map::Iterate
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:375
ResolverObject
Interface for SpriteGroup-s to access the gamestate.
Definition newgrf_spritegroup.h:288
ResolverObject::grffile
const GRFFile * grffile
GRFFile the resolved SpriteGroup belongs to.
Definition newgrf_spritegroup.h:352
ResolverObject::root_spritegroup
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
Definition newgrf_spritegroup.h:353
ResultSpriteGroup
Definition newgrf_spritegroup.h:217
RoadTypeResolverObject
Resolver object for road types.
Definition newgrf_roadtype.h:40
RoadTypeResolverObject::roadtype_scope
RoadTypeScopeResolver roadtype_scope
Resolver for the roadtype scope.
Definition newgrf_roadtype.h:41
RoadTypeResolverObject::RoadTypeResolverObject
RoadTypeResolverObject(const RoadTypeInfo *rti, TileIndex tile, TileContext context, RoadTypeSpriteGroup rtsg, uint32_t param1=0, uint32_t param2=0)
Resolver object for road types.
Definition newgrf_roadtype.cpp:134
RoadTypeResolverObject::GetDebugID
uint32_t GetDebugID() const override
Get an identifier for the item being resolved.
Definition newgrf_roadtype.cpp:120
RoadTypeResolverObject::GetFeature
GrfSpecFeature GetFeature() const override
Get the feature number being resolved for.
Definition newgrf_roadtype.cpp:110
RoadTypeScopeResolver::context
TileContext context
Are we resolving sprites for the upper halftile, or on a bridge?
Definition newgrf_roadtype.h:20
RoadTypeScopeResolver::GetVariable
uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override
Get a variable value.
Definition newgrf_roadtype.cpp:62
RoadTypeScopeResolver::GetRandomBits
uint32_t GetRandomBits() const override
Get a few random bits.
Definition newgrf_roadtype.cpp:56
RoadTypeScopeResolver::tile
TileIndex tile
Tracktile. For track on a bridge this is the southern bridgehead.
Definition newgrf_roadtype.h:19
ScopeResolver::ro
ResolverObject & ro
Surrounding resolver object.
Definition newgrf_spritegroup.h:270
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
Town
Town data structure.
Definition town.h:63
GetTileType
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
MP_ROAD
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
MP_STATION
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
MP_TUNNELBRIDGE
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
timer_game_calendar.h
Definition of the game-calendar-timer.
town.h
Base of the town class.
ClosestTownFromTile
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
Definition town_cmd.cpp:3952
GetTownRadiusGroup
HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile)
Returns the bit corresponding to the town zone of the specified tile.
Definition town_cmd.cpp:2507
TRANSPORT_ROAD
@ TRANSPORT_ROAD
Transport by road vehicle.
Definition transport_type.h:26
tunnelbridge_map.h
Functions that have tunnels and bridges in common.
GetTunnelBridgeTransportType
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
Definition tunnelbridge_map.h:39