summaryrefslogtreecommitdiff
path: root/rail_cmd.c
diff options
context:
space:
mode:
authorhackykid <hackykid@openttd.org>2005-07-04 14:58:55 +0000
committerhackykid <hackykid@openttd.org>2005-07-04 14:58:55 +0000
commit60ddaf95f0b52a09fad18ea05b2b9db4509d0511 (patch)
treec0f8f7ba8535ff0f5e9fd8581b36c737ac10e0b1 /rail_cmd.c
parentb872cf7f7bd6fdcc8b09903130cb961c004ad5de (diff)
downloadopenttd-60ddaf95f0b52a09fad18ea05b2b9db4509d0511.tar.xz
(svn r2516) - Feature: [pbs] Implement path-based-signalling. This allows multiple trains within the same signal block, provided their paths dont intersect. For this the block must have all exit and entry signals be pbs signals. Place these by ctrl-clicking 4 times on a normal signal.
- Feature: [pbs] Implement autoplacement of pbs blocks, when a block has an entry and an exit pbs signal, covert the entire block to pbs. Can be turned off in the patch settings. - Feature: [pbs] Allow showing of reserved status by making the tracks darker, when the pbs debug level is at least 1.
Diffstat (limited to 'rail_cmd.c')
-rw-r--r--rail_cmd.c137
1 files changed, 101 insertions, 36 deletions
diff --git a/rail_cmd.c b/rail_cmd.c
index a1340428b..796ba88fd 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -15,7 +15,9 @@
#include "station.h"
#include "sprite.h"
#include "depot.h"
+#include "pbs.h"
#include "waypoint.h"
+#include "npf.h"
#include "rail.h"
extern uint16 _custom_sprites_base;
@@ -757,10 +759,10 @@ int32 CmdBuildSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
_map3_lo[tile] |= SignalOnTrack(track);
} else {
if (pre_signal) {
- // cycle between normal -> pre -> exit -> combo -> ...
- byte type = (GetSignalType(tile, track) + 1) & 0x03;
- _map3_hi[tile] &= ~0x03;
- _map3_hi[tile] |= type;
+ // cycle between normal -> pre -> exit -> combo -> pbs ->...
+ byte type = ((GetSignalType(tile, track) + 1) % 5);
+ _map3_hi[tile] &= ~0x07;
+ _map3_hi[tile] |= type ;
} else {
// cycle between two-way -> one-way -> one-way -> ...
/* TODO: Rewrite switch into something more general */
@@ -1123,21 +1125,24 @@ static const SpriteID _signal_base_sprites[32] = {
0x1333,
0x1343,
- 0x0, //PBS place, light signal
- 0x0, //reserved for future use
- 0x0, //reserved for future use
- 0x0, //reserved for future use
+ // pbs signals
+ 0x1393,
+ 0x13A3, // not used (yet?)
+ 0x13B3, // not used (yet?)
+ 0x13C3, // not used (yet?)
- // use semaphores instead of signals?
+ // semaphores
0x1353,
0x1363,
0x1373,
0x1383,
- 0x0, //PBS place, semaphore
- 0x0, //reserved for future use
- 0x0, //reserved for future use
- 0x0, //reserved for future use
+ // pbs semaphores
+ 0x13D3,
+ 0x13E3, // not used (yet?)
+ 0x13F3, // not used (yet?)
+ 0x1403, // not used (yet?)
+
// mirrored versions
0x4FB,
@@ -1145,20 +1150,23 @@ static const SpriteID _signal_base_sprites[32] = {
0x1333,
0x1343,
- 0x0, //PBS place, semaphore
- 0x0, //reserved for future use
- 0x0, //reserved for future use
- 0x0, //reserved for future use
-
- 0x13C6,
- 0x13D6,
- 0x13E6,
- 0x13F6,
-
- 0x0, //PBS place, semaphore
- 0x0, //reserved for future use
- 0x0, //reserved for future use
- 0x0, //reserved for future use
+ // pbs signals
+ 0x1393,
+ 0x13A3, // not used (yet?)
+ 0x13B3, // not used (yet?)
+ 0x13C3, // not used (yet?)
+
+ // semaphores
+ 0x1446,
+ 0x1456,
+ 0x1466,
+ 0x1476,
+
+ // pbs semaphores
+ 0x14C6,
+ 0x14D6, // not used (yet?)
+ 0x14E6, // not used (yet?)
+ 0x14F6, // not used (yet?)
};
// used to determine the side of the road for the signal
@@ -1466,6 +1474,16 @@ static void DrawTile_Track(TileInfo *ti)
if (m5 & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST]);
}
+ if (_debug_pbs_level >= 1) {
+ byte pbs = PBSTileReserved(ti->tile);
+ if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite(TrackSet[SINGLE_Y] | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite(TrackSet[SINGLE_X] | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(TrackSet[SINGLE_NORTH] | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(TrackSet[SINGLE_SOUTH] | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_LEFT) DrawGroundSprite(TrackSet[SINGLE_WEST] | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST] | PALETTE_CRASH);
+ }
+
if (_display_opt & DO_FULL_DETAIL) {
_detailed_track_proc[_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK](ti);
}
@@ -1575,6 +1593,16 @@ static void DrawTile_Track(TileInfo *ti)
DrawGroundSprite(image);
+ if (_debug_pbs_level >= 1) {
+ byte pbs = PBSTileReserved(ti->tile);
+ if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite((0x3ED + tracktype_offs) | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite((0x3EE + tracktype_offs) | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_UPPER) DrawGroundSprite((0x3EF + tracktype_offs) | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_LOWER) DrawGroundSprite((0x3F0 + tracktype_offs) | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_LEFT) DrawGroundSprite((0x3F2 + tracktype_offs) | PALETTE_CRASH);
+ if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite((0x3F1 + tracktype_offs) | PALETTE_CRASH);
+ }
+
while ((image=drss->image) != 0) {
DrawSpecialBuilding(image, type < 4 ? tracktype_offs : 0, ti,
drss->subcoord_x, drss->subcoord_y, 0,
@@ -1611,15 +1639,17 @@ void DrawTrainDepotSprite(int x, int y, int image, int railtype)
}
}
-#define NUM_SSD_ENTRY 256
-#define NUM_SSD_STACK 32
-
typedef struct SetSignalsData {
int cur;
int cur_stack;
bool stop;
bool has_presignal;
+ bool has_pbssignal;
+ // lowest 2 bits = amount of pbs signals in the block, clamped at 2
+ // bit 2 = there is a pbs entry signal in this block
+ // bit 3 = there is a pbs exit signal in this block
+
// presignal info
int presignal_exits;
int presignal_exits_free;
@@ -1628,6 +1658,10 @@ typedef struct SetSignalsData {
byte bit[NUM_SSD_ENTRY];
TileIndex tile[NUM_SSD_ENTRY];
+ int pbs_cur;
+ // these are used to keep track of all signals in the block
+ TileIndex pbs_tile[NUM_SSD_ENTRY];
+
// these are used to keep track of the stack that modifies presignals recursively
TileIndex next_tile[NUM_SSD_STACK];
byte next_dir[NUM_SSD_STACK];
@@ -1647,15 +1681,34 @@ static bool SetSignalsEnumProc(TileIndex tile, SetSignalsData *ssd, int track, u
ssd->cur++;
}
+ if (PBSIsPbsSignal(tile, ReverseTrackdir(track)))
+ SETBIT(ssd->has_pbssignal, 2);
+
// remember if this block has a presignal.
ssd->has_presignal |= (_map3_hi[tile]&1);
}
- // is this an exit signal that points out from the segment?
- if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) {
- ssd->presignal_exits++;
- if ((_map2[tile]&_signals_table_other[track]) != 0)
- ssd->presignal_exits_free++;
+ if (PBSIsPbsSignal(tile, ReverseTrackdir(track)) || PBSIsPbsSignal(tile, track)) {
+ byte num = ssd->has_pbssignal & 3;
+ num = clamp(num + 1, 0, 2);
+ ssd->has_pbssignal &= ~3;
+ ssd->has_pbssignal |= num;
+ }
+
+ if ((_map3_lo[tile] & _signals_table_both[track]) != 0) {
+ ssd->pbs_tile[ssd->pbs_cur] = tile; // remember the tile index
+ ssd->pbs_cur++;
+ }
+
+ if (_map3_lo[tile]&_signals_table_other[track]) {
+ if (_map3_hi[tile]&2) {
+ // this is an exit signal that points out from the segment
+ ssd->presignal_exits++;
+ if ((_map2[tile]&_signals_table_other[track]) != 0)
+ ssd->presignal_exits_free++;
+ }
+ if (PBSIsPbsSignal(tile, track))
+ SETBIT(ssd->has_pbssignal, 3);
}
return true;
@@ -1792,6 +1845,15 @@ static void ChangeSignalStates(SetSignalsData *ssd)
// there is at least one green exit signal OR
// there are no exit signals in the segment
+ // convert the block to pbs, if needed
+ if (_patches.auto_pbs_placement && !(ssd->stop) && (ssd->has_pbssignal == 0xE) && !ssd->has_presignal && (ssd->presignal_exits == 0)) // 0xE means at least 2 pbs signals, and at least 1 entry and 1 exit, see comments ssd->has_pbssignal
+ for(i=0; i!=ssd->pbs_cur; i++) {
+ TileIndex tile = ssd->pbs_tile[i];
+ _map3_hi[tile] &= ~0x07;
+ _map3_hi[tile] |= 0x04;
+ MarkTileDirtyByTile(tile);
+ };
+
// then mark the signals in the segment accordingly
for(i=0; i!=ssd->cur; i++) {
TileIndex tile = ssd->tile[i];
@@ -1852,8 +1914,9 @@ bool UpdateSignalsOnSegment(TileIndex tile, byte direction)
for(;;) {
// go through one segment and update all signals pointing into that segment.
- ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
+ ssd.cur = ssd.pbs_cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
ssd.has_presignal = false;
+ ssd.has_pbssignal = false;
FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
ChangeSignalStates(&ssd);
@@ -2162,6 +2225,8 @@ static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
} else if (_fractcoords_enter[dir] == fract_coord) {
if (_enter_directions[dir] == v->direction) {
/* enter the depot */
+ if (v->next == NULL)
+ PBSClearTrack(v->tile, FIND_FIRST_BIT(v->u.rail.track));
v->u.rail.track = 0x80,
v->vehstatus |= VS_HIDDEN; /* hide it */
v->direction ^= 4;