Loading

Paste #pvgnf721h

  1. /**
  2.  * Build a dock/haven.
  3.  * @param tile tile where dock will be built
  4.  * @param flags operation to perform
  5.  * @param p1 (bit 0) - allow docks directly adjacent to other docks.
  6.  * @param p2 bit 16-31: station ID to join (NEW_STATION if build new one)
  7.  * @param text unused
  8.  * @return the cost of this operation or an error
  9.  */
  10. CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
  11. {
  12.     StationID station_to_join = GB(p2, 16, 16);
  13.     bool reuse = (station_to_join != NEW_STATION);
  14.     if (!reuse) station_to_join = INVALID_STATION;
  15.     bool distant_join = (station_to_join != INVALID_STATION);
  16.  
  17.     if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
  18.  
  19.     DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile));
  20.     if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  21.     direction = ReverseDiagDir(direction);
  22.  
  23.     /* Docks cannot be placed on rapids */
  24.     if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  25.  
  26.     CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
  27.     if (ret.Failed()) return ret;
  28.  
  29.     if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
  30.  
  31.     CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
  32.     ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  33.     if (ret.Failed()) return ret;
  34.     cost.AddCost(ret);
  35.  
  36.     /* Move to second tile. */
  37.     TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
  38.  
  39.     if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
  40.  
  41. //  if (!HasTileWaterGround(tile_cur)) {
  42. //      return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  43. //  }
  44.  
  45.     WaterClass wc = HasTileWaterGround(tile_cur) ? GetWaterClass(tile_cur) : WATER_CLASS_CANAL;
  46.     Owner oc = HasTileWaterGround(tile_cur) && GetWaterClass(tile_cur) == WATER_CLASS_CANAL ? GetCanalOwner(tile_cur) : _current_company;
  47.     bool river = HasTileCanalOnRiver(tile_cur);
  48.     bool add_cost = !IsWaterTile(tile_cur);
  49.  
  50.     /* At this point we got a tile_cur with no bridge over it. Check for ownership */
  51.     if (IsWaterTile(tile_cur) && IsCanal(tile_cur)) {
  52.         ret = EnsureNoVehicleOnGround(tile_cur);
  53.         if (ret.Failed()) return ret;
  54.         if (oc != OWNER_NONE) {
  55.             ret = CheckTileOwnership(tile_cur);
  56.             if (ret.Failed() && !_settings_game.construction.build_on_competitor_canal) return ret;
  57.         }
  58.     } else {
  59.         ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  60.         if (ret.Failed()) return ret;
  61.         if (add_cost) {
  62.             cost.AddCost(ret);
  63.             if (wc == WATER_CLASS_CANAL) cost.AddCost(_price[PR_BUILD_CANAL]);
  64.         }
  65.     }
  66.  
  67.     if (!IsTileFlat(tile_cur)) {
  68.         int z_tile = GetTileMaxZ(tile);
  69.         int z_tile_cur = GetTileMaxZ(tile_cur);
  70.         bool z = Delta(z_tile_cur, z_tile) == 0;
  71.         Slope slope = GetTileSlope(tile_cur);
  72.  
  73.         /* Mark the tile as already cleared for the terraform command.
  74.         * Do this for all tiles (like trees), not only objects. */
  75.         ClearedObjectArea *coa = FindClearedObject(tile_cur);
  76.         if (coa == NULL) {
  77.             coa = _cleared_object_areas.Append();
  78.             coa->first_tile = tile_cur;
  79.             coa->area = TileArea(tile_cur, 1, 1);
  80.         }
  81.         /* Hide the tile from the terraforming command */
  82.         TileIndex tile_cur_before = coa->first_tile;
  83.         coa->first_tile = INVALID_TILE;
  84.         ret = DoCommand(tile_cur, z ? slope : ComplementSlope(slope), z ? 0 : 1, flags | DC_NO_WATER, CMD_TERRAFORM_LAND);
  85. //      Slope slope_after = GetTileSlope(tile_cur);
  86.         coa->first_tile = tile_cur_before;
  87.         if (ret.Failed()) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  88.         cost.AddCost(ret);
  89. //      return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  90.     }
  91.  
  92.     /* Move to third tile. */
  93.     tile_cur += TileOffsByDiagDir(direction);
  94. //  if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
  95. //      return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
  96. //  }
  97.  
  98.     TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
  99.             _dock_w_chk[direction], _dock_h_chk[direction]);
  100.  
  101.     /* middle */
  102.     Station *st = NULL;
  103.     ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p1, 0), dock_area, &st);
  104.     if (ret.Failed()) return ret;
  105.  
  106.     /* Distant join */
  107.     if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
  108.  
  109.     ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK);
  110.     if (ret.Failed()) return ret;
  111.  
  112.     if (st != NULL && st->dock_tile != INVALID_TILE) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK);
  113.  
  114.     if (flags & DC_EXEC) {
  115.         st->dock_tile = tile;
  116.         st->AddFacility(FACIL_DOCK, tile);
  117.  
  118.         st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY);
  119.  
  120.         if (add_cost && wc == WATER_CLASS_CANAL) Company::Get(st->owner)->infrastructure.water++;
  121.         Company::Get(st->owner)->infrastructure.station += 2;
  122.         DirtyCompanyInfrastructureWindows(st->owner);
  123.  
  124.         MakeDock(tile, st->owner, oc, st->index, direction, wc);
  125.         if (river) SetCanalOnRiver(tile + TileOffsByDiagDir(direction));
  126.         MarkTileDirtyByTile(tile + TileOffsByDiagDir(direction), 0);
  127.  
  128.         st->UpdateVirtCoord();
  129.         UpdateStationAcceptance(st, false);
  130.         st->RecomputeIndustriesNear();
  131.         InvalidateWindowData(WC_SELECT_STATION, 0, 0);
  132.         InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
  133.         SetWindowWidgetDirty(WC_STATION_VIEW, st->index, WID_SV_SHIPS);
  134.     }
  135.  
  136.     return cost;
  137. }

Comments