diff --git a/docs/newgrf-additions-nml.html b/docs/newgrf-additions-nml.html
index 7f9dc5cd6d..9818ff6ba9 100644
--- a/docs/newgrf-additions-nml.html
+++ b/docs/newgrf-additions-nml.html
@@ -216,6 +216,17 @@
If there is no bridge above, the value is 0xFF.
+
adjacent_crossing | bitmask(RAILTYPE_ADJACENT_CROSSING_XXX, ...) |
+
+ Adjacent level crossing information:
+
+ - SOUTH
+ - This level crossing tile is part of a continuous adjacent crossing with the tile to the south (SW or SE)
+ - NORTH
+ - This level crossing tile is part of a continuous adjacent crossing with the tile to the north (NW or NE)
+
+ |
+
diff --git a/docs/newgrf-additions.html b/docs/newgrf-additions.html
index b888fd6a6f..a58adc28ef 100644
--- a/docs/newgrf-additions.html
+++ b/docs/newgrf-additions.html
@@ -872,6 +872,16 @@
This is indicated by the feature name: varaction2_railtype_signal_vertical_clearance, version 1
+ Adjacent level crossing information (mappable variable: railtype_adjacent_crossing)
+
+
+ Bit | Meaning |
+ 0 | This level crossing tile is part of a continuous adjacent crossing with the tile to the south (SW or SE) |
+ 1 | This level crossing tile is part of a continuous adjacent crossing with the tile to the north (NW or NE) |
+
+ The value is 0 for non level crossing tiles.
+
+ This is indicated by the feature name: varaction2_railtype_adjacent_crossing, version 1
Tile slope after foundation applied (mappable variable: object_foundation_tile_slope)
diff --git a/src/newgrf_extension.cpp b/src/newgrf_extension.cpp
index f8d9ba72c9..6c19e29487 100644
--- a/src/newgrf_extension.cpp
+++ b/src/newgrf_extension.cpp
@@ -44,6 +44,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("varaction2_railtype_signal_context", 1),
GRFFeatureInfo("varaction2_railtype_signal_side", 1),
GRFFeatureInfo("varaction2_railtype_signal_vertical_clearance", 1),
+ GRFFeatureInfo("varaction2_railtype_adjacent_crossing", 1),
GRFFeatureInfo("action0_global_extra_station_names", 2),
GRFFeatureInfo("action0_global_default_object_generate_amount", 1),
GRFFeatureInfo("action0_global_allow_rocks_in_desert", 1),
@@ -175,6 +176,7 @@ extern const GRFVariableMapDefinition _grf_action2_remappable_variables[] = {
GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_CONTEXT, "railtype_signal_context"),
GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_SIDE, "railtype_signal_side"),
GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE, "railtype_signal_vertical_clearance"),
+ GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_ADJACENT_CROSSING, "railtype_adjacent_crossing"),
GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_RESTRICTION_INFO, "signals_signal_restriction_info"),
GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_CONTEXT, "signals_signal_context"),
GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_STYLE, "signals_signal_style"),
diff --git a/src/newgrf_extension.h b/src/newgrf_extension.h
index 939beadd44..98016e23bf 100644
--- a/src/newgrf_extension.h
+++ b/src/newgrf_extension.h
@@ -86,6 +86,7 @@ enum Action2VariableRemapIds {
A2VRI_RAILTYPE_SIGNAL_CONTEXT,
A2VRI_RAILTYPE_SIGNAL_SIDE,
A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE,
+ A2VRI_RAILTYPE_ADJACENT_CROSSING,
A2VRI_SIGNALS_SIGNAL_RESTRICTION_INFO,
A2VRI_SIGNALS_SIGNAL_CONTEXT,
A2VRI_SIGNALS_SIGNAL_STYLE,
diff --git a/src/newgrf_optimiser.cpp b/src/newgrf_optimiser.cpp
index e9cfb4c525..59a9bb591a 100644
--- a/src/newgrf_optimiser.cpp
+++ b/src/newgrf_optimiser.cpp
@@ -108,6 +108,7 @@ static bool IsExpensiveRailtypeVariable(uint16 variable)
{
switch (variable) {
case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE:
+ case A2VRI_RAILTYPE_ADJACENT_CROSSING:
return true;
default:
diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp
index e31bc2b181..c319e97b59 100644
--- a/src/newgrf_railtype.cpp
+++ b/src/newgrf_railtype.cpp
@@ -17,6 +17,7 @@
#include "depot_base.h"
#include "town.h"
#include "signal_func.h"
+#include "road.h"
#include "safeguards.h"
@@ -39,6 +40,7 @@
case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context;
case A2VRI_RAILTYPE_SIGNAL_SIDE: return GetNewSignalsSideVariable();
case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE: return 0xFF;
+ case A2VRI_RAILTYPE_ADJACENT_CROSSING: return 0;
}
}
@@ -66,6 +68,31 @@
return GetNewSignalsSideVariable();
case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE:
return GetNewSignalsVerticalClearanceInfo(this->tile, this->z);
+ case A2VRI_RAILTYPE_ADJACENT_CROSSING: {
+ if (!IsLevelCrossingTile(this->tile) || !_settings_game.vehicle.adjacent_crossings) return 0;
+
+ auto is_usable_crossing = [&](TileIndex t) -> bool {
+ if (HasRoadTypeRoad(t) && !HasBit(_roadtypes_non_train_colliding, GetRoadTypeRoad(t))) return true;
+ if (HasRoadTypeTram(t) && !HasBit(_roadtypes_non_train_colliding, GetRoadTypeTram(t))) return true;
+ return false;
+ };
+ if (!is_usable_crossing(this->tile)) return 0;
+
+ const Axis axis = GetCrossingRoadAxis(this->tile);
+ const DiagDirection dir_s = AxisToDiagDir(axis);
+ const DiagDirection dir_n = ReverseDiagDir(dir_s);
+
+ uint32 result = 0;
+ auto test_dir = [&](DiagDirection dir, uint bit) {
+ const TileIndex t = TileAddByDiagDir(this->tile, dir);
+ if (t < MapSize() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == axis && is_usable_crossing(t)) {
+ SetBit(result, bit);
+ }
+ };
+ test_dir(dir_s, 0);
+ test_dir(dir_n, 1);
+ return result;
+ }
}
DEBUG(grf, 1, "Unhandled rail type tile variable 0x%X", variable);
diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h
index c5ecce0782..b63b2dd21c 100644
--- a/src/table/newgrf_debug_data.h
+++ b/src/table/newgrf_debug_data.h
@@ -1599,6 +1599,7 @@ static const NIVariable _niv_railtypes[] = {
NIV(0x42, "level crossing status"),
NIV(0x43, "construction date"),
NIV(0x44, "town zone"),
+ NIV(A2VRI_RAILTYPE_ADJACENT_CROSSING, "adjacent crossing"),
NIV_END()
};