Loading

Revision differences

Old revision #pvgnf721hNew revision #pm2z02db9
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 */    
10CommandCost 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)) {  1    if (!IsTileFlat(tile_cur)) {  
  2        if (GetTileZ(tile) == 0 && GetTileZ(tile_cur) == 0) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);  
68        int z_tile = GetTileMaxZ(tile);  3        int z_tile = GetTileMaxZ(tile);  
69        int z_tile_cur = GetTileMaxZ(tile_cur);  4        int z_tile_cur = GetTileMaxZ(tile_cur);  
70        bool z = Delta(z_tile_cur, z_tile) == 0;  5        bool z = Delta(z_tile_cur, z_tile) == 0;  
  
82        TileIndex tile_cur_before = coa->first_tile;  17        TileIndex tile_cur_before = coa->first_tile;  
83        coa->first_tile = INVALID_TILE;  18        coa->first_tile = INVALID_TILE;  
84        ret = DoCommand(tile_cur, z ? slope : ComplementSlope(slope), z ? 0 : 1, flags | DC_NO_WATER, CMD_TERRAFORM_LAND);  19        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;  20        coa->first_tile = tile_cur_before;  
87        if (ret.Failed()) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);  21        if (ret.Failed()) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);  
88        cost.AddCost(ret);  22        cost.AddCost(ret);  
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}