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 | } | | |
---|