Loading

Revision differences

Old revision #p5mqfcanmNew revision #pwhdeamuj
1/**  1/**  
2 * Procedure testing if a ship is in (one of) the specified track bits.  2 * Ensure there is no ship on the neighbouring tiles coming into or going
3 * @param v Vehicle to examine.  3 * away from the specified tile.
4 * @param data Pointer to TrackBits.  4 * @param tile the specified tile.
5 * @return \a v if conditions are met, else \c NULL.  5 * @param diag_dir_mask mask containing the diagonal directions to the
   6 *                      neighbouring tiles.
   7 * @return Succeeded command (no neighbouring ship) or failed command (a
   8 *         neighbouring ship is found)
6 */  9 */  
7static Vehicle *EnsureNoShipOnTrackProc(Vehicle *v, void *data)  7CommandCost EnsureNoShipFromDiagDirMask(TileIndex tile, byte diag_dir_mask)
8{  11{  
9    if (v->type != VEH_SHIP) return NULL;  12    /* Get track bits of the specified tile */
   13    TrackBits tile_tb = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0));
10  14  
11    Ship *s = Ship::From(v);  15    if ((tile_tb & TRACK_BIT_ALL) != TRACK_BIT_NONE) {
12    TrackBits tb = *(TrackBits *)data;  16        /* Ships can walk on main tile, so ensure from which provided diagonal directions a neightbouring ship can't be found */
13    if (s->state & tb) return v;  17        for (DiagDirection diag_dir = DIAGDIR_BEGIN; diag_dir != DIAGDIR_END; diag_dir++) {
   18            if (diag_dir_mask & 1 << diag_dir) {
   19                /* Make checks on this diagonal direction */
   20                TileIndex tc = TileAddByDiagDir(tile, diag_dir); // Move into the neighbouring tile
14  21  
15    return NULL;  22                /* Get track bits of the neighbouring tile that can be reached from the main tile */
   23                TrackBits tc_tb = TrackStatusToTrackBits(GetTileTrackStatus(tc, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(DiagdirBetweenTiles(tile, tc));
   24
   25                /* Then also check if there are track bits on the main tile that can be reached from the neighbouring tile */
   26                if (tc_tb && DiagdirReachesTracks(DiagdirBetweenTiles(tc, tile)) & tile_tb) {
   27                    /* We don't check for a ship in the neighbouring ship depots, locks or aqueducts,
   28                     * because we only care about 1-tile depth, and those structures are more than 1-tile wide. */
   29                    if (!IsShipDepotTile(tc) && !(IsTileType(tc, MP_WATER) && IsLock(tc)) &&
   30                            !(IsTileType(tc, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tc) == TRANSPORT_WATER)) {
   31                        /* Check if there are no ships on the track bits of the neighbouring tile */
   32                        if (HasVehicleOnPos(tc, &tc_tb, EnsureNoShipOnTrackProc)) {
   33                            return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
   34                        }
   35                    }
   36                }
   37            }
   38        }
   39    }
   40
   41    return CommandCost();
16} 42}