summaryrefslogtreecommitdiff
path: root/rail_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'rail_cmd.c')
-rw-r--r--rail_cmd.c89
1 files changed, 61 insertions, 28 deletions
diff --git a/rail_cmd.c b/rail_cmd.c
index 878fa0296..5449e3f55 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -1554,47 +1554,80 @@ static bool SetSignalsEnumProc(uint tile, SetSignalsData *ssd, int track, uint l
return false;
}
+/* Struct to parse data from VehicleFromPos to SignalVehicleCheckProc */
+typedef struct SignalVehicleCheckStruct {
+ TileIndex tile;
+ uint track;
+} SignalVehicleCheckStruct;
+
+static void *SignalVehicleCheckProc(Vehicle *v, void *data)
+{
+ SignalVehicleCheckStruct *dest = data;
+ TileIndex tile;
+
+ /* Find the tile outside the tunnel, for signalling */
+ if (v->u.rail.track == 0x40) {
+ tile = GetVehicleOutOfTunnelTile(v);
+ } else {
+ tile = v->tile;
+ }
+
+ /* Wrong tile, or no train? Not a match */
+ if (tile != dest->tile || v->type != VEH_Train)
+ return NULL;
+
+ /* Are we on the same piece of track? */
+ if (dest->track & (v->u.rail.track + (v->u.rail.track<<8)))
+ return v;
+
+ return NULL;
+}
+
+/* Special check for SetSignalsAfterProc, to see if there is a vehicle on this tile */
+bool SignalVehicleCheck(TileIndex tile, uint track)
+{
+ SignalVehicleCheckStruct dest;
+
+ dest.tile = tile;
+ dest.track = track;
+
+ return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL;
+}
+
static void SetSignalsAfterProc(TrackPathFinder *tpf)
{
SetSignalsData *ssd = tpf->userdata;
- Vehicle *v;
- uint tile, hash, val, offs;
TrackPathFinderLink *link;
+ uint offs;
+ uint i;
ssd->stop = false;
- // for each train, check if it is in the segment.
- // then we know that the signal should be red.
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_Train)
- continue;
-
- tile = v->tile;
- if (v->u.rail.track == 0x40) { tile = GetVehicleOutOfTunnelTile(v); }
-
- hash = PATHFIND_HASH_TILE(tile);
-
- val = tpf->hash_head[hash];
- if (val == 0)
+ /* Go through all the PF tiles */
+ for (i = 0; i < lengthof(tpf->hash_head); i++) {
+ /* Empty hash item */
+ if (tpf->hash_head[i] == 0)
continue;
- if (!(val & 0x8000)) {
- if ((TileIndex)tile == tpf->hash_tile[hash])
- goto check_val;
+ /* If 0x8000 is not set, there is only 1 item */
+ if (!(tpf->hash_head[i] & 0x8000)) {
+ /* Check if there is a vehicle on this tile */
+ if (SignalVehicleCheck(tpf->hash_tile[i], tpf->hash_head[i])) {
+ ssd->stop = true;
+ return;
+ }
} else {
- offs = tpf->hash_tile[hash];
+ /* There are multiple items, where hash_tile points to the first item in the list */
+ offs = tpf->hash_tile[i];
do {
+ /* Find the next item */
link = PATHFIND_GET_LINK_PTR(tpf, offs);
- if ( (TileIndex)tile == link->tile) {
- val = link->flags;
-check_val:;
- // the train is on the track, in either direction?
- if (val & (v->u.rail.track + (v->u.rail.track<<8))) {
- ssd->stop = true;
- return;
- }
- break;
+ /* Check if there is a vehicle on this tile */
+ if (SignalVehicleCheck(link->tile, link->flags)) {
+ ssd->stop = true;
+ return;
}
+ /* Goto the next item */
} while ((offs=link->next) != 0xFFFF);
}
}