Loading

Paste #puadexwa4

  1. /**
  2.  * Build a ship depot.
  3.  * @param tile tile where ship depot is built
  4.  * @param flags type of operation
  5.  * @param p1 bit 0 depot orientation (Axis)
  6.  * @param p2 unused
  7.  * @param text unused
  8.  * @return the cost of this operation or an error
  9.  */
  10. CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
  11. {
  12.     Axis axis = Extract<Axis, 0, 1>(p1);
  13.  
  14.     TileIndex tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
  15.  
  16.     if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
  17.         return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER);
  18.     }
  19.  
  20.     if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
  21.  
  22.     if (!IsTileFlat(tile) || !IsTileFlat(tile2)) {
  23.         /* Prevent depots on rapids */
  24.         return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  25.     }
  26.  
  27.     if (!Depot::CanAllocateItem()) return CMD_ERROR;
  28.  
  29.     WaterClass wc1 = GetWaterClass(tile);
  30.     WaterClass wc2 = GetWaterClass(tile2);
  31.     CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_DEPOT_SHIP]);
  32.  
  33.     bool add_cost = !IsWaterTile(tile);
  34.     CommandCost ret = DoCommand(tile, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
  35.     if (ret.Failed()) return ret;
  36.     if (add_cost) {
  37.         cost.AddCost(ret);
  38.     }
  39.     add_cost = !IsWaterTile(tile2);
  40.     ret = DoCommand(tile2, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
  41.     if (ret.Failed()) return ret;
  42.     if (add_cost) {
  43.         cost.AddCost(ret);
  44.     }
  45.  
  46.     byte diag_dir_mask = (axis == AXIS_X) ? (1 << DIAGDIR_SE | 1 << DIAGDIR_NW) : (1 << DIAGDIR_NE | 1 << DIAGDIR_SW);
  47.     ret = EnsureNoShipFromDiagDirByte(tile, diag_dir_mask);
  48.     if (ret.Failed()) return ret;
  49.  
  50.     ret = EnsureNoShipFromDiagDirByte(tile2, diag_dir_mask);
  51.     if (ret.Failed()) return ret;
  52.  
  53. //  DiagDirection dir_rotate = axis == AXIS_X ? DIAGDIR_SE : DIAGDIR_NE;
  54. //  TileIndex tc = tile + (axis == AXIS_X ? TileDiffXY(0, -1) : TileDiffXY(1, 0));
  55. //  ret = EnsureNoShipFromDiagDir(tc, dir_rotate);
  56. //  if (ret.Failed()) return ret;
  57. //
  58. //  tc = tile2 + (axis == AXIS_X ? TileDiffXY(0, -1) : TileDiffXY(1, 0));
  59. //  ret = EnsureNoShipFromDiagDir(tc, dir_rotate);
  60. //  if (ret.Failed()) return ret;
  61. //
  62. //  dir_rotate = ReverseDiagDir(dir_rotate);
  63. //  tc = tile + (axis == AXIS_X ? TileDiffXY(0, 1) : TileDiffXY(-1, 0));
  64. //  ret = EnsureNoShipFromDiagDir(tc, dir_rotate);
  65. //  if (ret.Failed()) return ret;
  66. //
  67. //  tc = tile2 + (axis == AXIS_X ? TileDiffXY(0, 1) : TileDiffXY(-1, 0));
  68. //  ret = EnsureNoShipFromDiagDir(tc, dir_rotate);
  69. //  if (ret.Failed()) return ret;
  70. //
  71.     if (flags & DC_EXEC) {
  72.         Depot *depot = new Depot(tile);
  73.         depot->build_date = _date;
  74.  
  75.         if (wc1 == WATER_CLASS_CANAL || wc2 == WATER_CLASS_CANAL) {
  76.             /* Update infrastructure counts after the unconditional clear earlier. */
  77.             Company::Get(_current_company)->infrastructure.water += wc1 == WATER_CLASS_CANAL && wc2 == WATER_CLASS_CANAL ? 2 : 1;
  78.         }
  79.         Company::Get(_current_company)->infrastructure.water += 2 * LOCK_DEPOT_TILE_FACTOR;
  80.         DirtyCompanyInfrastructureWindows(_current_company);
  81.  
  82.         MakeShipDepot(tile,  _current_company, depot->index, DEPOT_PART_NORTH, axis, wc1);
  83.         MakeShipDepot(tile2, _current_company, depot->index, DEPOT_PART_SOUTH, axis, wc2);
  84.         MarkTileDirtyByTile(tile);
  85.         MarkTileDirtyByTile(tile2);
  86.         MakeDefaultName(depot);
  87.     }
  88.  
  89.     return cost;
  90. }
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /** Temporary data storage for testing track. */
  98. struct ShipTrackChecker {
  99.     TrackBits tb; ///< Tracks to check against.
  100.     int z;            ///< Tile height.
  101. };
  102.  
  103. static Vehicle *NoShipOnTrack(Vehicle *v, void *data)
  104. {
  105.     if (v->type != VEH_SHIP) return NULL;
  106.  
  107.     ShipTrackChecker *stc = (ShipTrackChecker *)data;
  108.     if (v->z_pos > stc->z) return NULL;
  109.  
  110.     if (Ship::From(v)->state & stc->tb) return v;
  111.  
  112.     return NULL;
  113. }
  114.  
  115. CommandCost EnsureNoShipFromDiagDirByte(TileIndex tile, byte diag_dir_byte)
  116. {
  117.     TrackBits tile_tb = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0));
  118.     if ((tile_tb & TRACK_BIT_ALL) != TRACK_BIT_NONE) {
  119.         for (DiagDirection diag_dir = DIAGDIR_BEGIN; diag_dir != DIAGDIR_END; diag_dir++) {
  120.             if (diag_dir_byte & 1 << diag_dir) {
  121.                 TileIndex tc = TileAddByDiagDir(tile, diag_dir);
  122.                 TrackBits tc_tb = TrackStatusToTrackBits(GetTileTrackStatus(tc, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(DiagdirBetweenTiles(tile, tc));
  123.  
  124.                 if (tc_tb && !IsShipDepotTile(tc) && !(IsTileType(tc, MP_WATER) && IsLock(tc)) &&
  125.                         !(IsTileType(tc, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tc) == TRANSPORT_WATER)) {
  126.                     ShipTrackChecker stc;
  127.                     stc.z = GetTileMaxPixelZ(tc);
  128.                     stc.tb = tc_tb;
  129.                     if (HasVehicleOnPos(tc, &stc, NoShipOnTrack)) {
  130.                         return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
  131.                     }
  132.                 }
  133.             }
  134.         }
  135.     }
  136.  
  137.     return CommandCost();
  138. }

Comments