From 64c8985cd716d81cdbc065db654d3402b32f4b1f Mon Sep 17 00:00:00 2001 From: HackaLittleBit Date: Sun, 4 Feb 2018 12:46:57 +0000 Subject: [PATCH 1/5] Remove 90 degree comment --- src/lang/english.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 34c266aa01..dc9561ff10 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1254,7 +1254,7 @@ STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Changing STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :Infrastructure maintenance: {STRING2} STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :When enabled, infrastructure causes maintenance costs. The cost grows over-proportional with the network size, thus affecting bigger companies more than smaller ones STR_CONFIG_SETTING_SHIP_COLLISION_AVOIDANCE :Ships avoid collisions: {STRING2} -STR_CONFIG_SETTING_SHIP_COLLISION_AVOIDANCE_HELPTEXT :When enabled, ships try to avoid passing through each other. Requires 90° turns to be forbidden. +STR_CONFIG_SETTING_SHIP_COLLISION_AVOIDANCE_HELPTEXT :When enabled, ships try to avoid passing through each other. The best results are obtained when 90° turns are forbidden. STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS :Airports never expire: {STRING2} STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT :Enabling this setting makes each airport type stay available forever after its introduction From 80500f8f08bea01dda164b41aeca129d8ef3af0f Mon Sep 17 00:00:00 2001 From: HackaLittleBit Date: Sun, 4 Feb 2018 12:47:30 +0000 Subject: [PATCH 2/5] Rework z position --- src/ship_cmd.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 4f95e93255..acf316b1ed 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -513,8 +513,8 @@ static const byte _ship_subcoord[4][6][3] = { struct ShipCollideChecker { TrackBits track_bits; ///< Pathfinder chosen track converted to trackbits, or is v->state of requesting ship. (one bit set) - TileIndex tile; ///< Tile where ship was found, used to determine distance between ships. - int32 z_pos; ///< z_pos of requesting ship. + TileIndex tile; ///< The tile that we really want to check. + Ship *v; ///< Ship we are testing for collision. }; /** Helper function for collision avoidance. */ @@ -529,7 +529,7 @@ static Vehicle *FindShipOnTile(Vehicle *v, void *data) if (bits == TRACK_BIT_HORZ || bits == TRACK_BIT_VERT) return NULL; /* Don't detect ships passing on aquaduct. */ - if (abs(v->z_pos - scc->z_pos) >= 8) return NULL; + if (abs(v->z_pos - scc->v->z_pos) >= 8) return NULL; scc->tile = v->tile; @@ -563,7 +563,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, if (!IsValidTile(tile_plus_two)) tile_plus_two = tile_plus_one; ShipCollideChecker scc; - scc.z_pos = v->z_pos; + scc.v = v; scc.track_bits = track_bits; bool found = HasVehicleOnPos(tile, &scc, FindShipOnTile); From 9326706eb964615ef8683f248c6a1b63733f2fa4 Mon Sep 17 00:00:00 2001 From: HackaLittleBit Date: Sun, 4 Feb 2018 12:47:57 +0000 Subject: [PATCH 3/5] Code cleanup and preparation for ships in wormhole detection --- src/ship_cmd.cpp | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index acf316b1ed..d05f287255 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -512,9 +512,9 @@ static const byte _ship_subcoord[4][6][3] = { /** Temporary data storage for testing collisions. */ struct ShipCollideChecker { - TrackBits track_bits; ///< Pathfinder chosen track converted to trackbits, or is v->state of requesting ship. (one bit set) - TileIndex tile; ///< The tile that we really want to check. - Ship *v; ///< Ship we are testing for collision. + TrackBits track_bits; ///< Pathfinder chosen track converted to trackbits, or is v->state of requesting ship. (one bit set) + TileIndex search_tile; ///< The tile that we really want to check. + Ship *v; ///< Ship we are testing for collision. }; /** Helper function for collision avoidance. */ @@ -531,7 +531,8 @@ static Vehicle *FindShipOnTile(Vehicle *v, void *data) /* Don't detect ships passing on aquaduct. */ if (abs(v->z_pos - scc->v->z_pos) >= 8) return NULL; - scc->tile = v->tile; + /* Only requested tiles are checked. avoid desync. */ + if (TileVirtXY(v->x_pos, v->y_pos) != scc->search_tile) return NULL; return v; } @@ -555,27 +556,34 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, /* Only check for collision when pathfinder did not change direction. * This is done in order to keep ships moving towards the intended target. */ TrackBits combine = (v->state | track_bits); - if (combine != TRACK_BIT_HORZ && combine != TRACK_BIT_VERT && combine != track_bits && v->state != TRACK_BIT_WORMHOLE) return; - - TileIndex tile_plus_one = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); - if (!IsValidTile(tile_plus_one)) tile_plus_one = tile; - TileIndex tile_plus_two = TileAddByDiagDir(tile_plus_one, diagdir); - if (!IsValidTile(tile_plus_two)) tile_plus_two = tile_plus_one; + if (combine != TRACK_BIT_HORZ && combine != TRACK_BIT_VERT && combine != track_bits) return; ShipCollideChecker scc; scc.v = v; + scc.track_bits = track_bits; + scc.search_tile = tile; - scc.track_bits = track_bits; bool found = HasVehicleOnPos(tile, &scc, FindShipOnTile); - scc.track_bits = v->state; - if (!found) found = HasVehicleOnPos(tile_plus_one, &scc, FindShipOnTile); - scc.track_bits = track_bits; - if (!found) found = HasVehicleOnPos(tile_plus_two, &scc, FindShipOnTile); + + if (!found) { + scc.track_bits = v->state; + scc.search_tile = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); + if (!IsValidTile(scc.search_tile)) return; + + found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile); + } + if (!found) { + scc.track_bits = track_bits; + scc.search_tile = TileAddByDiagDir(scc.search_tile, diagdir); + if (!IsValidTile(scc.search_tile)) return; + + found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile); + } if (found) { /* Speed adjustment related to distance. */ - v->cur_speed /= scc.tile == tile ? 8 : 2; + v->cur_speed /= scc.search_tile == tile ? 8 : 2; /* Clean none wanted trackbits, including pathfinder track, TRACK_BIT_WORMHOLE and no 90 degree turns. */ tracks = IsDiagonalTrack(track) ? KillFirstBit(tracks) : (tracks & TRACK_BIT_CROSS); @@ -587,7 +595,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, TileIndex tile_check = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); if (!IsValidTile(tile_check)) continue; - if (HasVehicleOnPos(tile_check, &scc, &FindShipOnTile)) continue; + if (HasVehicleOnPos(tile_check, &scc, FindShipOnTile)) continue; TrackBits bits = GetAvailShipTracks(tile_check, _ship_search_directions[track][diagdir]); if (!IsDiagonalTrack(track)) bits &= TRACK_BIT_CROSS; // No 90 degree turns. From fca03da2bbe9d701a7568585c0f110e5501931d8 Mon Sep 17 00:00:00 2001 From: HackaLittleBit Date: Sun, 4 Feb 2018 12:48:50 +0000 Subject: [PATCH 4/5] Add wormhole ship detection, one tile only! --- src/ship_cmd.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index d05f287255..8a7cd0d358 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -537,6 +537,28 @@ static Vehicle *FindShipOnTile(Vehicle *v, void *data) return v; } +/** + * Adjust speed while on aqueducts. + * @param search_tile Tile that the requesting ship will check, one will be added to look in front of the bow. + * @param ramp Ramp tile from aqueduct. + * @param v Ship that does the request. + * @return Allways false. + */ +static bool HandleSpeedOnAqueduct(Ship *v, TileIndex tile, TileIndex ramp) +{ + ShipCollideChecker scc; + scc.search_tile = tile + TileOffsByDir(v->direction); + scc.v = v; + scc.track_bits = TRACK_BIT_NONE; + + if (IsValidTile(scc.search_tile) && + (HasVehicleOnPos(ramp, &scc, FindShipOnTile) || + HasVehicleOnPos(GetOtherTunnelBridgeEnd(ramp), &scc, FindShipOnTile))) { + v->cur_speed /= 4; + } + return false; +} + /** * If there is imminent collision or worse, direction and speed will be adjusted. * @param tile Tile that the ship is about to enter. @@ -566,6 +588,9 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, bool found = HasVehicleOnPos(tile, &scc, FindShipOnTile); if (!found) { + /* Bridge entrance */ + if (IsBridgeTile(tile) && HandleSpeedOnAqueduct(v, tile, tile)) return; + scc.track_bits = v->state; scc.search_tile = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); if (!IsValidTile(scc.search_tile)) return; @@ -579,7 +604,6 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile); } - if (found) { /* Speed adjustment related to distance. */ @@ -727,12 +751,15 @@ static void ShipController(Ship *v) } else { /* On a bridge */ if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { + if (_settings_game.vehicle.ship_collision_avoidance && gp.new_tile != TileVirtXY(v->x_pos, v->y_pos)) HandleSpeedOnAqueduct(v, gp.new_tile, v->tile); v->x_pos = gp.x; v->y_pos = gp.y; v->UpdatePosition(); if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true); return; } + /* Bridge exit */ + if (_settings_game.vehicle.ship_collision_avoidance && gp.new_tile != TileVirtXY(v->x_pos, v->y_pos)) HandleSpeedOnAqueduct(v, gp.new_tile, v->tile); } /* update image of ship, as well as delta XY */ From 691ce0f1eada867bf9a7f968782952644ccb9e05 Mon Sep 17 00:00:00 2001 From: HackaLittleBit Date: Sun, 4 Feb 2018 12:49:27 +0000 Subject: [PATCH 5/5] An assert could be triggered while looking beyond the map border. This patch fixes that. --- src/ship_cmd.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 8a7cd0d358..5e2974b2f3 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -546,10 +546,14 @@ static Vehicle *FindShipOnTile(Vehicle *v, void *data) */ static bool HandleSpeedOnAqueduct(Ship *v, TileIndex tile, TileIndex ramp) { + TileIndexDiffC ti = TileIndexDiffCByDir(v->direction); + ShipCollideChecker scc; - scc.search_tile = tile + TileOffsByDir(v->direction); scc.v = v; scc.track_bits = TRACK_BIT_NONE; + scc.search_tile = TileAddWrap(tile, ti.x, ti.y); + + if (scc.search_tile == INVALID_TILE) return false; if (IsValidTile(scc.search_tile) && (HasVehicleOnPos(ramp, &scc, FindShipOnTile) || @@ -580,6 +584,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, TrackBits combine = (v->state | track_bits); if (combine != TRACK_BIT_HORZ && combine != TRACK_BIT_VERT && combine != track_bits) return; + TileIndexDiffC ti; ShipCollideChecker scc; scc.v = v; scc.track_bits = track_bits; @@ -592,15 +597,17 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, if (IsBridgeTile(tile) && HandleSpeedOnAqueduct(v, tile, tile)) return; scc.track_bits = v->state; - scc.search_tile = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); - if (!IsValidTile(scc.search_tile)) return; + ti = TileIndexDiffCByDiagDir(_ship_search_directions[track][diagdir]); + scc.search_tile = TileAddWrap(tile, ti.x, ti.y); + if (scc.search_tile == INVALID_TILE) return; found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile); } if (!found) { scc.track_bits = track_bits; - scc.search_tile = TileAddByDiagDir(scc.search_tile, diagdir); - if (!IsValidTile(scc.search_tile)) return; + ti = TileIndexDiffCByDiagDir(diagdir); + scc.search_tile = TileAddWrap(scc.search_tile, ti.x, ti.y); + if (scc.search_tile == INVALID_TILE) return; found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile); } @@ -616,8 +623,9 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks, while (tracks != TRACK_BIT_NONE) { track = RemoveFirstTrack(&tracks); - TileIndex tile_check = TileAddByDiagDir(tile, _ship_search_directions[track][diagdir]); - if (!IsValidTile(tile_check)) continue; + ti = TileIndexDiffCByDiagDir(_ship_search_directions[track][diagdir]); + TileIndex tile_check = TileAddWrap(tile, ti.x, ti.y); + if (tile_check == INVALID_TILE) continue; if (HasVehicleOnPos(tile_check, &scc, FindShipOnTile)) continue;