From e138d3564beefae1773c4a05ed3fc88d4f5f0b1b Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 21 Jun 2017 23:40:19 +0100 Subject: [PATCH 1/3] Fix tram reversing on custom bridge head tiles. (cherry picked from commit 0a345efc27d967d3ec5dd465ac6aa6044fa8bc91) --- src/roadveh_cmd.cpp | 4 ++-- src/tunnelbridge_cmd.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 1072c72d41..c8ae6f518a 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1097,7 +1097,7 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl }; RoadBits required = required_roadbits[dir & 0x07]; - if ((required & GetAnyRoadBits(tile, v->roadtype, true)) == ROAD_NONE) { + if ((required & GetAnyRoadBits(tile, v->roadtype, false)) == ROAD_NONE) { dir = INVALID_TRACKDIR; } @@ -1348,7 +1348,7 @@ again: Trackdir dir; uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME; - if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true))) { + if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false))) { /* * The tram is turning around with one tram 'roadbit'. This means that * it is using the 'big' corner 'drive data'. However, to support the diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 630c95da68..a5a6dd83e9 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1895,6 +1895,12 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti case VEH_ROAD: { RoadVehicle *rv = RoadVehicle::From(v); + if (IsRoadCustomBridgeHeadTile(tile)) { + RoadBits bits = ROAD_NONE; + if (rv->compatible_roadtypes & ROADTYPES_TRAM) bits |= GetCustomBridgeHeadRoadBits(tile, ROADTYPE_TRAM); + if (rv->compatible_roadtypes & ROADTYPES_ROAD) bits |= GetCustomBridgeHeadRoadBits(tile, ROADTYPE_ROAD); + if (!(bits & DiagDirToRoadBits(GetTunnelBridgeDirection(tile)))) return VETSB_CONTINUE; + } rv->state = RVSB_WORMHOLE; /* There are no slopes inside bridges / tunnels. */ ClrBit(rv->gv_flags, GVF_GOINGUP_BIT); From 78cce81bac41c01c8cdf40549476bde034c603be Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 22 Jun 2017 19:02:46 +0100 Subject: [PATCH 2/3] Prevent AIs/scripts from creating road custom bridge heads. (cherry picked from commit f3dde49ff89027f8ca2ccf74ba7b3e3fef853cc0) --- src/road_cmd.cpp | 9 ++++++--- src/script/api/script_bridge.cpp | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 56f6888197..4105d2f3d0 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -519,6 +519,7 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi * @param p1 bit 0..3 road pieces to build (RoadBits) * bit 4..5 road type * bit 6..7 disallowed directions to toggle + * bit 8 disable custom bridge heads * @param p2 the town that is building the road (0 if not applicable) * @param text unused * @return the cost of this operation or an error @@ -558,6 +559,8 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 DisallowedRoadDirections toggle_drd = Extract(p1); + bool disable_custom_bridge_heads = HasBit(p1, 8); + Slope tileh = GetTileSlope(tile); bool need_to_clear = false; @@ -721,7 +724,7 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 const RoadBits axial_pieces = AxisToRoadBits(DiagDirToAxis(entrance_dir)); existing = GetCustomBridgeHeadRoadBits(tile, rt); - if (!(_settings_game.construction.road_custom_bridge_heads && HasBridgeFlatRamp(tileh, DiagDirToAxis(entrance_dir)))) { + if (!(_settings_game.construction.road_custom_bridge_heads && HasBridgeFlatRamp(tileh, DiagDirToAxis(entrance_dir))) || disable_custom_bridge_heads) { /* Ordinary bridge heads only */ /* Only allow building the outer roadbit, so building long roads stops at existing bridges */ if (MirrorRoadBits(entrance_piece) != pieces) goto do_clear; @@ -955,7 +958,7 @@ static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir) * - p2 = (bit 5) - set road direction * - p2 = (bit 6) - defines two different behaviors for this command: * - 0 = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile - * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts + * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. Disable custom bridge heads. This behavior is used for scripts * @param text unused * @return the cost of this operation or an error */ @@ -1014,7 +1017,7 @@ CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir); } - CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD); + CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits | (is_ai ? 1 << 8 : 0), 0, flags, CMD_BUILD_ROAD); if (ret.Failed()) { last_error = ret; if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) { diff --git a/src/script/api/script_bridge.cpp b/src/script/api/script_bridge.cpp index 45bec466c8..f7465ec718 100644 --- a/src/script/api/script_bridge.cpp +++ b/src/script/api/script_bridge.cpp @@ -113,7 +113,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance) DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_2 = ::ReverseDiagDir(dir_1); - return ScriptObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &::_DoCommandReturnBuildBridge2); + return ScriptObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4) | (1 << 8), 0, CMD_BUILD_ROAD, NULL, &::_DoCommandReturnBuildBridge2); } /* static */ bool ScriptBridge::_BuildBridgeRoad2() @@ -125,7 +125,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance) DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_2 = ::ReverseDiagDir(dir_1); - return ScriptObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD); + return ScriptObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4) | (1 << 8), 0, CMD_BUILD_ROAD); } /* static */ bool ScriptBridge::RemoveBridge(TileIndex tile) From ff6a3ed234a316220470f9c9ffc9f1cf2bd80396 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 25 Apr 2018 18:51:15 +0100 Subject: [PATCH 3/3] Preserve custom bridge head road data when upgrading bridges. Based on commit 301925f948c9b36966c9c668e1476c2485425338 --- src/bridge_map.h | 9 ++++++++- src/tunnelbridge_cmd.cpp | 17 +++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/bridge_map.h b/src/bridge_map.h index 7d8af3a319..9a384ceca7 100644 --- a/src/bridge_map.h +++ b/src/bridge_map.h @@ -147,13 +147,20 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing * @param r the road type of the bridge + * @param upgrade whether the bridge is an upgrade instead of a totally new bridge */ -static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r) +static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r, bool upgrade) { + // Backup custom bridgehead data. + uint custom_bridge_head_backup = GB(_m[t].m2, 0, 8); + MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, 0); SetRoadOwner(t, ROADTYPE_ROAD, owner_road); if (owner_tram != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, owner_tram); SetRoadTypes(t, r); + + // Restore custom bridgehead data if we're upgrading an existing bridge. + if (upgrade) SB(_m[t].m2, 0, 8, custom_bridge_head_backup); } /** diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index a5a6dd83e9..4c7596ad78 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -327,6 +327,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u CommandCost cost(EXPENSES_CONSTRUCTION); Owner owner; bool is_new_owner; + bool is_upgrade = false; if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) && GetOtherBridgeEnd(tile_start) == tile_end && GetTunnelBridgeTransportType(tile_start) == transport_type) { @@ -381,6 +382,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u default: break; } + + is_upgrade = true; } else { /* Build a new bridge. */ @@ -507,18 +510,12 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u if (HasBit(prev_roadtypes, ROADTYPE_ROAD) && GetRoadOwner(tile_start, ROADTYPE_ROAD) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_ROAD); if (HasBit(prev_roadtypes, ROADTYPE_TRAM) && GetRoadOwner(tile_start, ROADTYPE_TRAM) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_TRAM); } - if (c != NULL) { - /* Add all new road types to the company infrastructure counter. */ - RoadType new_rt; - FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ prev_roadtypes) { - /* A full diagonal road tile has two road bits. */ - c->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; - } - } + if (is_upgrade) SubtractRoadTunnelBridgeInfrastructure(tile_start, tile_end); Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(tile_start, ROADTYPE_ROAD) : company; Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(tile_start, ROADTYPE_TRAM) : company; - MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes); - MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes); + MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes, is_upgrade); + MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes, is_upgrade); + AddRoadTunnelBridgeInfrastructure(tile_start, tile_end); break; }