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;
|
||||
}
|
||||
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);
|
||||
if (m_new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
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.
|
||||
*
|
||||
* @param dst_tile The tile of interest.
|
||||
* @param src_tile The originating tile.
|
||||
* @param src_trackdir The direction the vehicle is currently moving.
|
||||
* @param type The transporttype of the vehicle.
|
||||
* @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
|
||||
* @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));
|
||||
|
||||
|
@ -836,7 +837,9 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_tr
|
|||
trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -877,7 +880,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
|||
if (CheckIgnoreFirstTile(¤t->path)) {
|
||||
/* Do not perform any checks that involve src_tile */
|
||||
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) {
|
||||
/* We drive through the wormhole and arrive on the other side */
|
||||
dst_tile = GetOtherTunnelBridgeEnd(src_tile);
|
||||
|
@ -901,7 +904,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
|||
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) {
|
||||
/* 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;
|
||||
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. */
|
||||
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 && 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. */
|
||||
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));
|
||||
}
|
||||
|
|
25
src/rail.h
25
src/rail.h
|
@ -21,6 +21,7 @@
|
|||
#include "strings_type.h"
|
||||
#include "date_type.h"
|
||||
#include "signal_type.h"
|
||||
#include "settings_type.h"
|
||||
|
||||
/** Railtype flags. */
|
||||
enum RailTypeFlags {
|
||||
|
@ -28,12 +29,16 @@ enum RailTypeFlags {
|
|||
RTF_NO_LEVEL_CROSSING = 1, ///< Bit number for disallowing level crossings.
|
||||
RTF_HIDDEN = 2, ///< Bit number for hiding from selection.
|
||||
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_CATENARY = 1 << RTF_CATENARY, ///< Value for drawing a catenary.
|
||||
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_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)
|
||||
|
||||
|
@ -341,6 +346,26 @@ static inline bool RailNoLevelCrossings(RailType rt)
|
|||
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.
|
||||
* @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 the next tile is a PBS signal, try to make a reservation. */
|
||||
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));
|
||||
}
|
||||
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 (_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);
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
TileIndex next_tile = TileAddByDiagDir(res_dest.tile, 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));
|
||||
}
|
||||
|
||||
|
@ -2718,7 +2718,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
|||
TileIndex new_tile = TileAddByDiagDir(origin.tile, 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;
|
||||
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 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
|
||||
* can be switched on halfway a turn */
|
||||
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 */
|
||||
TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
|
||||
if (_settings_game.pf.forbid_90_deg) {
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(v->tile), GetTileRailType(tile))) {
|
||||
bits &= ~TrackCrossesTracks(FindFirstTrack(v->track));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue