Index: src/tunnelbridge_cmd.cpp =================================================================== --- src/tunnelbridge_cmd.cpp (revision 18015) +++ src/tunnelbridge_cmd.cpp (working copy) @@ -1326,10 +1326,40 @@ } } +/** Bite indicating vehicle position + * _tile_fractcoord_ is used to determine exact x,y position of vehicle on the tile. + * Tunnel bridge tiles can have four diagonal directions e.g., + * DIAGDIR_NE=0, DIAGDIR_SE=1, DIAGDIR_SW=2, DIAGDIR_NW=3. + * using last four bits of y_pos << 4 (shifted 4 left) and + * using last four bits of x_pos. + * x = horizontal left + * y = vertical down + * 00 is north corner of tile + * F0 is east corner of tile + * FF is south corner of tile + * 0F is west corner of tile + * | F| E| D| C| B| A| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0 + * 0|0F|0E|0D|0C|0B|0A|09|08|07|06|05|04|03|02|01|00 + * 1|1F|1E|1D|1C|1B|1A|19|18|17|16|15|14|13|12|11|10 + * 2|2F|2E|2D|2C|2B|2A|29|28|27|26|25|24|23|22|21|20 + * 3|3F|3E|3D|3C|3B|3A|39|38|37|36|35|34|33|32|31|30 + * 4|4F|4E|4D|4C|4B|4A|49|48|47|46|45|44|43|42|41|40 + * 5|5F|5E|5D|5C|5B|5A|59|58|57|56|55|54|53|52|51|50 + * 6|6F|6E|6D|6C|6B|6A|69|68|67|66|65|64|63|62|61|60 + * 7|7F|7E|7D|7C|7B|7A|79|78|77|76|75|74|73|72|71|70 + * 8|8F|8E|8D|8C|8B|8A|89|88|87|86|85|84|83|82|81|80 + * 9|9F|9E|9D|9C|9B|9A|99|98|97|96|95|94|93|92|91|90 + * A|AF|AE|AD|AC|AB|AA|A9|A8|A7|A6|A5|A4|A3|A2|A1|A0 + * B|BF|BE|BD|BC|BB|BA|B9|B8|B7|B6|B5|B4|B3|B2|B1|B0 + * C|CF|CE|CD|CC|CB|CA|C9|C8|C7|C6|C5|C4|C3|C2|C1|C0 + * D|DF|DE|DD|DC|DB|DA|D9|D8|D7|D6|D5|D4|D3|D2|D1|D0 + * E|EF|EE|ED|EC|EB|EA|E9|E8|E7|E6|E5|E4|E3|E2|E1|E0 + * F|FF|FE|FD|FC|FB|FA|F9|F8|F7|F6|F5|F4|F3|F2|F1|F0 + */ -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 _tile_fractcoord_1[4] = {0x8E, 0x18, 0x81, 0xE8}; +static const byte _tile_fractcoord_2[4] = {0x81, 0x98, 0x87, 0x38}; +static const byte _tile_fractcoord_3[4] = {0x82, 0x88, 0x86, 0x48}; static const byte _exit_tunnel_track[4] = {1, 2, 1, 2}; /** Get the trackdir of the exit of a tunnel */ @@ -1338,80 +1368,104 @@ }; static const byte _road_exit_tunnel_frame[4] = {2, 7, 9, 4}; -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}; +static const byte _tile_fractcoord_4[4] = {0x52, 0x85, 0x98, 0x29}; +static const byte _tile_fractcoord_5[4] = {0x92, 0x89, 0x58, 0x25}; +static const byte _tile_fractcoord_6[4] = {0x92, 0x89, 0x56, 0x45}; +static const byte _tile_fractcoord_7[4] = {0x52, 0x85, 0x96, 0x49}; +/** Handle vehicles on tunnel and bridge entrance and exit + * variables tbdir and vdir are used to determine entrance and exit tile according to direction of + * vehicle. + */ 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; - const DiagDirection dir = GetTunnelBridgeDirection(tile); + if (abs(z) > 2) return VETSB_CONTINUE; + const DiagDirection tbdir = GetTunnelBridgeDirection(tile); + const DiagDirection vdir = DirToDiagDir(v->direction); // Get diagonal direction of vehicle + if (IsTunnel(tile)) { - byte fc; - DiagDirection vdir; + /* Entrance */ + if (tbdir == vdir) { + byte fc = (x & 0xF) + (y << 4); + if (fc == _tile_fractcoord_1[tbdir] && v->type == VEH_TRAIN) { + Train *t = Train::From(v); + if (t->IsFrontEngine() && !PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) { + SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); + } + return VETSB_CONTINUE; + } + if (fc == _tile_fractcoord_2[tbdir] && v->type == VEH_TRAIN) { + Train::From(v)->vehstatus |= VS_HIDDEN; + return VETSB_CONTINUE; + } + if (fc == _tile_fractcoord_4[tbdir] || fc == _tile_fractcoord_5[tbdir] && v->type == VEH_ROAD) { + RoadVehicle::From(v)->vehstatus |= VS_HIDDEN; + return VETSB_CONTINUE; + } - 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 (!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]) { + switch (tbdir) { // return if not on last position of tile just before entering worm hole + 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; + } + switch (v->type) { + case VEH_TRAIN: { + Train *t = Train::From(v); t->tile = tile; t->track = TRACK_BIT_WORMHOLE; - t->vehstatus |= VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; - } - } + } break; - if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) { - /* We're at the tunnel exit ?? */ - t->tile = tile; - t->track = (TrackBits)_exit_tunnel_track[dir]; - 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]) { + case VEH_ROAD: { + RoadVehicle *rv = RoadVehicle::From(v); rv->tile = tile; rv->state = RVSB_WORMHOLE; - rv->vehstatus |= VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; - } else { - return VETSB_CONTINUE; - } + } break; + + default: NOT_REACHED(); } + } else { + /* Exit */ + switch (v->type) { - if (dir == ReverseDiagDir(vdir) && ( - /* We're at the tunnel exit ?? */ - fc == _tunnel_fractcoord_6[dir] || - fc == _tunnel_fractcoord_7[dir] - ) && - z == 0) { - rv->tile = tile; - rv->state = _road_exit_tunnel_state[dir]; - rv->frame = _road_exit_tunnel_frame[dir]; - rv->vehstatus &= ~VS_HIDDEN; - return VETSB_ENTERED_WORMHOLE; + case VEH_TRAIN: { + Train *t = Train::From(v); + if (t->track == TRACK_BIT_WORMHOLE) { + t->track = (DiagDirToAxis(tbdir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + t->tile = tile; + return VETSB_ENTERED_WORMHOLE; + } + + byte fc = (x & 0xF) + (y << 4); + if (fc == _tile_fractcoord_3[tbdir] && z == 0) { + t->vehstatus &= ~VS_HIDDEN; + return VETSB_CONTINUE; + } + } break; + + case VEH_ROAD: { + RoadVehicle *rv = RoadVehicle::From(v); + if (rv->state == RVSB_WORMHOLE) { + rv->state = _road_exit_tunnel_state[tbdir]; + rv->frame = 0; + rv->tile = tile; + return VETSB_ENTERED_WORMHOLE; + } + + byte fc = (x & 0xF) + (y << 4); + if ((fc == _tile_fractcoord_6[tbdir] || fc == _tile_fractcoord_7[tbdir]) && z == 0) { + rv->vehstatus &= ~VS_HIDDEN; + return VETSB_CONTINUE; + } + } break; + + default: NOT_REACHED(); } } } else { // IsBridge(tile) @@ -1420,17 +1474,18 @@ /* modify speed of vehicle */ uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed; - if (v->type == VEH_ROAD) spd *= 2; - if (v->cur_speed > spd) v->cur_speed = spd; + if (v->type == VEH_ROAD) spd = (spd << 1); + if (v->cur_speed > spd) v->cur_speed = spd; } - if (DirToDiagDir(v->direction) == dir) { - switch (dir) { + /* Entrance */ + if (tbdir == vdir) { + switch (tbdir) { 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; + 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; } switch (v->type) { case VEH_TRAIN: { @@ -1451,13 +1506,14 @@ default: NOT_REACHED(); } return VETSB_ENTERED_WORMHOLE; - } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { - v->tile = tile; + } else { // Exit + 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 = (DiagDirToAxis(tbdir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + t->tile = tile; return VETSB_ENTERED_WORMHOLE; } } break; @@ -1465,8 +1521,9 @@ case VEH_ROAD: { RoadVehicle *rv = RoadVehicle::From(v); if (rv->state == RVSB_WORMHOLE) { - rv->state = _road_exit_tunnel_state[dir]; + rv->state = _road_exit_tunnel_state[tbdir]; rv->frame = 0; + rv->tile = tile; return VETSB_ENTERED_WORMHOLE; } } break; @@ -1474,7 +1531,8 @@ 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 = (DiagDirToAxis(tbdir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + ship->tile = tile; return VETSB_ENTERED_WORMHOLE; } } break; @@ -1512,18 +1570,18 @@ } extern const TileTypeProcs _tile_type_tunnelbridge_procs = { - DrawTile_TunnelBridge, // draw_tile_proc - GetSlopeZ_TunnelBridge, // get_slope_z_proc - ClearTile_TunnelBridge, // clear_tile_proc - NULL, // add_accepted_cargo_proc - GetTileDesc_TunnelBridge, // get_tile_desc_proc - GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc - NULL, // click_tile_proc - NULL, // animate_tile_proc - TileLoop_TunnelBridge, // tile_loop_clear - ChangeTileOwner_TunnelBridge, // change_tile_owner_clear - NULL, // add_produced_cargo_proc - VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc - GetFoundation_TunnelBridge, // get_foundation_proc - TerraformTile_TunnelBridge, // terraform_tile_proc + DrawTile_TunnelBridge, // draw_tile_proc + GetSlopeZ_TunnelBridge, // get_slope_z_proc + ClearTile_TunnelBridge, // clear_tile_proc + NULL, // add_accepted_cargo_proc + GetTileDesc_TunnelBridge, // get_tile_desc_proc + GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc + NULL, // click_tile_proc + NULL, // animate_tile_proc + TileLoop_TunnelBridge, // tile_loop_clear + ChangeTileOwner_TunnelBridge, // change_tile_owner_clear + NULL, // add_produced_cargo_proc + VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc + GetFoundation_TunnelBridge, // get_foundation_proc + TerraformTile_TunnelBridge, // terraform_tile_proc };