| 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 |
| | |
|---|
| 89 | // return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
| 89 | } |
|---|
| 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 | } | | |
|---|