diff -r 5f31e43dd7fd -r 1b9f29d4f24b src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp Fri Oct 22 12:17:34 2010 +0000 +++ b/src/tunnelbridge_cmd.cpp Fri Oct 22 16:53:36 2010 +0200 @@ -1481,48 +1481,59 @@ } } +/** Frame when the 'enter tunnel' sound should be played. This is the second + * frame on a tile, so the sound is played shortly after entering the tunnel + * tile, while the vehicle is still visible. */ +static const byte TUNNEL_SOUND_FRAME = 1; -static const byte _tunnel_fractcoord_1[4] = {0x8E, 0x18, 0x81, 0xE8}; -static const byte _tunnel_fractcoord_2[4] = {0x81, 0x98, 0x87, 0x38}; -static const byte _tunnel_fractcoord_3[4] = {0x82, 0x88, 0x86, 0x48}; -static const byte _exit_tunnel_track[4] = {1, 2, 1, 2}; +/** + * Frame when a train should be hidden in a tunnel with a certain direction. + * This differs per direction, because of visibility / bounding box issues. + * Note that direction, in this case, is the direction leading into the tunnel. + * When entering a tunnel, hide the train when it reaches the given frame. + * When leaving a tunnel, show the train when it is one frame further + * to the 'outside', i.e. at (TILE_SIZE-1) - (frame) + 1 */ +static const byte _train_tunnel_frame[DIAGDIR_END] = {14, 9, 7, 12}; -/** Get the trackdir of the exit of a tunnel */ -static const Trackdir _road_exit_tunnel_state[DIAGDIR_END] = { - TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE -}; -static const byte _road_exit_tunnel_frame[4] = {2, 7, 9, 4}; +/** Frame when a road vehicle enters a tunnel with a certain direction. + * This differs per direction, like for trains. To make it even more fun, + * the entry and exit frames are not consistent. This is the entry frame, + * the road vehicle should be hidden when it reaches this frame.*/ +static const byte _road_enter_tunnel_frame[DIAGDIR_END] = {13, 8, 8, 13}; -static const byte _tunnel_fractcoord_4[4] = {0x52, 0x85, 0x98, 0x29}; -static const byte _tunnel_fractcoord_5[4] = {0x92, 0x89, 0x58, 0x25}; -static const byte _tunnel_fractcoord_6[4] = {0x92, 0x89, 0x56, 0x45}; -static const byte _tunnel_fractcoord_7[4] = {0x52, 0x85, 0x96, 0x49}; +/** Frame when a road vehicle exits a tunnel with a certain direction. + * Note that 'direction' refers to the tunnel direction, not the + * vehicle direction. As stated above, this frame is not the same as the + * entry frame, for unclear (historical?) reasons. */ +static const byte _road_exit_tunnel_frame[DIAGDIR_END] = {2, 7, 9, 4}; + static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y) { int z = GetSlopeZ(x, y) - v->z_pos; if (abs(z) > 2) return VETSB_CANNOT_ENTER; + /* Direction into the wormhole */ const DiagDirection dir = GetTunnelBridgeDirection(tile); + /* Direction of the vehicle */ + const DiagDirection vdir = DirToDiagDir(v->direction); + /* New position of the vehicle on the tile */ + byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK; + /* Number of units moved by the vehicle since entering the tile */ + byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos; if (IsTunnel(tile)) { - byte fc; - DiagDirection vdir; - if (v->type == VEH_TRAIN) { Train *t = Train::From(v); - fc = (x & 0xF) + (y << 4); - - vdir = DirToDiagDir(t->direction); if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) { - if (t->IsFrontEngine() && fc == _tunnel_fractcoord_1[dir]) { + if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) { if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) { SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); } return VETSB_CONTINUE; } - if (fc == _tunnel_fractcoord_2[dir]) { + if (frame == _train_tunnel_frame[dir]) { t->tile = tile; t->track = TRACK_BIT_WORMHOLE; t->vehstatus |= VS_HIDDEN; @@ -1530,23 +1541,22 @@ } } - if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) { + if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _train_tunnel_frame[dir] && z == 0) { /* We're at the tunnel exit ?? */ t->tile = tile; - t->track = (TrackBits)_exit_tunnel_track[dir]; + t->track = DiagDirToDiagTrackBits(vdir); assert(t->track); t->vehstatus &= ~VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; } } else if (v->type == VEH_ROAD) { RoadVehicle *rv = RoadVehicle::From(v); - fc = (x & 0xF) + (y << 4); - vdir = DirToDiagDir(v->direction); /* Enter tunnel? */ if (rv->state != RVSB_WORMHOLE && dir == vdir) { - if (fc == _tunnel_fractcoord_4[dir] || - fc == _tunnel_fractcoord_5[dir]) { + if (frame == _road_enter_tunnel_frame[dir]) { + /* Frame should be equal to the next frame number in the RV's movement */ + assert(frame == rv->frame + 1); rv->tile = tile; rv->state = RVSB_WORMHOLE; rv->vehstatus |= VS_HIDDEN; @@ -1556,15 +1566,11 @@ } } - if (dir == ReverseDiagDir(vdir) && ( - /* We're at the tunnel exit ?? */ - fc == _tunnel_fractcoord_6[dir] || - fc == _tunnel_fractcoord_7[dir] - ) && - z == 0) { + /* We're at the tunnel exit ?? */ + if (dir == ReverseDiagDir(vdir) && frame == _road_exit_tunnel_frame[dir] && z == 0) { rv->tile = tile; - rv->state = _road_exit_tunnel_state[dir]; - rv->frame = _road_exit_tunnel_frame[dir]; + rv->state = DiagDirToDiagTrackdir(vdir); + rv->frame = frame; rv->vehstatus &= ~VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; } @@ -1579,14 +1585,9 @@ if (v->cur_speed > spd) v->cur_speed = spd; } - if (DirToDiagDir(v->direction) == dir) { - switch (dir) { - default: NOT_REACHED(); - case DIAGDIR_NE: if ((x & 0xF) != 0) return VETSB_CONTINUE; break; - case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; - case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; - case DIAGDIR_NW: if ((y & 0xF) != 0) return VETSB_CONTINUE; break; - } + if (vdir == dir) { + /* Vehicle enters bridge at the last frame inside this tile. */ + if (frame != TILE_SIZE - 1) return VETSB_CONTINUE; switch (v->type) { case VEH_TRAIN: { Train *t = Train::From(v); @@ -1612,13 +1613,13 @@ default: NOT_REACHED(); } return VETSB_ENTERED_WORMHOLE; - } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { + } else if (vdir == ReverseDiagDir(dir)) { v->tile = tile; switch (v->type) { case VEH_TRAIN: { Train *t = Train::From(v); if (t->track == TRACK_BIT_WORMHOLE) { - t->track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + t->track = DiagDirToDiagTrackBits(vdir); return VETSB_ENTERED_WORMHOLE; } break; @@ -1627,7 +1628,7 @@ case VEH_ROAD: { RoadVehicle *rv = RoadVehicle::From(v); if (rv->state == RVSB_WORMHOLE) { - rv->state = _road_exit_tunnel_state[dir]; + rv->state = DiagDirToDiagTrackdir(vdir); rv->frame = 0; return VETSB_ENTERED_WORMHOLE; } @@ -1637,7 +1638,7 @@ case VEH_SHIP: { Ship *ship = Ship::From(v); if (ship->state == TRACK_BIT_WORMHOLE) { - ship->state = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + ship->state = DiagDirToDiagTrackBits(vdir); return VETSB_ENTERED_WORMHOLE; } break;