(svn r7687) [cbh] - Fix: trains can now enter the bridge from side. They still can't leave it from side (pathfinder will need to be invoked when the other ramp is entered). Also the code is not very clear and needs review. It is more proof of concept than final solution. I hope that somebody smarter (Celestar) can do it better. custombridgeheads
authorKUDr
Sun, 31 Dec 2006 02:53:23 +0000
branchcustombridgeheads
changeset 5611 11da6bafbfb9
parent 5610 f67ca2533978
child 5612 5e103bb5236d
(svn r7687) [cbh] - Fix: trains can now enter the bridge from side. They still can't leave it from side (pathfinder will need to be invoked when the other ramp is entered). Also the code is not very clear and needs review. It is more proof of concept than final solution. I hope that somebody smarter (Celestar) can do it better.
bridge_cmd.c
train_cmd.c
--- a/bridge_cmd.c	Sat Dec 30 18:36:42 2006 +0000
+++ b/bridge_cmd.c	Sun Dec 31 02:53:23 2006 +0000
@@ -982,7 +982,19 @@
 	return 0;
 }
 
-static uint32 VehicleEnter_Railway_Bridge(Vehicle *v, TileIndex tile, int x, int y)
+uint32 VehicleEnter_Railway_Bridge(Vehicle *v, TileIndex tile, int x, int y)
+{
+	DiagDirection dir;
+	assert(IsBridgeTile(v->tile));
+	dir = GetBridgeRampDirection(v->tile);
+	v->u.rail.track = 0x40;
+	v->direction = DiagDirToDir(dir);
+	CLRBIT(v->u.rail.flags, VRF_GOINGUP);
+	CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
+	return 0;
+}
+
+static uint32 VehicleEnter_Railway_BridgeRamp(Vehicle *v, TileIndex tile, int x, int y)
 {
 	int z = GetSlopeZ(x, y) - v->z_pos;
 
@@ -1004,20 +1016,8 @@
 	}
 
 	dir = GetBridgeRampDirection(tile);
-	if (DirToDiagDir(v->direction) == dir ||
-			(IsTileType(tile, MP_RAILWAY_BRIDGE) && DirToDiagDir(v->direction) != ReverseDiagDir(dir))) {
-		switch (dir) {
-			default: NOT_REACHED();
-			case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
-			case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
-			case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
-			case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
-		}
-		v->u.rail.track = 0x40;
-		CLRBIT(v->u.rail.flags, VRF_GOINGUP);
-		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
-		return 4;
-	} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
+	if (v->direction == DiagDirToDir(ReverseDiagDir(dir))) {
+		/* leaving the bridge */
 		v->tile = tile;
 		if (v->u.rail.track == 0x40) {
 			v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
@@ -1030,7 +1030,7 @@
 
 static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
 {
-	if (v->type == VEH_Train) return VehicleEnter_Railway_Bridge(v, tile, x, y);
+	if (v->type == VEH_Train) return VehicleEnter_Railway_BridgeRamp(v, tile, x, y);
 
 	if (v->type == VEH_Road) return VehicleEnter_Street_Bridge(v, tile, x, y);
 
--- a/train_cmd.c	Sat Dec 30 18:36:42 2006 +0000
+++ b/train_cmd.c	Sun Dec 31 02:53:23 2006 +0000
@@ -2740,24 +2740,26 @@
 
 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
 {
-	byte new_z, old_z;
-
-	// need this hint so it returns the right z coordinate on bridges.
-	new_z = GetSlopeZ(v->x_pos, v->y_pos);
-
-	old_z = v->z_pos;
-	v->z_pos = new_z;
-
-	if (new_tile) {
-		CLRBIT(v->u.rail.flags, VRF_GOINGUP);
-		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
-
-		if (new_z != old_z) {
-			TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
-
-			// XXX workaround, whole UP/DOWN detection needs overhaul
-			if (!IsTunnelTile(tile)) {
-				SETBIT(v->u.rail.flags, (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
+	byte new_z;
+	byte old_z = v->z_pos;
+
+	if (v->type != VEH_Train || v->u.rail.track != 0x40) {
+		// need this hint so it returns the right z coordinate on bridges.
+		new_z = GetSlopeZ(v->x_pos, v->y_pos);
+
+		v->z_pos = new_z;
+
+		if (new_tile) {
+			CLRBIT(v->u.rail.flags, VRF_GOINGUP);
+			CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
+
+			if (new_z != old_z) {
+				TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
+
+				// XXX workaround, whole UP/DOWN detection needs overhaul
+				if (!IsTunnelTile(tile)) {
+					SETBIT(v->u.rail.flags, (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
+				}
 			}
 		}
 	}
@@ -2783,9 +2785,12 @@
 
 static Direction GetNewVehicleDirection(const Vehicle *v, int x, int y)
 {
-	uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1);
-	assert(offs < 11);
-	return _new_vehicle_direction_table[offs];
+	if (v->type != VEH_Train || v->u.rail.track != 0x40 || !IsBridgeTile(v->tile)) {
+		uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1);
+		assert(offs < 11);
+		return _new_vehicle_direction_table[offs];
+	}
+	return DiagDirToDir(GetBridgeRampDirection(v->tile));
 }
 
 static int GetDirectionToVehicle(const Vehicle *v, int x, int y)
@@ -3042,7 +3047,10 @@
 				} else {
 					/* is not inside depot */
 
-					if (!TrainCheckIfLineEnds(v)) return;
+					if (!TrainCheckIfLineEnds(v)) {
+						/* reversing */
+						return;
+					}
 
 					r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
 					if (r & 0x8) {
@@ -3064,11 +3072,20 @@
 				/* A new tile is about to be entered. */
 
 				byte bits;
+
 				/* Determine what direction we're entering the new tile from */
 				dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile);
 				enterdir = DirToDiagDir(dir);
 				assert(enterdir==0 || enterdir==1 || enterdir==2 || enterdir==3);
 
+				/* We should not let the train that is leaving custom bridge head to enter the tile that is under bridge */
+				if (IsBridgeTile(gp.old_tile) && GetBridgeRampDirection(gp.old_tile) == enterdir) {
+					/* train entering the bridge body */
+					extern uint32 VehicleEnter_Railway_Bridge(Vehicle *v, TileIndex tile, int x, int y);
+					VehicleEnter_Railway_Bridge(v, gp.new_tile, gp.x, gp.y);
+					goto move_done;
+				}
+
 				/* Get the status of the tracks in the new tile and mask
 				 * away the bits that aren't reachable. */
 				ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _reachable_tracks[enterdir];
@@ -3173,6 +3190,7 @@
 			}
 		}
 
+move_done:
 		/* update image of train, as well as delta XY */
 		newdir = GetNewVehicleDirection(v, gp.x, gp.y);
 		UpdateTrainDeltaXY(v, newdir);
@@ -3405,11 +3423,11 @@
 
 	tile = v->tile;
 
-	if (IsTileType(tile, MP_TUNNEL) || IsTileType(tile, MP_RAILWAY_BRIDGE)) {
-		DiagDirection dir;
-
-		dir = IsTunnelTile(tile) ? GetTunnelDirection(tile) : GetBridgeRampDirection(tile);
-		if (DiagDirToDir(dir) == v->direction) return true;
+	if (IsTunnelTile(tile)) {
+		DiagDirection dir = GetTunnelDirection(tile);
+		if (v->direction == DiagDirToDir(dir)) return true;
+	} else if (IsBridgeTile(tile)) {
+		if (TrackdirToExitdir(GetVehicleTrackdir(v)) == GetBridgeRampDirection(tile)) return true;
 	}
 
 	// depot?