mirror of https://github.com/OpenTTD/OpenTTD.git
Feature: Railtype flags to allow/disallow 90 degree curves. (#7352)
This commit is contained in:
parent
26b0615c47
commit
cc5f175615
|
@ -157,7 +157,7 @@ struct CFollowTrackT
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Allow90degTurns()) {
|
if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(m_old_tile), GetTileRailType(m_new_tile), !Allow90degTurns()))) {
|
||||||
m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(m_old_td);
|
m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(m_old_td);
|
||||||
if (m_new_td_bits == TRACKDIR_BIT_NONE) {
|
if (m_new_td_bits == TRACKDIR_BIT_NONE) {
|
||||||
m_err = EC_90DEG;
|
m_err = EC_90DEG;
|
||||||
|
|
|
@ -803,12 +803,13 @@ static bool CanEnterTile(TileIndex tile, DiagDirection dir, AyStarUserData *user
|
||||||
* One-way-roads are taken into account. Signals are not tested.
|
* One-way-roads are taken into account. Signals are not tested.
|
||||||
*
|
*
|
||||||
* @param dst_tile The tile of interest.
|
* @param dst_tile The tile of interest.
|
||||||
|
* @param src_tile The originating tile.
|
||||||
* @param src_trackdir The direction the vehicle is currently moving.
|
* @param src_trackdir The direction the vehicle is currently moving.
|
||||||
* @param type The transporttype of the vehicle.
|
* @param type The transporttype of the vehicle.
|
||||||
* @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
|
* @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
|
||||||
* @return The Trackdirs the vehicle can continue moving on.
|
* @return The Trackdirs the vehicle can continue moving on.
|
||||||
*/
|
*/
|
||||||
static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_trackdir, TransportType type, uint subtype)
|
static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, TileIndex src_tile, Trackdir src_trackdir, TransportType type, uint subtype)
|
||||||
{
|
{
|
||||||
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));
|
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));
|
||||||
|
|
||||||
|
@ -836,7 +837,9 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_tr
|
||||||
trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
|
trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
|
||||||
|
|
||||||
/* Filter out trackdirs that would make 90 deg turns for trains */
|
/* Filter out trackdirs that would make 90 deg turns for trains */
|
||||||
if (_settings_game.pf.forbid_90_deg && type == TRANSPORT_RAIL) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
|
if (type == TRANSPORT_RAIL && Rail90DegTurnDisallowed(GetTileRailType(src_tile), GetTileRailType(dst_tile))) {
|
||||||
|
trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
|
DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
|
||||||
|
|
||||||
|
@ -877,7 +880,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
||||||
if (CheckIgnoreFirstTile(¤t->path)) {
|
if (CheckIgnoreFirstTile(¤t->path)) {
|
||||||
/* Do not perform any checks that involve src_tile */
|
/* Do not perform any checks that involve src_tile */
|
||||||
dst_tile = src_tile + TileOffsByDiagDir(src_exitdir);
|
dst_tile = src_tile + TileOffsByDiagDir(src_exitdir);
|
||||||
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
|
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype);
|
||||||
} else if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) {
|
} else if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) {
|
||||||
/* We drive through the wormhole and arrive on the other side */
|
/* We drive through the wormhole and arrive on the other side */
|
||||||
dst_tile = GetOtherTunnelBridgeEnd(src_tile);
|
dst_tile = GetOtherTunnelBridgeEnd(src_tile);
|
||||||
|
@ -901,7 +904,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
||||||
src_trackdir = ReverseTrackdir(src_trackdir);
|
src_trackdir = ReverseTrackdir(src_trackdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
|
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype);
|
||||||
|
|
||||||
if (trackdirbits == TRACKDIR_BIT_NONE) {
|
if (trackdirbits == TRACKDIR_BIT_NONE) {
|
||||||
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
|
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
|
||||||
|
@ -910,7 +913,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
||||||
dst_tile = src_tile;
|
dst_tile = src_tile;
|
||||||
src_trackdir = ReverseTrackdir(src_trackdir);
|
src_trackdir = ReverseTrackdir(src_trackdir);
|
||||||
|
|
||||||
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype);
|
trackdirbits = GetDriveableTrackdirBits(dst_tile, src_tile, src_trackdir, type, subtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -400,7 +400,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
||||||
|
|
||||||
/* Check for reachable tracks. */
|
/* Check for reachable tracks. */
|
||||||
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||||
if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||||
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
|
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
|
||||||
|
|
||||||
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||||
|
@ -445,7 +445,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
||||||
|
|
||||||
/* Check for reachable tracks. */
|
/* Check for reachable tracks. */
|
||||||
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||||
if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||||
|
|
||||||
return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits));
|
return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits));
|
||||||
}
|
}
|
||||||
|
|
25
src/rail.h
25
src/rail.h
|
@ -21,6 +21,7 @@
|
||||||
#include "strings_type.h"
|
#include "strings_type.h"
|
||||||
#include "date_type.h"
|
#include "date_type.h"
|
||||||
#include "signal_type.h"
|
#include "signal_type.h"
|
||||||
|
#include "settings_type.h"
|
||||||
|
|
||||||
/** Railtype flags. */
|
/** Railtype flags. */
|
||||||
enum RailTypeFlags {
|
enum RailTypeFlags {
|
||||||
|
@ -28,12 +29,16 @@ enum RailTypeFlags {
|
||||||
RTF_NO_LEVEL_CROSSING = 1, ///< Bit number for disallowing level crossings.
|
RTF_NO_LEVEL_CROSSING = 1, ///< Bit number for disallowing level crossings.
|
||||||
RTF_HIDDEN = 2, ///< Bit number for hiding from selection.
|
RTF_HIDDEN = 2, ///< Bit number for hiding from selection.
|
||||||
RTF_NO_SPRITE_COMBINE = 3, ///< Bit number for using non-combined junctions.
|
RTF_NO_SPRITE_COMBINE = 3, ///< Bit number for using non-combined junctions.
|
||||||
|
RTF_ALLOW_90DEG = 4, ///< Bit number for always allowed 90 degree turns, regardless of setting.
|
||||||
|
RTF_DISALLOW_90DEG = 5, ///< Bit number for never allowed 90 degree turns, regardless of setting.
|
||||||
|
|
||||||
RTFB_NONE = 0, ///< All flags cleared.
|
RTFB_NONE = 0, ///< All flags cleared.
|
||||||
RTFB_CATENARY = 1 << RTF_CATENARY, ///< Value for drawing a catenary.
|
RTFB_CATENARY = 1 << RTF_CATENARY, ///< Value for drawing a catenary.
|
||||||
RTFB_NO_LEVEL_CROSSING = 1 << RTF_NO_LEVEL_CROSSING, ///< Value for disallowing level crossings.
|
RTFB_NO_LEVEL_CROSSING = 1 << RTF_NO_LEVEL_CROSSING, ///< Value for disallowing level crossings.
|
||||||
RTFB_HIDDEN = 1 << RTF_HIDDEN, ///< Value for hiding from selection.
|
RTFB_HIDDEN = 1 << RTF_HIDDEN, ///< Value for hiding from selection.
|
||||||
RTFB_NO_SPRITE_COMBINE = 1 << RTF_NO_SPRITE_COMBINE, ///< Value for using non-combined junctions.
|
RTFB_NO_SPRITE_COMBINE = 1 << RTF_NO_SPRITE_COMBINE, ///< Value for using non-combined junctions.
|
||||||
|
RTFB_ALLOW_90DEG = 1 << RTF_ALLOW_90DEG, ///< Value for always allowed 90 degree turns, regardless of setting.
|
||||||
|
RTFB_DISALLOW_90DEG = 1 << RTF_DISALLOW_90DEG, ///< Value for never allowed 90 degree turns, regardless of setting.
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(RailTypeFlags)
|
DECLARE_ENUM_AS_BIT_SET(RailTypeFlags)
|
||||||
|
|
||||||
|
@ -341,6 +346,26 @@ static inline bool RailNoLevelCrossings(RailType rt)
|
||||||
return HasBit(GetRailTypeInfo(rt)->flags, RTF_NO_LEVEL_CROSSING);
|
return HasBit(GetRailTypeInfo(rt)->flags, RTF_NO_LEVEL_CROSSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if 90 degree turns are disallowed between two railtypes.
|
||||||
|
* @param rt1 First railtype to test for.
|
||||||
|
* @param rt2 Second railtype to test for.
|
||||||
|
* @param def Default value to use if the rail type doesn't specify anything.
|
||||||
|
* @return True if 90 degree turns are disallowed between the two rail types.
|
||||||
|
*/
|
||||||
|
static inline bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def = _settings_game.pf.forbid_90_deg)
|
||||||
|
{
|
||||||
|
if (rt1 == INVALID_RAILTYPE || rt2 == INVALID_RAILTYPE) return def;
|
||||||
|
|
||||||
|
const RailtypeInfo *rti1 = GetRailTypeInfo(rt1);
|
||||||
|
const RailtypeInfo *rti2 = GetRailTypeInfo(rt2);
|
||||||
|
|
||||||
|
bool rt1_90deg = HasBit(rti1->flags, RTF_DISALLOW_90DEG) || (!HasBit(rti1->flags, RTF_ALLOW_90DEG) && def);
|
||||||
|
bool rt2_90deg = HasBit(rti2->flags, RTF_DISALLOW_90DEG) || (!HasBit(rti2->flags, RTF_ALLOW_90DEG) && def);
|
||||||
|
|
||||||
|
return rt1_90deg || rt2_90deg;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cost of building the specified railtype.
|
* Returns the cost of building the specified railtype.
|
||||||
* @param railtype The railtype being built.
|
* @param railtype The railtype being built.
|
||||||
|
|
|
@ -2100,7 +2100,7 @@ static void CheckNextTrainTile(Train *v)
|
||||||
if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) {
|
if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) {
|
||||||
/* If the next tile is a PBS signal, try to make a reservation. */
|
/* If the next tile is a PBS signal, try to make a reservation. */
|
||||||
TrackBits tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
|
TrackBits tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
|
||||||
if (_settings_game.pf.forbid_90_deg) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||||
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.m_old_td));
|
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.m_old_td));
|
||||||
}
|
}
|
||||||
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false);
|
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false);
|
||||||
|
@ -2339,7 +2339,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
if (HasOnewaySignalBlockingTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) break;
|
if (HasOnewaySignalBlockingTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_settings_game.pf.forbid_90_deg) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||||
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
||||||
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break;
|
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break;
|
||||||
}
|
}
|
||||||
|
@ -2391,7 +2391,7 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
||||||
while (tile != stopped || cur_td != stopped_td) {
|
while (tile != stopped || cur_td != stopped_td) {
|
||||||
if (!ft.Follow(tile, cur_td)) break;
|
if (!ft.Follow(tile, cur_td)) break;
|
||||||
|
|
||||||
if (_settings_game.pf.forbid_90_deg) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||||
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
||||||
assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE);
|
assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE);
|
||||||
}
|
}
|
||||||
|
@ -2626,7 +2626,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||||
DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
|
DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
|
||||||
TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir);
|
TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir);
|
||||||
TrackBits reachable = TrackdirBitsToTrackBits((TrackdirBits)(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0))) & DiagdirReachesTracks(exitdir);
|
TrackBits reachable = TrackdirBitsToTrackBits((TrackdirBits)(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0))) & DiagdirReachesTracks(exitdir);
|
||||||
if (_settings_game.pf.forbid_90_deg) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(res_dest.tile), GetTileRailType(next_tile))) {
|
||||||
reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir));
|
reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2718,7 +2718,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
||||||
TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
|
TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
|
||||||
TrackBits reachable = TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTrackdirs(exitdir));
|
TrackBits reachable = TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTrackdirs(exitdir));
|
||||||
|
|
||||||
if (_settings_game.pf.forbid_90_deg) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir));
|
if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir));
|
||||||
|
|
||||||
bool res_made = false;
|
bool res_made = false;
|
||||||
ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
|
ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
|
||||||
|
@ -3139,7 +3139,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||||
TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
|
TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
|
||||||
|
|
||||||
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
|
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
|
||||||
if (_settings_game.pf.forbid_90_deg && prev == NULL) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == NULL) {
|
||||||
/* We allow wagons to make 90 deg turns, because forbid_90_deg
|
/* We allow wagons to make 90 deg turns, because forbid_90_deg
|
||||||
* can be switched on halfway a turn */
|
* can be switched on halfway a turn */
|
||||||
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
|
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
|
||||||
|
@ -3711,7 +3711,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse)
|
||||||
|
|
||||||
/* mask unreachable track bits if we are forbidden to do 90deg turns */
|
/* mask unreachable track bits if we are forbidden to do 90deg turns */
|
||||||
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
|
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
|
||||||
if (_settings_game.pf.forbid_90_deg) {
|
if (Rail90DegTurnDisallowed(GetTileRailType(v->tile), GetTileRailType(tile))) {
|
||||||
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
|
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue