--- a/bridge_cmd.c Sun Dec 31 02:53:23 2006 +0000
+++ b/bridge_cmd.c Sun Dec 31 12:28:51 2006 +0000
@@ -985,12 +985,25 @@
uint32 VehicleEnter_Railway_Bridge(Vehicle *v, TileIndex tile, int x, int y)
{
DiagDirection dir;
+ uint8 dxy;
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);
+
+ switch (dir) {
+ default: NOT_REACHED();
+ case DIAGDIR_NE: dxy = 0xF8; break;
+ case DIAGDIR_SE: dxy = 0x80; break;
+ case DIAGDIR_SW: dxy = 0x08; break;
+ case DIAGDIR_NW: dxy = 0x8F; break;
+ }
+ SB(x, 0, 4, GB(dxy, 4, 4));
+ SB(y, 0, 4, GB(dxy, 0, 4));
+ v->x_pos = x;
+ v->y_pos = y;
return 0;
}
--- a/train_cmd.c Sun Dec 31 02:53:23 2006 +0000
+++ b/train_cmd.c Sun Dec 31 12:28:51 2006 +0000
@@ -2740,26 +2740,24 @@
static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
{
- 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);
- }
+ 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);
}
}
}
@@ -2785,12 +2783,9 @@
static Direction GetNewVehicleDirection(const Vehicle *v, int x, int y)
{
- 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));
+ uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1);
+ assert(offs < 11);
+ return _new_vehicle_direction_table[offs];
}
static int GetDirectionToVehicle(const Vehicle *v, int x, int y)
@@ -3078,12 +3073,15 @@
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 */
+ /* We should not let the train that is leaving custom bridge head (entering bridge)
+ * to enter the tile that is under bridge. Enter the bridge wormhole instead. */
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;
+ UpdateTrainDeltaXY(v, v->direction);
+ if (update_image) v->cur_image = GetTrainImage(v, v->direction);
+ continue;
}
/* Get the status of the tracks in the new tile and mask
@@ -3181,7 +3179,10 @@
SetSpeedLimitOnBridge(v);
- if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 0x4)) {
+ if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && ((VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 0x4) != 0)) {
+ /* vehicle just left the bridge/tunnel wormhole and entered ramp/exit from inside */
+ } else {
+ /* vehicle stays in the bridge/tunnel wormhole */
v->x_pos = gp.x;
v->y_pos = gp.y;
VehiclePositionChanged(v);
@@ -3190,7 +3191,6 @@
}
}
-move_done:
/* update image of train, as well as delta XY */
newdir = GetNewVehicleDirection(v, gp.x, gp.y);
UpdateTrainDeltaXY(v, newdir);